Merge libffi to upstream commit c82cc159426d8d4402375fa1ae3f045b9cf82e16
From-SVN: r219477
This commit is contained in:
parent
62e22fcb79
commit
b1760f7f91
221 changed files with 23053 additions and 15964 deletions
|
@ -1,3 +1,7 @@
|
|||
2015-01-12 Richard Henderson <rth@redhat.com>
|
||||
|
||||
Merge to upstream commit c82cc159426d8d4402375fa1ae3f045b9cf82e16.
|
||||
|
||||
2014-11-21 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR bootstrap/63784
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
libffi - Copyright (c) 1996-2012 Anthony Green, Red Hat, Inc and others.
|
||||
libffi - Copyright (c) 1996-2014 Anthony Green, Red Hat, Inc and others.
|
||||
See source files for details.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
|
|
@ -1,46 +1,19 @@
|
|||
## Process this with automake to create Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
|
||||
ACLOCAL_AMFLAGS = -I .. -I ../config
|
||||
|
||||
SUBDIRS = include testsuite man
|
||||
|
||||
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \
|
||||
src/aarch64/ffi.c src/aarch64/ffitarget.h \
|
||||
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 src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
|
||||
src/mips/ffitarget.h src/m32r/ffi.c src/m32r/sysv.S \
|
||||
src/m32r/ffitarget.h src/m68k/ffi.c src/m68k/sysv.S \
|
||||
src/m68k/ffitarget.h \
|
||||
src/powerpc/ffi.c src/powerpc/ffi_powerpc.h \
|
||||
src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \
|
||||
src/powerpc/sysv.S src/powerpc/linux64.S \
|
||||
src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S \
|
||||
src/powerpc/asm.h src/powerpc/aix.S src/powerpc/darwin.S \
|
||||
src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \
|
||||
src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \
|
||||
src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \
|
||||
src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h src/sh64/ffi.c \
|
||||
src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S \
|
||||
src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c \
|
||||
src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S \
|
||||
src/x86/win32.S src/x86/darwin.S src/x86/win64.S \
|
||||
src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S \
|
||||
src/x86/ffitarget.h src/pa/ffitarget.h 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/tile/ffi.c \
|
||||
src/tile/ffitarget.h src/tile/tile.S libtool-version \
|
||||
ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4 \
|
||||
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \
|
||||
ChangeLog.libffi ChangeLog.libffi-3.1 \
|
||||
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
|
||||
m4/ltversion.m4 src/debug.c msvcc.sh \
|
||||
generate-darwin-source-and-headers.py \
|
||||
libffi.xcodeproj/project.pbxproj \
|
||||
libtool-ldflags
|
||||
|
||||
# Automake Documentation:
|
||||
# If your package has Texinfo files in many directories, you can use the
|
||||
|
@ -79,7 +52,6 @@ stamp-build-info: doc/libffi.texi $(srcdir)/doc/version.texi doc/$(am__dirstamp)
|
|||
$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)/doc -o doc/libffi.info $(srcdir)/doc/libffi.texi
|
||||
@touch $@
|
||||
|
||||
|
||||
CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) doc/libffi.info
|
||||
MAINTAINERCLEANFILES = $(srcdir)/doc/libffi.info
|
||||
|
||||
|
@ -93,153 +65,147 @@ MAINTAINERCLEANFILES = $(srcdir)/doc/libffi.info
|
|||
# values defined in terms of make variables, as is the case for CC and
|
||||
# friends when we are called from the top level Makefile.
|
||||
AM_MAKEFLAGS = \
|
||||
"AR_FLAGS=$(AR_FLAGS)" \
|
||||
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
|
||||
"CFLAGS=$(CFLAGS)" \
|
||||
"CXXFLAGS=$(CXXFLAGS)" \
|
||||
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
|
||||
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
|
||||
"INSTALL=$(INSTALL)" \
|
||||
"INSTALL_DATA=$(INSTALL_DATA)" \
|
||||
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
|
||||
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
|
||||
"JC1FLAGS=$(JC1FLAGS)" \
|
||||
"LDFLAGS=$(LDFLAGS)" \
|
||||
"LIBCFLAGS=$(LIBCFLAGS)" \
|
||||
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
|
||||
"MAKE=$(MAKE)" \
|
||||
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
"PICFLAG=$(PICFLAG)" \
|
||||
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
|
||||
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
|
||||
"SHELL=$(SHELL)" \
|
||||
"exec_prefix=$(exec_prefix)" \
|
||||
"infodir=$(infodir)" \
|
||||
"libdir=$(libdir)" \
|
||||
"mandir=$(mandir)" \
|
||||
"prefix=$(prefix)" \
|
||||
"AR=$(AR)" \
|
||||
"AS=$(AS)" \
|
||||
"CC=$(CC)" \
|
||||
"CXX=$(CXX)" \
|
||||
"LD=$(LD)" \
|
||||
"NM=$(NM)" \
|
||||
"RANLIB=$(RANLIB)" \
|
||||
"DESTDIR=$(DESTDIR)"
|
||||
'AR_FLAGS=$(AR_FLAGS)' \
|
||||
'CC_FOR_BUILD=$(CC_FOR_BUILD)' \
|
||||
'CFLAGS=$(CFLAGS)' \
|
||||
'CXXFLAGS=$(CXXFLAGS)' \
|
||||
'CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)' \
|
||||
'CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)' \
|
||||
'INSTALL=$(INSTALL)' \
|
||||
'INSTALL_DATA=$(INSTALL_DATA)' \
|
||||
'INSTALL_PROGRAM=$(INSTALL_PROGRAM)' \
|
||||
'INSTALL_SCRIPT=$(INSTALL_SCRIPT)' \
|
||||
'JC1FLAGS=$(JC1FLAGS)' \
|
||||
'LDFLAGS=$(LDFLAGS)' \
|
||||
'LIBCFLAGS=$(LIBCFLAGS)' \
|
||||
'LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)' \
|
||||
'MAKE=$(MAKE)' \
|
||||
'MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)' \
|
||||
'PICFLAG=$(PICFLAG)' \
|
||||
'PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)' \
|
||||
'RUNTESTFLAGS=$(RUNTESTFLAGS)' \
|
||||
'SHELL=$(SHELL)' \
|
||||
'exec_prefix=$(exec_prefix)' \
|
||||
'infodir=$(infodir)' \
|
||||
'libdir=$(libdir)' \
|
||||
'mandir=$(mandir)' \
|
||||
'prefix=$(prefix)' \
|
||||
'AR=$(AR)' \
|
||||
'AS=$(AS)' \
|
||||
'CC=$(CC)' \
|
||||
'CXX=$(CXX)' \
|
||||
'LD=$(LD)' \
|
||||
'NM=$(NM)' \
|
||||
'RANLIB=$(RANLIB)' \
|
||||
'DESTDIR=$(DESTDIR)'
|
||||
|
||||
# Subdir rules rely on $(FLAGS_TO_PASS)
|
||||
FLAGS_TO_PASS = $(AM_MAKEFLAGS)
|
||||
|
||||
MAKEOVERRIDES=
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libffi.pc
|
||||
|
||||
toolexeclib_LTLIBRARIES = libffi.la
|
||||
noinst_LTLIBRARIES = libffi_convenience.la
|
||||
|
||||
libffi_la_SOURCES = src/prep_cif.c src/types.c \
|
||||
src/raw_api.c src/java_raw_api.c src/closures.c
|
||||
|
||||
nodist_libffi_la_SOURCES =
|
||||
|
||||
if FFI_DEBUG
|
||||
nodist_libffi_la_SOURCES += src/debug.c
|
||||
libffi_la_SOURCES += src/debug.c
|
||||
endif
|
||||
|
||||
if MIPS
|
||||
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
|
||||
endif
|
||||
if BFIN
|
||||
nodist_libffi_la_SOURCES += src/bfin/ffi.c src/bfin/sysv.S
|
||||
endif
|
||||
if X86
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
|
||||
endif
|
||||
if X86_FREEBSD
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/freebsd.S
|
||||
endif
|
||||
if X86_WIN32
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S
|
||||
endif
|
||||
if X86_WIN64
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win64.S
|
||||
endif
|
||||
if X86_DARWIN
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
|
||||
endif
|
||||
if SPARC
|
||||
nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
|
||||
endif
|
||||
if ALPHA
|
||||
nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S
|
||||
endif
|
||||
if IA64
|
||||
nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S
|
||||
endif
|
||||
if M32R
|
||||
nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c
|
||||
endif
|
||||
if M68K
|
||||
nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S
|
||||
endif
|
||||
if POWERPC
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
|
||||
endif
|
||||
if POWERPC_AIX
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
|
||||
endif
|
||||
if POWERPC_DARWIN
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
|
||||
endif
|
||||
if POWERPC_FREEBSD
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
|
||||
endif
|
||||
if AARCH64
|
||||
nodist_libffi_la_SOURCES += src/aarch64/sysv.S src/aarch64/ffi.c
|
||||
endif
|
||||
if ARM
|
||||
nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
|
||||
if FFI_EXEC_TRAMPOLINE_TABLE
|
||||
nodist_libffi_la_SOURCES += src/arm/trampoline.S
|
||||
endif
|
||||
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
|
||||
if FRV
|
||||
nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
|
||||
endif
|
||||
if S390
|
||||
nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
|
||||
endif
|
||||
if X86_64
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
|
||||
endif
|
||||
if SH
|
||||
nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c
|
||||
endif
|
||||
if SH64
|
||||
nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
|
||||
endif
|
||||
if PA_LINUX
|
||||
nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
|
||||
endif
|
||||
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
|
||||
noinst_HEADERS = \
|
||||
src/aarch64/ffitarget.h src/aarch64/internal.h \
|
||||
src/alpha/ffitarget.h src/alpha/internal.h \
|
||||
src/arc/ffitarget.h \
|
||||
src/arm/ffitarget.h src/arm/internal.h \
|
||||
src/avr32/ffitarget.h \
|
||||
src/bfin/ffitarget.h \
|
||||
src/cris/ffitarget.h \
|
||||
src/frv/ffitarget.h \
|
||||
src/ia64/ffitarget.h src/ia64/ia64_flags.h \
|
||||
src/m32r/ffitarget.h \
|
||||
src/m68k/ffitarget.h \
|
||||
src/m88k/ffitarget.h \
|
||||
src/metag/ffitarget.h \
|
||||
src/microblaze/ffitarget.h \
|
||||
src/mips/ffitarget.h \
|
||||
src/moxie/ffitarget.h \
|
||||
src/nios2/ffitarget.h \
|
||||
src/or1k/ffitarget.h \
|
||||
src/pa/ffitarget.h \
|
||||
src/powerpc/ffitarget.h src/powerpc/asm.h src/powerpc/ffi_powerpc.h \
|
||||
src/s390/ffitarget.h \
|
||||
src/sh/ffitarget.h \
|
||||
src/sh64/ffitarget.h \
|
||||
src/sparc/ffitarget.h src/sparc/internal.h \
|
||||
src/tile/ffitarget.h \
|
||||
src/vax/ffitarget.h \
|
||||
src/x86/ffitarget.h src/x86/internal.h src/x86/internal64.h \
|
||||
src/xtensa/ffitarget.h \
|
||||
src/dlmalloc.c
|
||||
|
||||
EXTRA_libffi_la_SOURCES = \
|
||||
src/aarch64/ffi.c src/aarch64/sysv.S \
|
||||
src/alpha/ffi.c src/alpha/osf.S \
|
||||
src/arc/ffi.c src/arc/arcompact.S \
|
||||
src/arm/ffi.c src/arm/sysv.S \
|
||||
src/avr32/ffi.c src/avr32/sysv.S \
|
||||
src/bfin/ffi.c src/bfin/sysv.S \
|
||||
src/cris/ffi.c src/cris/sysv.S \
|
||||
src/frv/ffi.c src/frv/eabi.S \
|
||||
src/ia64/ffi.c src/ia64/unix.S \
|
||||
src/m32r/ffi.c src/m32r/sysv.S \
|
||||
src/m68k/ffi.c src/m68k/sysv.S \
|
||||
src/m88k/ffi.c src/m88k/obsd.S \
|
||||
src/metag/ffi.c src/metag/sysv.S \
|
||||
src/microblaze/ffi.c src/microblaze/sysv.S \
|
||||
src/mips/ffi.c src/mips/o32.S src/mips/n32.S \
|
||||
src/moxie/ffi.c src/moxie/eabi.S \
|
||||
src/nios2/ffi.c src/nios2/sysv.S \
|
||||
src/or1k/ffi.c src/or1k/sysv.S \
|
||||
src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \
|
||||
src/powerpc/ffi.c src/powerpc/ffi_sysv.c src/powerpc/ffi_linux64.c \
|
||||
src/powerpc/sysv.S src/powerpc/linux64.S \
|
||||
src/powerpc/linux64_closure.S src/powerpc/ppc_closure.S \
|
||||
src/powerpc/aix.S src/powerpc/darwin.S src/powerpc/aix_closure.S \
|
||||
src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c \
|
||||
src/s390/ffi.c src/s390/sysv.S \
|
||||
src/sh/ffi.c src/sh/sysv.S \
|
||||
src/sh64/ffi.c src/sh64/sysv.S \
|
||||
src/sparc/ffi.c src/sparc/ffi64.c src/sparc/v8.S src/sparc/v9.S \
|
||||
src/tile/ffi.c src/tile/tile.S \
|
||||
src/vax/ffi.c src/vax/elfbsd.S \
|
||||
src/x86/ffi.c src/x86/sysv.S \
|
||||
src/x86/ffiw64.c src/x86/win64.S \
|
||||
src/x86/ffi64.c src/x86/unix64.S \
|
||||
src/x86/darwin64.S src/x86/darwin.S \
|
||||
src/x86/darwin64_c.c src/x86/darwin_c.c \
|
||||
src/xtensa/ffi.c src/xtensa/sysv.S
|
||||
|
||||
TARGET_OBJ = @TARGET_OBJ@
|
||||
libffi_la_LIBADD = $(TARGET_OBJ)
|
||||
libffi_la_DEPENDENCIES = $(TARGET_OBJ)
|
||||
|
||||
libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
|
||||
EXTRA_libffi_convenience_la_SOURCES = $(EXTRA_libffi_la_SOURCES)
|
||||
libffi_convenience_la_LIBADD = $(libffi_la_LIBADD)
|
||||
libffi_convenience_la_DEPENDENCIES = $(libffi_la_DEPENDENCIES)
|
||||
nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
|
||||
|
||||
AM_CFLAGS = -Wall -g -fexceptions
|
||||
|
||||
LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
|
||||
|
||||
libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
|
||||
AM_CFLAGS = -Wall -g -fexceptions
|
||||
if FFI_DEBUG
|
||||
# Build debug. Define FFI_DEBUG on the commandline so that, when building with
|
||||
# MSVC, it can link against the debug CRT.
|
||||
AM_CFLAGS += -DFFI_DEBUG
|
||||
endif
|
||||
|
||||
libffi_la_LDFLAGS = -no-undefined -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
|
||||
|
||||
AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
|
||||
AM_CCASFLAGS = $(AM_CPPFLAGS)
|
||||
|
|
File diff suppressed because it is too large
Load diff
204
libffi/README
204
libffi/README
|
@ -1,8 +1,8 @@
|
|||
Status
|
||||
======
|
||||
|
||||
libffi-3.0.12 was released on XXXXXXX. Check the libffi web page for
|
||||
updates: <URL:http://sourceware.org/libffi/>.
|
||||
libffi-4?? was released on TBD. Check the libffi web
|
||||
page for updates: <URL:http://sourceware.org/libffi/>.
|
||||
|
||||
|
||||
What is libffi?
|
||||
|
@ -43,57 +43,78 @@ Libffi has been ported to many different platforms.
|
|||
For specific configuration details and testing status, please
|
||||
refer to the wiki page here:
|
||||
|
||||
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
|
||||
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.2
|
||||
|
||||
At the time of release, the following basic configurations have been
|
||||
tested:
|
||||
|
||||
|-----------------+------------------|
|
||||
| Architecture | Operating System |
|
||||
|-----------------+------------------|
|
||||
| AArch64 | Linux |
|
||||
| Alpha | Linux |
|
||||
| Alpha | Tru64 |
|
||||
| ARM | Linux |
|
||||
| ARM | iOS |
|
||||
| AVR32 | Linux |
|
||||
| Blackfin | uClinux |
|
||||
| HPPA | HPUX |
|
||||
| IA-64 | Linux |
|
||||
| M68K | FreeMiNT |
|
||||
| M68K | RTEMS |
|
||||
| MIPS | IRIX |
|
||||
| MIPS | Linux |
|
||||
| MIPS | RTEMS |
|
||||
| MIPS64 | Linux |
|
||||
| PowerPC | AMIGA |
|
||||
| PowerPC | Linux |
|
||||
| PowerPC | Mac OSX |
|
||||
| PowerPC | FreeBSD |
|
||||
| PowerPC64 | Linux |
|
||||
| S390 | Linux |
|
||||
| S390X | Linux |
|
||||
| SPARC | Linux |
|
||||
| SPARC | Solaris |
|
||||
| SPARC64 | Linux |
|
||||
| SPARC64 | FreeBSD |
|
||||
| TILE-Gx/TILEPro | Linux |
|
||||
| X86 | FreeBSD |
|
||||
| X86 | Interix |
|
||||
| X86 | kFreeBSD |
|
||||
| X86 | Linux |
|
||||
| X86 | Mac OSX |
|
||||
| X86 | OpenBSD |
|
||||
| X86 | OS/2 |
|
||||
| X86 | Solaris |
|
||||
| X86 | Windows/Cygwin |
|
||||
| X86 | Windows/MingW |
|
||||
| X86-64 | FreeBSD |
|
||||
| X86-64 | Linux |
|
||||
| X86-64 | Linux/x32 |
|
||||
| X86-64 | OpenBSD |
|
||||
| X86-64 | Windows/MingW |
|
||||
|-----------------+------------------|
|
||||
|-----------------+------------------+-------------------------|
|
||||
| Architecture | Operating System | Compiler |
|
||||
|-----------------+------------------+-------------------------|
|
||||
| AArch64 (ARM64) | iOS | Clang |
|
||||
| AArch64 | Linux | GCC |
|
||||
| Alpha | Linux | GCC |
|
||||
| Alpha | Tru64 | GCC |
|
||||
| ARC | Linux | GCC |
|
||||
| ARM | Linux | GCC |
|
||||
| ARM | iOS | GCC |
|
||||
| AVR32 | Linux | GCC |
|
||||
| Blackfin | uClinux | GCC |
|
||||
| HPPA | HPUX | GCC |
|
||||
| IA-64 | Linux | GCC |
|
||||
| M68K | FreeMiNT | GCC |
|
||||
| M68K | Linux | GCC |
|
||||
| M68K | RTEMS | GCC |
|
||||
| M88K | OpenBSD/mvme88k | GCC |
|
||||
| Meta | Linux | GCC |
|
||||
| MicroBlaze | Linux | GCC |
|
||||
| MIPS | IRIX | GCC |
|
||||
| MIPS | Linux | GCC |
|
||||
| MIPS | RTEMS | GCC |
|
||||
| MIPS64 | Linux | GCC |
|
||||
| Moxie | Bare metal | GCC |
|
||||
| Nios II | Linux | GCC |
|
||||
| OpenRISC | Linux | GCC |
|
||||
| PowerPC 32-bit | AIX | IBM XL C |
|
||||
| PowerPC 64-bit | AIX | IBM XL C |
|
||||
| PowerPC | AMIGA | GCC |
|
||||
| PowerPC | Linux | GCC |
|
||||
| PowerPC | Mac OSX | GCC |
|
||||
| PowerPC | FreeBSD | GCC |
|
||||
| PowerPC 64-bit | FreeBSD | GCC |
|
||||
| PowerPC 64-bit | Linux ELFv1 | GCC |
|
||||
| PowerPC 64-bit | Linux ELFv2 | GCC |
|
||||
| S390 | Linux | GCC |
|
||||
| S390X | Linux | GCC |
|
||||
| SPARC | Linux | GCC |
|
||||
| SPARC | Solaris | GCC |
|
||||
| SPARC | Solaris | Oracle Solaris Studio C |
|
||||
| SPARC64 | Linux | GCC |
|
||||
| SPARC64 | FreeBSD | GCC |
|
||||
| SPARC64 | Solaris | Oracle Solaris Studio C |
|
||||
| TILE-Gx/TILEPro | Linux | GCC |
|
||||
| VAX | OpenBSD/vax | GCC |
|
||||
| X86 | FreeBSD | GCC |
|
||||
| X86 | GNU HURD | GCC |
|
||||
| X86 | Interix | GCC |
|
||||
| X86 | kFreeBSD | GCC |
|
||||
| X86 | Linux | GCC |
|
||||
| X86 | Mac OSX | GCC |
|
||||
| X86 | OpenBSD | GCC |
|
||||
| X86 | OS/2 | GCC |
|
||||
| X86 | Solaris | GCC |
|
||||
| X86 | Solaris | Oracle Solaris Studio C |
|
||||
| X86 | Windows/Cygwin | GCC |
|
||||
| X86 | Windows/MingW | GCC |
|
||||
| X86-64 | FreeBSD | GCC |
|
||||
| X86-64 | Linux | GCC |
|
||||
| X86-64 | Linux/x32 | GCC |
|
||||
| X86-64 | OpenBSD | GCC |
|
||||
| X86-64 | Solaris | Oracle Solaris Studio C |
|
||||
| X86-64 | Windows/Cygwin | GCC |
|
||||
| X86-64 | Windows/MingW | GCC |
|
||||
| Xtensa | Linux | GCC |
|
||||
|-----------------+------------------+-------------------------|
|
||||
|
||||
Please send additional platform test results to
|
||||
libffi-discuss@sourceware.org and feel free to update the wiki page
|
||||
|
@ -107,6 +128,9 @@ system. Go to the directory you wish to build libffi in and run the
|
|||
"configure" program found in the root directory of the libffi source
|
||||
distribution.
|
||||
|
||||
If you're building libffi directly from version control, configure won't
|
||||
exist yet; run ./autogen.sh first.
|
||||
|
||||
You may want to tell configure where to install the libffi library and
|
||||
header files. To do that, use the --prefix configure switch. Libffi
|
||||
will install under /usr/local by default.
|
||||
|
@ -124,20 +148,28 @@ It's also possible to build libffi on Windows platforms with
|
|||
Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
|
||||
wrapper script during configuration like so:
|
||||
|
||||
path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
|
||||
path/to/configure CC=path/to/msvcc.sh CXX=path/to/msvcc.sh LD=link CPP="cl -nologo -EP"
|
||||
|
||||
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
|
||||
You may also need to specify --build appropriately. When building with MSVC
|
||||
under a MingW environment, you may need to remove the line in configure
|
||||
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
|
||||
present in MingW, and is not required when using MingW-style paths.)
|
||||
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64" and
|
||||
CXX="path/to/msvcc.sh -m64". You may also need to specify --build
|
||||
appropriately.
|
||||
|
||||
It is also possible to build libffi on Windows platforms with the LLVM
|
||||
project's clang-cl compiler, like below:
|
||||
|
||||
path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP"
|
||||
|
||||
When building with MSVC under a MingW environment, you may need to
|
||||
remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath'
|
||||
command. ('cygpath' is not present in MingW, and is not required when
|
||||
using MingW-style paths.)
|
||||
|
||||
For iOS builds, the 'libffi.xcodeproj' Xcode project is available.
|
||||
|
||||
Configure has many other options. Use "configure --help" to see them all.
|
||||
|
||||
Once configure has finished, type "make". Note that you must be using
|
||||
GNU make. You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
||||
GNU make. You can ftp GNU make from ftp.gnu.org:/pub/gnu/make .
|
||||
|
||||
To ensure that libffi is working as advertised, type "make check".
|
||||
This will require that you have DejaGNU installed.
|
||||
|
@ -148,17 +180,59 @@ To install the library and header files, type "make install".
|
|||
History
|
||||
=======
|
||||
|
||||
See the ChangeLog files for details.
|
||||
See the git log for details at http://github.com/atgreen/libffi.
|
||||
|
||||
3.0.12 XXX-XX-XX
|
||||
4.0 TBD
|
||||
New API in support of GO closures.
|
||||
|
||||
3.2.1 Nov-12-14
|
||||
Build fix for non-iOS AArch64 targets.
|
||||
|
||||
3.2 Nov-11-14
|
||||
Add C99 Complex Type support (currently only supported on
|
||||
s390).
|
||||
Add support for PASCAL and REGISTER calling conventions on x86
|
||||
Windows/Linux.
|
||||
Add OpenRISC and Cygwin-64 support.
|
||||
Bug fixes.
|
||||
|
||||
3.1 May-19-14
|
||||
Add AArch64 (ARM64) iOS support.
|
||||
Add Nios II support.
|
||||
Add m88k and DEC VAX support.
|
||||
Add support for stdcall, thiscall, and fastcall on non-Windows
|
||||
32-bit x86 targets such as Linux.
|
||||
Various Android, MIPS N32, x86, FreeBSD and UltraSPARC IIi
|
||||
fixes.
|
||||
Make the testsuite more robust: eliminate several spurious
|
||||
failures, and respect the $CC and $CXX environment variables.
|
||||
Archive off the manually maintained ChangeLog in favor of git
|
||||
log.
|
||||
|
||||
3.0.13 Mar-17-13
|
||||
Add Meta support.
|
||||
Add missing Moxie bits.
|
||||
Fix stack alignment bug on 32-bit x86.
|
||||
Build fix for m68000 targets.
|
||||
Build fix for soft-float Power targets.
|
||||
Fix the install dir location for some platforms when building
|
||||
with GCC (OS X, Solaris).
|
||||
Fix Cygwin regression.
|
||||
|
||||
3.0.12 Feb-11-13
|
||||
Add Moxie support.
|
||||
Add AArch64 support.
|
||||
Add Blackfin support.
|
||||
Add TILE-Gx/TILEPro support.
|
||||
Add AArch64 support.
|
||||
Add MicroBlaze support.
|
||||
Add Xtensa support.
|
||||
Add support for PaX enabled kernels with MPROTECT.
|
||||
Add support for native vendor compilers on
|
||||
Solaris and AIX.
|
||||
Work around LLVM/GCC interoperability issue on x86_64.
|
||||
|
||||
3.0.11 Apr-11-12
|
||||
Lots of build fixes.
|
||||
Add Amiga newer MacOS support.
|
||||
Add support for variadic functions (ffi_prep_cif_var).
|
||||
Add Linux/x32 support.
|
||||
Add thiscall, fastcall and MSVC cdecl support on Windows.
|
||||
|
@ -167,7 +241,6 @@ See the ChangeLog files for details.
|
|||
Integration with iOS' xcode build tools.
|
||||
Fix Octeon and MC68881 support.
|
||||
Fix code pessimizations.
|
||||
Lots of build fixes.
|
||||
|
||||
3.0.10 Aug-23-11
|
||||
Add support for Apple's iOS.
|
||||
|
@ -311,7 +384,7 @@ See the ChangeLog files for details.
|
|||
Authors & Credits
|
||||
=================
|
||||
|
||||
libffi was originally written by Anthony Green <green@redhat.com>.
|
||||
libffi was originally written by Anthony Green <green@moxielogic.com>.
|
||||
|
||||
The developers of the GNU Compiler Collection project have made
|
||||
innumerable valuable contributions. See the ChangeLog file for
|
||||
|
@ -335,8 +408,13 @@ frv Anthony Green
|
|||
ia64 Hans Boehm
|
||||
m32r Kazuhiro Inaoka
|
||||
m68k Andreas Schwab
|
||||
m88k Miod Vallat
|
||||
microblaze Nathan Rossi
|
||||
mips Anthony Green, Casey Marshall
|
||||
mips64 David Daney
|
||||
moxie Anthony Green
|
||||
nios ii Sandra Loosemore
|
||||
openrisc Sebastian Macke
|
||||
pa Randolph Chung, Dave Anglin, Andreas Tobler
|
||||
powerpc Geoffrey Keating, Andreas Tobler,
|
||||
David Edelsohn, John Hornkvist
|
||||
|
@ -346,8 +424,10 @@ sh Kaz Kojima
|
|||
sh64 Kaz Kojima
|
||||
sparc Anthony Green, Gordon Irlam
|
||||
tile-gx/tilepro Walter Lee
|
||||
vax Miod Vallat
|
||||
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.
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
PLATFORM_IOS=/Developer/Platforms/iPhoneOS.platform/
|
||||
PLATFORM_IOS_SIM=/Developer/Platforms/iPhoneSimulator.platform/
|
||||
SDK_IOS_VERSION="4.2"
|
||||
MIN_IOS_VERSION="3.0"
|
||||
OUTPUT_DIR="universal-ios"
|
||||
|
||||
build_target () {
|
||||
local platform=$1
|
||||
local sdk=$2
|
||||
local arch=$3
|
||||
local triple=$4
|
||||
local builddir=$5
|
||||
|
||||
mkdir -p "${builddir}"
|
||||
pushd "${builddir}"
|
||||
export CC="${platform}"/Developer/usr/bin/gcc-4.2
|
||||
export CFLAGS="-arch ${arch} -isysroot ${sdk} -miphoneos-version-min=${MIN_IOS_VERSION}"
|
||||
../configure --host=${triple} && make
|
||||
popd
|
||||
}
|
||||
|
||||
# Build all targets
|
||||
build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv6 arm-apple-darwin10 armv6-ios
|
||||
build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv7 arm-apple-darwin10 armv7-ios
|
||||
build_target "${PLATFORM_IOS_SIM}" "${PLATFORM_IOS_SIM}/Developer/SDKs/iPhoneSimulator${SDK_IOS_VERSION}.sdk/" i386 i386-apple-darwin10 i386-ios-sim
|
||||
|
||||
# Create universal output directories
|
||||
mkdir -p "${OUTPUT_DIR}"
|
||||
mkdir -p "${OUTPUT_DIR}/include"
|
||||
mkdir -p "${OUTPUT_DIR}/include/armv6"
|
||||
mkdir -p "${OUTPUT_DIR}/include/armv7"
|
||||
mkdir -p "${OUTPUT_DIR}/include/i386"
|
||||
|
||||
# Create the universal binary
|
||||
lipo -create armv6-ios/.libs/libffi.a armv7-ios/.libs/libffi.a i386-ios-sim/.libs/libffi.a -output "${OUTPUT_DIR}/libffi.a"
|
||||
|
||||
# Copy in the headers
|
||||
copy_headers () {
|
||||
local src=$1
|
||||
local dest=$2
|
||||
|
||||
# Fix non-relative header reference
|
||||
sed 's/<ffitarget.h>/"ffitarget.h"/' < "${src}/include/ffi.h" > "${dest}/ffi.h"
|
||||
cp "${src}/include/ffitarget.h" "${dest}"
|
||||
}
|
||||
|
||||
copy_headers armv6-ios "${OUTPUT_DIR}/include/armv6"
|
||||
copy_headers armv7-ios "${OUTPUT_DIR}/include/armv7"
|
||||
copy_headers i386-ios-sim "${OUTPUT_DIR}/include/i386"
|
||||
|
||||
# Create top-level header
|
||||
(
|
||||
cat << EOF
|
||||
#ifdef __arm__
|
||||
#include <arm/arch.h>
|
||||
#ifdef _ARM_ARCH_6
|
||||
#include "include/armv6/ffi.h"
|
||||
#elif _ARM_ARCH_7
|
||||
#include "include/armv7/ffi.h"
|
||||
#endif
|
||||
#elif defined(__i386__)
|
||||
#include "include/i386/ffi.h"
|
||||
#endif
|
||||
EOF
|
||||
) > "${OUTPUT_DIR}/ffi.h"
|
4790
libffi/configure
vendored
4790
libffi/configure
vendored
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,7 @@ dnl Process this with autoconf to create configure
|
|||
|
||||
AC_PREREQ(2.64)
|
||||
|
||||
AC_INIT([libffi], [3.0.11], [http://gcc.gnu.org/bugs.html])
|
||||
AC_INIT([libffi], [3.99999], [http://github.com/atgreen/libffi/issues])
|
||||
AC_CONFIG_HEADERS([fficonfig.h])
|
||||
|
||||
AM_ENABLE_MULTILIB(, ..)
|
||||
|
@ -10,8 +10,6 @@ AM_ENABLE_MULTILIB(, ..)
|
|||
AC_CANONICAL_SYSTEM
|
||||
target_alias=${target_alias-$host_alias}
|
||||
|
||||
. ${srcdir}/configure.host
|
||||
|
||||
AM_INIT_AUTOMAKE([no-dist])
|
||||
|
||||
# See if makeinfo has been installed and is modern enough
|
||||
|
@ -43,10 +41,16 @@ AM_CONDITIONAL(GENINSRC, test "$enable_generated_files_in_srcdir" = yes)
|
|||
# We must force CC to /not/ be precious variables; otherwise
|
||||
# the wrong, non-multilib-adjusted value will be used in multilibs.
|
||||
# As a side effect, we have to subst CFLAGS ourselves.
|
||||
# Also save and restore CFLAGS, since AC_PROG_CC will come up with
|
||||
# defaults of its own if none are provided.
|
||||
|
||||
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
|
||||
m4_define([_AC_ARG_VAR_PRECIOUS],[])
|
||||
save_CFLAGS=$CFLAGS
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
CFLAGS=$save_CFLAGS
|
||||
m4_undefine([_AC_ARG_VAR_PRECIOUS])
|
||||
m4_rename_force([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
|
@ -55,10 +59,13 @@ AM_PROG_AS
|
|||
AM_PROG_CC_C_O
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
# Test for 64-bit build.
|
||||
AC_CHECK_SIZEOF([size_t])
|
||||
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_CHECK_HEADERS(sys/mman.h)
|
||||
AC_CHECK_FUNCS(mmap)
|
||||
AC_CHECK_FUNCS([mmap mkostemp])
|
||||
AC_FUNC_MMAP_BLACKLIST
|
||||
|
||||
dnl The -no-testsuite modules omit the test subdir.
|
||||
|
@ -66,205 +73,15 @@ AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
|
|||
|
||||
TARGETDIR="unknown"
|
||||
HAVE_LONG_DOUBLE_VARIANT=0
|
||||
case "$host" in
|
||||
aarch64*-*-*)
|
||||
TARGET=AARCH64; TARGETDIR=aarch64
|
||||
;;
|
||||
|
||||
alpha*-*-*)
|
||||
TARGET=ALPHA; TARGETDIR=alpha;
|
||||
# Support 128-bit long double, changeable via command-line switch.
|
||||
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
|
||||
;;
|
||||
. ${srcdir}/configure.host
|
||||
|
||||
arm*-*-*)
|
||||
TARGET=ARM; TARGETDIR=arm
|
||||
;;
|
||||
|
||||
amd64-*-freebsd* | amd64-*-openbsd*)
|
||||
TARGET=X86_64; TARGETDIR=x86
|
||||
;;
|
||||
|
||||
amd64-*-freebsd*)
|
||||
TARGET=X86_64; TARGETDIR=x86
|
||||
;;
|
||||
|
||||
avr32*-*-*)
|
||||
TARGET=AVR32; TARGETDIR=avr32
|
||||
;;
|
||||
|
||||
bfin*)
|
||||
TARGET=BFIN; TARGETDIR=bfin
|
||||
;;
|
||||
|
||||
cris-*-*)
|
||||
TARGET=LIBFFI_CRIS; TARGETDIR=cris
|
||||
;;
|
||||
|
||||
frv-*-*)
|
||||
TARGET=FRV; TARGETDIR=frv
|
||||
;;
|
||||
|
||||
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
|
||||
TARGET=PA_LINUX; TARGETDIR=pa
|
||||
;;
|
||||
hppa*64-*-hpux*)
|
||||
TARGET=PA64_HPUX; TARGETDIR=pa
|
||||
;;
|
||||
hppa*-*-hpux*)
|
||||
TARGET=PA_HPUX; TARGETDIR=pa
|
||||
;;
|
||||
|
||||
i?86-*-freebsd* | i?86-*-openbsd*)
|
||||
TARGET=X86_FREEBSD; TARGETDIR=x86
|
||||
;;
|
||||
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
|
||||
TARGET=X86_WIN32; TARGETDIR=x86
|
||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
||||
# We must also check with_cross_host to decide if this is a native
|
||||
# or cross-build and select where to install dlls appropriately.
|
||||
if test -n "$with_cross_host" &&
|
||||
test x"$with_cross_host" != x"no"; then
|
||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
||||
else
|
||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
||||
fi
|
||||
;;
|
||||
i?86-*-darwin*)
|
||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
||||
;;
|
||||
i?86-*-solaris2.1[[0-9]]*)
|
||||
TARGET=X86_64; TARGETDIR=x86
|
||||
;;
|
||||
i?86-*-*)
|
||||
TARGET=X86_64; TARGETDIR=x86
|
||||
;;
|
||||
|
||||
ia64*-*-*)
|
||||
TARGET=IA64; TARGETDIR=ia64
|
||||
;;
|
||||
|
||||
m32r*-*-*)
|
||||
TARGET=M32R; TARGETDIR=m32r
|
||||
;;
|
||||
|
||||
m68k-*-*)
|
||||
TARGET=M68K; TARGETDIR=m68k
|
||||
;;
|
||||
|
||||
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
|
||||
TARGET=MIPS; TARGETDIR=mips
|
||||
;;
|
||||
mips*-*-linux* | mips*-*-openbsd*)
|
||||
# Support 128-bit long double for NewABI.
|
||||
HAVE_LONG_DOUBLE='defined(__mips64)'
|
||||
TARGET=MIPS; TARGETDIR=mips
|
||||
;;
|
||||
|
||||
powerpc*-*-linux* | powerpc-*-sysv*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
HAVE_LONG_DOUBLE_VARIANT=1
|
||||
;;
|
||||
powerpc-*-amigaos*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-beos*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-darwin* | powerpc64-*-darwin*)
|
||||
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-aix* | rs6000-*-aix*)
|
||||
TARGET=POWERPC_AIX; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-freebsd* | powerpc-*-openbsd*)
|
||||
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
|
||||
HAVE_LONG_DOUBLE_VARIANT=1
|
||||
;;
|
||||
powerpc64-*-freebsd*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc*-*-rtems*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
|
||||
s390-*-* | s390x-*-*)
|
||||
TARGET=S390; TARGETDIR=s390
|
||||
;;
|
||||
|
||||
sh-*-* | sh[[34]]*-*-*)
|
||||
TARGET=SH; TARGETDIR=sh
|
||||
;;
|
||||
sh64-*-* | sh5*-*-*)
|
||||
TARGET=SH64; TARGETDIR=sh64
|
||||
;;
|
||||
|
||||
sparc*-*-*)
|
||||
TARGET=SPARC; TARGETDIR=sparc
|
||||
;;
|
||||
|
||||
tile*-*)
|
||||
TARGET=TILE; TARGETDIR=tile
|
||||
;;
|
||||
|
||||
x86_64-*-darwin*)
|
||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
||||
;;
|
||||
|
||||
x86_64-*-cygwin* | x86_64-*-mingw*)
|
||||
TARGET=X86_WIN64; TARGETDIR=x86
|
||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
||||
# We must also check with_cross_host to decide if this is a native
|
||||
# or cross-build and select where to install dlls appropriately.
|
||||
if test -n "$with_cross_host" &&
|
||||
test x"$with_cross_host" != x"no"; then
|
||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
||||
else
|
||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
||||
fi
|
||||
;;
|
||||
|
||||
x86_64-*-*)
|
||||
TARGET=X86_64; TARGETDIR=x86
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST(AM_RUNTESTFLAGS)
|
||||
AC_SUBST(AM_LTLDFLAGS)
|
||||
|
||||
if test $TARGETDIR = unknown; then
|
||||
if test -n "${UNSUPPORTED}"; then
|
||||
AC_MSG_ERROR(["libffi has not been ported to $host."])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
|
||||
AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN)
|
||||
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
||||
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
||||
AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
|
||||
AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
|
||||
AM_CONDITIONAL(X86_WIN64, test x$TARGET = xX86_WIN64)
|
||||
AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
|
||||
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
||||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
||||
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
|
||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
||||
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(AARCH64, test x$TARGET = xAARCH64)
|
||||
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)
|
||||
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
|
||||
AM_CONDITIONAL(SH, test x$TARGET = xSH)
|
||||
AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
|
||||
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_SUBST(AM_RUNTESTFLAGS)
|
||||
AC_SUBST(AM_LTLDFLAGS)
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_FUNCS(memcpy)
|
||||
|
@ -295,15 +112,6 @@ AC_C_BIGENDIAN
|
|||
|
||||
GCC_AS_CFI_PSEUDO_OP
|
||||
|
||||
AC_CACHE_CHECK([if compiler supports -Qunused-arguments],
|
||||
[libffi_cv_c_unused_arguments],
|
||||
[CFLAGS_hold=$CFLAGS
|
||||
CFLAGS="$CFLAGS -Qunused-arguments"
|
||||
AC_COMPILE_IFELSE([[int i;]],
|
||||
[libffi_cv_c_unused_arguments=yes],
|
||||
[libffi_cv_c_unused_arguments=no])
|
||||
CFLAGS=$CFLAGS_hold])
|
||||
|
||||
if test x$TARGET = xSPARC; then
|
||||
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
|
||||
libffi_cv_as_sparc_ua_pcrel, [
|
||||
|
@ -325,7 +133,7 @@ if test x$TARGET = xSPARC; then
|
|||
libffi_cv_as_register_pseudo_op, [
|
||||
libffi_cv_as_register_pseudo_op=unknown
|
||||
# Check if we have .register
|
||||
AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
|
||||
AC_TRY_COMPILE(,[asm (".register %g2, #scratch");],
|
||||
[libffi_cv_as_register_pseudo_op=yes],
|
||||
[libffi_cv_as_register_pseudo_op=no])
|
||||
])
|
||||
|
@ -338,16 +146,11 @@ fi
|
|||
if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
|
||||
AC_CACHE_CHECK([assembler supports pc related relocs],
|
||||
libffi_cv_as_x86_pcrel, [
|
||||
libffi_cv_as_x86_pcrel=yes
|
||||
libffi_cv_as_x86_pcrel=no
|
||||
echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
|
||||
CFLAGS_hold=$CFLAGS
|
||||
if test "$libffi_cv_c_unused_arguments" = yes; then
|
||||
CFLAGS="$CFLAGS -Qunused-arguments"
|
||||
if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then
|
||||
libffi_cv_as_x86_pcrel=yes
|
||||
fi
|
||||
if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
|
||||
libffi_cv_as_x86_pcrel=no
|
||||
fi
|
||||
CFLAGS=$CFLAGS_hold
|
||||
])
|
||||
if test "x$libffi_cv_as_x86_pcrel" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_X86_PCREL, 1,
|
||||
|
@ -358,7 +161,7 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64
|
|||
libffi_cv_as_ascii_pseudo_op, [
|
||||
libffi_cv_as_ascii_pseudo_op=unknown
|
||||
# Check if we have .ascii
|
||||
AC_TRY_COMPILE([asm (".ascii \\"string\\"");],,
|
||||
AC_TRY_COMPILE(,[asm (".ascii \\"string\\"");],
|
||||
[libffi_cv_as_ascii_pseudo_op=yes],
|
||||
[libffi_cv_as_ascii_pseudo_op=no])
|
||||
])
|
||||
|
@ -371,7 +174,7 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64
|
|||
libffi_cv_as_string_pseudo_op, [
|
||||
libffi_cv_as_string_pseudo_op=unknown
|
||||
# Check if we have .string
|
||||
AC_TRY_COMPILE([asm (".string \\"string\\"");],,
|
||||
AC_TRY_COMPILE(,[asm (".string \\"string\\"");],
|
||||
[libffi_cv_as_string_pseudo_op=yes],
|
||||
[libffi_cv_as_string_pseudo_op=no])
|
||||
])
|
||||
|
@ -381,6 +184,23 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64
|
|||
fi
|
||||
fi
|
||||
|
||||
if test x$TARGET = xS390; then
|
||||
AC_CACHE_CHECK([compiler uses zarch features],
|
||||
libffi_cv_as_s390_zarch, [
|
||||
libffi_cv_as_s390_zarch=no
|
||||
echo 'void foo(void) { bar(); bar(); }' > conftest.c
|
||||
if $CC $CFLAGS -S conftest.c > /dev/null 2>&1; then
|
||||
if grep -q brasl conftest.s; then
|
||||
libffi_cv_as_s390_zarch=yes
|
||||
fi
|
||||
fi
|
||||
])
|
||||
if test "x$libffi_cv_as_s390_zarch" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_S390_ZARCH, 1,
|
||||
[Define if the compiler uses zarch features.])
|
||||
fi
|
||||
fi
|
||||
|
||||
# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
|
||||
AC_ARG_ENABLE(pax_emutramp,
|
||||
[ --enable-pax_emutramp enable pax emulated trampolines, for we can't use PROT_EXEC],
|
||||
|
@ -407,18 +227,29 @@ AM_CONDITIONAL(FFI_EXEC_TRAMPOLINE_TABLE, test x$FFI_EXEC_TRAMPOLINE_TABLE = x1)
|
|||
AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE)
|
||||
|
||||
if test x$TARGET = xX86_64; then
|
||||
AC_CACHE_CHECK([assembler supports unwind section type],
|
||||
AC_CACHE_CHECK([toolchain supports unwind section type],
|
||||
libffi_cv_as_x86_64_unwind_section_type, [
|
||||
libffi_cv_as_x86_64_unwind_section_type=yes
|
||||
echo '.section .eh_frame,"a",@unwind' > conftest.s
|
||||
CFLAGS_hold=$CFLAGS
|
||||
if test "$libffi_cv_c_unused_arguments" = yes; then
|
||||
CFLAGS="$CFLAGS -Qunused-arguments"
|
||||
cat > conftest1.s << EOF
|
||||
.text
|
||||
.globl foo
|
||||
foo:
|
||||
jmp bar
|
||||
.section .eh_frame,"a",@unwind
|
||||
bar:
|
||||
EOF
|
||||
|
||||
cat > conftest2.c << EOF
|
||||
extern void foo();
|
||||
int main(){foo();}
|
||||
EOF
|
||||
|
||||
libffi_cv_as_x86_64_unwind_section_type=no
|
||||
# we ensure that we can compile _and_ link an assembly file containing an @unwind section
|
||||
# since the compiler can support it and not the linker (ie old binutils)
|
||||
if $CC -Wa,--fatal-warnings $CFLAGS -c conftest1.s > /dev/null 2>&1 && \
|
||||
$CC conftest2.c conftest1.o > /dev/null 2>&1 ; then
|
||||
libffi_cv_as_x86_64_unwind_section_type=yes
|
||||
fi
|
||||
if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
|
||||
libffi_cv_as_x86_64_unwind_section_type=no
|
||||
fi
|
||||
CFLAGS=$CFLAGS_hold
|
||||
])
|
||||
if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
|
||||
|
@ -431,13 +262,16 @@ if test "x$GCC" = "xyes"; then
|
|||
libffi_cv_ro_eh_frame, [
|
||||
libffi_cv_ro_eh_frame=no
|
||||
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
|
||||
if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
|
||||
if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
|
||||
libffi_cv_ro_eh_frame=yes
|
||||
elif grep '.section.*eh_frame.*#alloc' conftest.c \
|
||||
| grep -v '#write' > /dev/null; then
|
||||
libffi_cv_ro_eh_frame=yes
|
||||
fi
|
||||
if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then
|
||||
objdump -h conftest.o > conftest.dump 2>&1
|
||||
libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1`
|
||||
if test "x$libffi_eh_frame_line" != "x"; then
|
||||
libffi_test_line=`expr $libffi_eh_frame_line + 1`p
|
||||
sed -n $libffi_test_line conftest.dump > conftest.line
|
||||
if grep READONLY conftest.line > /dev/null; then
|
||||
libffi_cv_ro_eh_frame=yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
rm -f conftest.*
|
||||
])
|
||||
|
@ -487,6 +321,14 @@ AH_BOTTOM([
|
|||
AC_SUBST(TARGET)
|
||||
AC_SUBST(TARGETDIR)
|
||||
|
||||
changequote(<,>)
|
||||
TARGET_OBJ=
|
||||
for i in $SOURCES; do
|
||||
TARGET_OBJ="${TARGET_OBJ} src/${TARGETDIR}/"`echo $i | sed 's/[cS]$/lo/'`
|
||||
done
|
||||
changequote([,])
|
||||
AC_SUBST(TARGET_OBJ)
|
||||
|
||||
AC_SUBST(SHELL)
|
||||
|
||||
AC_ARG_ENABLE(debug,
|
||||
|
@ -499,13 +341,14 @@ AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
|
|||
AC_ARG_ENABLE(structs,
|
||||
[ --disable-structs omit code for struct support],
|
||||
if test "$enable_structs" = "no"; then
|
||||
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
|
||||
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this if you do not want support for aggregate types.])
|
||||
fi)
|
||||
AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
|
||||
|
||||
AC_ARG_ENABLE(raw-api,
|
||||
[ --disable-raw-api make the raw api unavailable],
|
||||
if test "$enable_raw_api" = "no"; then
|
||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
|
||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this if you do not want support for the raw API.])
|
||||
fi)
|
||||
|
||||
AC_ARG_ENABLE(purify-safety,
|
||||
|
@ -544,6 +387,6 @@ test -d src/$TARGETDIR || mkdir src/$TARGETDIR
|
|||
|
||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
||||
|
||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile)
|
||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
|
||||
|
||||
AC_OUTPUT
|
||||
|
|
|
@ -1,11 +1,265 @@
|
|||
# configure.host
|
||||
#
|
||||
# This shell script handles all host based configuration for libffi.
|
||||
#
|
||||
#
|
||||
|
||||
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
|
||||
# Most of the time we can define all the variables all at once...
|
||||
case "${host}" in
|
||||
frv*-elf)
|
||||
LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/
|
||||
;;
|
||||
aarch64*-*-*)
|
||||
TARGET=AARCH64; TARGETDIR=aarch64
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
alpha*-*-*)
|
||||
TARGET=ALPHA; TARGETDIR=alpha;
|
||||
# Support 128-bit long double, changeable via command-line switch.
|
||||
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
|
||||
SOURCES="ffi.c osf.S"
|
||||
;;
|
||||
|
||||
arc*-*-*)
|
||||
TARGET=ARC; TARGETDIR=arc
|
||||
SOURCES="ffi.c arcompact.S"
|
||||
;;
|
||||
|
||||
arm*-*-*)
|
||||
TARGET=ARM; TARGETDIR=arm
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
avr32*-*-*)
|
||||
TARGET=AVR32; TARGETDIR=avr32
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
bfin*)
|
||||
TARGET=BFIN; TARGETDIR=bfin
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
cris-*-*)
|
||||
TARGET=LIBFFI_CRIS; TARGETDIR=cris
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
frv-*-*)
|
||||
TARGET=FRV; TARGETDIR=frv
|
||||
SOURCES="ffi.c eabi.S"
|
||||
;;
|
||||
|
||||
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
|
||||
TARGET=PA_LINUX; TARGETDIR=pa
|
||||
SOURCES="ffi.c linux.S"
|
||||
;;
|
||||
hppa*64-*-hpux*)
|
||||
TARGET=PA64_HPUX; TARGETDIR=pa
|
||||
;;
|
||||
hppa*-*-hpux*)
|
||||
TARGET=PA_HPUX; TARGETDIR=pa
|
||||
SOURCES="ffi.c hpux32.S"
|
||||
;;
|
||||
|
||||
i?86-*-freebsd* | i?86-*-openbsd*)
|
||||
TARGET=X86_FREEBSD; TARGETDIR=x86
|
||||
;;
|
||||
|
||||
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix* \
|
||||
| x86_64-*-cygwin* | x86_64-*-mingw*)
|
||||
TARGETDIR=x86
|
||||
if test $ac_cv_sizeof_size_t = 4; then
|
||||
TARGET=X86_WIN32
|
||||
else
|
||||
TARGET=X86_WIN64
|
||||
fi
|
||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
||||
# We must also check with_cross_host to decide if this is a native
|
||||
# or cross-build and select where to install dlls appropriately.
|
||||
if test -n "$with_cross_host" &&
|
||||
test x"$with_cross_host" != x"no"; then
|
||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
||||
else
|
||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
||||
fi
|
||||
;;
|
||||
|
||||
i?86-*-darwin* | x86_64-*-darwin*)
|
||||
TARGETDIR=x86
|
||||
if test $ac_cv_sizeof_size_t = 4; then
|
||||
TARGET=X86_DARWIN
|
||||
else
|
||||
TARGET=X86_64_DARWIN
|
||||
fi
|
||||
;;
|
||||
|
||||
i?86-*-* | x86_64-*-* | amd64-*)
|
||||
TARGETDIR=x86
|
||||
if test $ac_cv_sizeof_size_t = 4; then
|
||||
case "$host" in
|
||||
*-gnux32)
|
||||
TARGET=X86_64
|
||||
;;
|
||||
*)
|
||||
TARGET=X86
|
||||
;;
|
||||
esac
|
||||
else
|
||||
TARGET=X86_64;
|
||||
fi
|
||||
;;
|
||||
|
||||
ia64*-*-*)
|
||||
TARGET=IA64; TARGETDIR=ia64
|
||||
SOURCES="ffi.c unix.S"
|
||||
;;
|
||||
|
||||
m32r*-*-*)
|
||||
TARGET=M32R; TARGETDIR=m32r
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
m68k-*-*)
|
||||
TARGET=M68K; TARGETDIR=m68k
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
m88k-*-*)
|
||||
TARGET=M88K; TARGETDIR=m88k
|
||||
SOURCES="ffi.c obsd.S"
|
||||
;;
|
||||
|
||||
microblaze*-*-*)
|
||||
TARGET=MICROBLAZE; TARGETDIR=microblaze
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
moxie-*-*)
|
||||
TARGET=MOXIE; TARGETDIR=moxie
|
||||
SOURCES="ffi.c eabi.S"
|
||||
;;
|
||||
|
||||
metag-*-*)
|
||||
TARGET=METAG; TARGETDIR=metag
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
|
||||
TARGET=MIPS; TARGETDIR=mips
|
||||
;;
|
||||
mips*-*linux* | mips*-*-openbsd*)
|
||||
# Support 128-bit long double for NewABI.
|
||||
HAVE_LONG_DOUBLE='defined(__mips64)'
|
||||
TARGET=MIPS; TARGETDIR=mips
|
||||
;;
|
||||
|
||||
nios2*-linux*)
|
||||
TARGET=NIOS2; TARGETDIR=nios2
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
or1k*-linux*)
|
||||
TARGET=OR1K; TARGETDIR=or1k
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
powerpc*-*-linux* | powerpc-*-sysv*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
HAVE_LONG_DOUBLE_VARIANT=1
|
||||
;;
|
||||
powerpc-*-amigaos*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-beos*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-darwin* | powerpc64-*-darwin*)
|
||||
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-aix* | rs6000-*-aix*)
|
||||
TARGET=POWERPC_AIX; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-freebsd* | powerpc-*-openbsd*)
|
||||
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
|
||||
HAVE_LONG_DOUBLE_VARIANT=1
|
||||
;;
|
||||
powerpc64-*-freebsd*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc*-*-rtems*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
|
||||
s390-*-* | s390x-*-*)
|
||||
TARGET=S390; TARGETDIR=s390
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
sh-*-* | sh[[34]]*-*-*)
|
||||
TARGET=SH; TARGETDIR=sh
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
sh64-*-* | sh5*-*-*)
|
||||
TARGET=SH64; TARGETDIR=sh64
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
|
||||
sparc*-*-*)
|
||||
TARGET=SPARC; TARGETDIR=sparc
|
||||
SOURCES="ffi.c ffi64.c v8.S v9.S"
|
||||
;;
|
||||
|
||||
tile*-*)
|
||||
TARGET=TILE; TARGETDIR=tile
|
||||
SOURCES="ffi.c tile.S"
|
||||
;;
|
||||
|
||||
vax-*-*)
|
||||
TARGET=VAX; TARGETDIR=vax
|
||||
SOURCES="ffi.c elfbsd.S"
|
||||
;;
|
||||
|
||||
xtensa*-*)
|
||||
TARGET=XTENSA; TARGETDIR=xtensa
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
esac
|
||||
|
||||
# ... but some of the cases above share configury.
|
||||
case "${TARGET}" in
|
||||
MIPS)
|
||||
SOURCES="ffi.c o32.S n32.S"
|
||||
;;
|
||||
POWERPC)
|
||||
SOURCES="ffi.c ffi_sysv.c ffi_linux64.c sysv.S ppc_closure.S"
|
||||
SOURCES="${SOURCES} linux64.S linux64_closure.S"
|
||||
;;
|
||||
POWERPC_AIX)
|
||||
SOURCES="ffi_darwin.c aix.S aix_closure.S"
|
||||
;;
|
||||
POWERPC_DARWIN)
|
||||
SOURCES="ffi_darwin.c darwin.S darwin_closure.S"
|
||||
;;
|
||||
POWERPC_FREEBSD)
|
||||
SOURCES="ffi.c ffi_sysv.c sysv.S ppc_closure.S"
|
||||
;;
|
||||
X86 | X86_FREEBSD | X86_WIN32)
|
||||
SOURCES="ffi.c sysv.S"
|
||||
;;
|
||||
X86_64)
|
||||
SOURCES="ffi64.c unix64.S"
|
||||
;;
|
||||
X86_WIN64)
|
||||
SOURCES="ffiw64.c win64.S"
|
||||
;;
|
||||
X86_DARWIN)
|
||||
SOURCES="darwin_c.c darwin.S"
|
||||
;;
|
||||
X86_64_DARWIN)
|
||||
SOURCES="darwin64_c.c darwin64.S"
|
||||
;;
|
||||
esac
|
||||
|
||||
# If we failed to configure SOURCES, we can't do anything.
|
||||
if test -z "${SOURCES}"; then
|
||||
UNSUPPORTED=1
|
||||
fi
|
||||
|
|
|
@ -63,14 +63,14 @@ section entitled ``GNU General Public License''.
|
|||
@node Introduction
|
||||
@chapter What is libffi?
|
||||
|
||||
Compilers for high-level languages generate code that follow certain
|
||||
Compilers for high level languages generate code that follow certain
|
||||
conventions. These conventions are necessary, in part, for separate
|
||||
compilation to work. One such convention is the @dfn{calling
|
||||
convention}. The calling convention is a set of assumptions made by
|
||||
the compiler about where function arguments will be found on entry to
|
||||
a function. A calling convention also specifies where the return
|
||||
value for a function is found. The calling convention is part of
|
||||
what is called the @dfn{ABI} or @dfn{Application Binary Interface}.
|
||||
value for a function is found. The calling convention is also
|
||||
sometimes called the @dfn{ABI} or @dfn{Application Binary Interface}.
|
||||
@cindex calling convention
|
||||
@cindex ABI
|
||||
@cindex Application Binary Interface
|
||||
|
@ -247,6 +247,8 @@ int main()
|
|||
* Primitive Types:: Built-in types.
|
||||
* Structures:: Structure types.
|
||||
* Type Example:: Structure type example.
|
||||
* Complex:: Complex types.
|
||||
* Complex Type Example:: Complex type example.
|
||||
@end menu
|
||||
|
||||
@node Primitive Types
|
||||
|
@ -345,6 +347,20 @@ On other platforms, it is not.
|
|||
@tindex ffi_type_pointer
|
||||
A generic @code{void *} pointer. You should use this for all
|
||||
pointers, regardless of their real type.
|
||||
|
||||
@item ffi_type_complex_float
|
||||
@tindex ffi_type_complex_float
|
||||
The C @code{_Complex float} type.
|
||||
|
||||
@item ffi_type_complex_double
|
||||
@tindex ffi_type_complex_double
|
||||
The C @code{_Complex double} type.
|
||||
|
||||
@item ffi_type_complex_longdouble
|
||||
@tindex ffi_type_complex_longdouble
|
||||
The C @code{_Complex long double} type.
|
||||
On platforms that have a C @code{long double} type, this is defined.
|
||||
On other platforms, it is not.
|
||||
@end table
|
||||
|
||||
Each of these is of type @code{ffi_type}, so you must take the address
|
||||
|
@ -429,6 +445,135 @@ Here is the corresponding code to describe this struct to
|
|||
@}
|
||||
@end example
|
||||
|
||||
@node Complex
|
||||
@subsection Complex Types
|
||||
|
||||
@samp{libffi} supports the complex types defined by the C99
|
||||
standard (@code{_Complex float}, @code{_Complex double} and
|
||||
@code{_Complex long double} with the built-in type descriptors
|
||||
@code{ffi_type_complex_float}, @code{ffi_type_complex_double} and
|
||||
@code{ffi_type_complex_longdouble}.
|
||||
|
||||
Custom complex types like @code{_Complex int} can also be used.
|
||||
An @code{ffi_type} object has to be defined to describe the
|
||||
complex type to @samp{libffi}.
|
||||
|
||||
@tindex ffi_type
|
||||
@deftp {Data type} ffi_type
|
||||
@table @code
|
||||
@item size_t size
|
||||
This must be manually set to the size of the complex type.
|
||||
|
||||
@item unsigned short alignment
|
||||
This must be manually set to the alignment of the complex type.
|
||||
|
||||
@item unsigned short type
|
||||
For a complex type, this must be set to @code{FFI_TYPE_COMPLEX}.
|
||||
|
||||
@item ffi_type **elements
|
||||
|
||||
This is a @samp{NULL}-terminated array of pointers to
|
||||
@code{ffi_type} objects. The first element is set to the
|
||||
@code{ffi_type} of the complex's base type. The second element
|
||||
must be set to @code{NULL}.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
The section @ref{Complex Type Example} shows a way to determine
|
||||
the @code{size} and @code{alignment} members in a platform
|
||||
independent way.
|
||||
|
||||
For platforms that have no complex support in @code{libffi} yet,
|
||||
the functions @code{ffi_prep_cif} and @code{ffi_prep_args} abort
|
||||
the program if they encounter a complex type.
|
||||
|
||||
@node Complex Type Example
|
||||
@subsection Complex Type Example
|
||||
|
||||
This example demonstrates how to use complex types:
|
||||
|
||||
@example
|
||||
#include <stdio.h>
|
||||
#include <ffi.h>
|
||||
#include <complex.h>
|
||||
|
||||
void complex_fn(_Complex float cf,
|
||||
_Complex double cd,
|
||||
_Complex long double cld)
|
||||
@{
|
||||
printf("cf=%f+%fi\ncd=%f+%fi\ncld=%f+%fi\n",
|
||||
(float)creal (cf), (float)cimag (cf),
|
||||
(float)creal (cd), (float)cimag (cd),
|
||||
(float)creal (cld), (float)cimag (cld));
|
||||
@}
|
||||
|
||||
int main()
|
||||
@{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[3];
|
||||
void *values[3];
|
||||
_Complex float cf;
|
||||
_Complex double cd;
|
||||
_Complex long double cld;
|
||||
|
||||
/* Initialize the argument info vectors */
|
||||
args[0] = &ffi_type_complex_float;
|
||||
args[1] = &ffi_type_complex_double;
|
||||
args[2] = &ffi_type_complex_longdouble;
|
||||
values[0] = &cf;
|
||||
values[1] = &cd;
|
||||
values[2] = &cld;
|
||||
|
||||
/* Initialize the cif */
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
|
||||
&ffi_type_void, args) == FFI_OK)
|
||||
@{
|
||||
cf = 1.0 + 20.0 * I;
|
||||
cd = 300.0 + 4000.0 * I;
|
||||
cld = 50000.0 + 600000.0 * I;
|
||||
/* Call the function */
|
||||
ffi_call(&cif, (void (*)(void))complex_fn, 0, values);
|
||||
@}
|
||||
|
||||
return 0;
|
||||
@}
|
||||
@end example
|
||||
|
||||
This is an example for defining a custom complex type descriptor
|
||||
for compilers that support them:
|
||||
|
||||
@example
|
||||
/*
|
||||
* This macro can be used to define new complex type descriptors
|
||||
* in a platform independent way.
|
||||
*
|
||||
* name: Name of the new descriptor is ffi_type_complex_<name>.
|
||||
* type: The C base type of the complex type.
|
||||
*/
|
||||
#define FFI_COMPLEX_TYPEDEF(name, type, ffitype) \
|
||||
static ffi_type *ffi_elements_complex_##name [2] = @{ \
|
||||
(ffi_type *)(&ffitype), NULL \
|
||||
@}; \
|
||||
struct struct_align_complex_##name @{ \
|
||||
char c; \
|
||||
_Complex type x; \
|
||||
@}; \
|
||||
ffi_type ffi_type_complex_##name = @{ \
|
||||
sizeof(_Complex type), \
|
||||
offsetof(struct struct_align_complex_##name, x), \
|
||||
FFI_TYPE_COMPLEX, \
|
||||
(ffi_type **)ffi_elements_complex_##name \
|
||||
@}
|
||||
|
||||
/* Define new complex type descriptors using the macro: */
|
||||
/* ffi_type_complex_sint */
|
||||
FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint);
|
||||
/* ffi_type_complex_uchar */
|
||||
FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8);
|
||||
@end example
|
||||
|
||||
The new type descriptors can then be used like one of the built-in
|
||||
type descriptors in the previous example.
|
||||
|
||||
@node Multiple ABIs
|
||||
@section Multiple ABIs
|
||||
|
@ -534,7 +679,7 @@ writable and executable addresses.
|
|||
@section Closure Example
|
||||
|
||||
A trivial example that creates a new @code{puts} by binding
|
||||
@code{fputs} with @code{stdin}.
|
||||
@code{fputs} with @code{stdout}.
|
||||
|
||||
@example
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
@set UPDATED 6 March 2012
|
||||
@set UPDATED-MONTH March 2012
|
||||
@set EDITION 3.0.11
|
||||
@set VERSION 3.0.11
|
|
@ -1,4 +1,4 @@
|
|||
@set UPDATED 6 March 2012
|
||||
@set UPDATED-MONTH March 2012
|
||||
@set EDITION 3.0.11
|
||||
@set VERSION 3.0.11
|
||||
@set UPDATED 8 November 2014
|
||||
@set UPDATED-MONTH November 2014
|
||||
@set EDITION 3.2.1
|
||||
@set VERSION 3.2.1
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
/* Cannot use malloc on this target, so, we revert to alternative means */
|
||||
#undef FFI_MMAP_EXEC_WRIT
|
||||
|
||||
/* Define this is you do not want support for the raw API. */
|
||||
/* Define this if you do not want support for the raw API. */
|
||||
#undef FFI_NO_RAW_API
|
||||
|
||||
/* Define this is you do not want support for aggregate types. */
|
||||
/* Define this if you do not want support for aggregate types. */
|
||||
#undef FFI_NO_STRUCTS
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
|
@ -48,6 +48,9 @@
|
|||
/* Define if your assembler supports .register. */
|
||||
#undef HAVE_AS_REGISTER_PSEUDO_OP
|
||||
|
||||
/* Define if the compiler uses zarch features. */
|
||||
#undef HAVE_AS_S390_ZARCH
|
||||
|
||||
/* Define if your assembler and linker support unaligned PC relative relocs.
|
||||
*/
|
||||
#undef HAVE_AS_SPARC_UA_PCREL
|
||||
|
@ -82,6 +85,9 @@
|
|||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mkostemp' function. */
|
||||
#undef HAVE_MKOSTEMP
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
|
@ -155,6 +161,9 @@
|
|||
/* The size of `long double', as computed by sizeof. */
|
||||
#undef SIZEOF_LONG_DOUBLE
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#undef SIZEOF_SIZE_T
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at runtime.
|
||||
|
|
209
libffi/generate-darwin-source-and-headers.py
Normal file
209
libffi/generate-darwin-source-and-headers.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
#!/usr/bin/env python
|
||||
import subprocess
|
||||
import os
|
||||
import errno
|
||||
import collections
|
||||
import glob
|
||||
import argparse
|
||||
|
||||
class Platform(object):
|
||||
pass
|
||||
|
||||
class simulator_platform(Platform):
|
||||
directory = 'darwin_ios'
|
||||
sdk = 'iphonesimulator'
|
||||
arch = 'i386'
|
||||
triple = 'i386-apple-darwin11'
|
||||
version_min = '-miphoneos-version-min=7.0'
|
||||
|
||||
prefix = "#ifdef __i386__\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
src_dir = 'x86'
|
||||
src_files = ['darwin.S', 'win32.S', 'ffi.c']
|
||||
|
||||
|
||||
class simulator64_platform(Platform):
|
||||
directory = 'darwin_ios'
|
||||
sdk = 'iphonesimulator'
|
||||
arch = 'x86_64'
|
||||
triple = 'x86_64-apple-darwin13'
|
||||
version_min = '-miphoneos-version-min=7.0'
|
||||
|
||||
prefix = "#ifdef __x86_64__\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
src_dir = 'x86'
|
||||
src_files = ['darwin64.S', 'ffi64.c']
|
||||
|
||||
|
||||
class device_platform(Platform):
|
||||
directory = 'darwin_ios'
|
||||
sdk = 'iphoneos'
|
||||
arch = 'armv7'
|
||||
triple = 'arm-apple-darwin11'
|
||||
version_min = '-miphoneos-version-min=7.0'
|
||||
|
||||
prefix = "#ifdef __arm__\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
src_dir = 'arm'
|
||||
src_files = ['sysv.S', 'trampoline.S', 'ffi.c']
|
||||
|
||||
|
||||
class device64_platform(Platform):
|
||||
directory = 'darwin_ios'
|
||||
sdk = 'iphoneos'
|
||||
arch = 'arm64'
|
||||
triple = 'aarch64-apple-darwin13'
|
||||
version_min = '-miphoneos-version-min=7.0'
|
||||
|
||||
prefix = "#ifdef __arm64__\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
src_dir = 'aarch64'
|
||||
src_files = ['sysv.S', 'ffi.c']
|
||||
|
||||
|
||||
class desktop32_platform(Platform):
|
||||
directory = 'darwin_osx'
|
||||
sdk = 'macosx'
|
||||
arch = 'i386'
|
||||
triple = 'i386-apple-darwin10'
|
||||
version_min = '-mmacosx-version-min=10.6'
|
||||
src_dir = 'x86'
|
||||
src_files = ['darwin.S', 'win32.S', 'ffi.c']
|
||||
|
||||
prefix = "#ifdef __i386__\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
|
||||
|
||||
class desktop64_platform(Platform):
|
||||
directory = 'darwin_osx'
|
||||
sdk = 'macosx'
|
||||
arch = 'x86_64'
|
||||
triple = 'x86_64-apple-darwin10'
|
||||
version_min = '-mmacosx-version-min=10.6'
|
||||
|
||||
prefix = "#ifdef __x86_64__\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
src_dir = 'x86'
|
||||
src_files = ['darwin64.S', 'ffi64.c']
|
||||
|
||||
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST:
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
|
||||
mkdir_p(dst_dir)
|
||||
out_filename = filename
|
||||
|
||||
if file_suffix:
|
||||
split_name = os.path.splitext(filename)
|
||||
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
|
||||
|
||||
with open(os.path.join(src_dir, filename)) as in_file:
|
||||
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
|
||||
if prefix:
|
||||
out_file.write(prefix)
|
||||
|
||||
out_file.write(in_file.read())
|
||||
|
||||
if suffix:
|
||||
out_file.write(suffix)
|
||||
|
||||
|
||||
def list_files(src_dir, pattern=None, filelist=None):
|
||||
if pattern: filelist = glob.iglob(os.path.join(src_dir, pattern))
|
||||
for file in filelist:
|
||||
yield os.path.basename(file)
|
||||
|
||||
|
||||
def copy_files(src_dir, dst_dir, pattern=None, filelist=None, file_suffix=None, prefix=None, suffix=None):
|
||||
for filename in list_files(src_dir, pattern=pattern, filelist=filelist):
|
||||
move_file(src_dir, dst_dir, filename, file_suffix=file_suffix, prefix=prefix, suffix=suffix)
|
||||
|
||||
|
||||
def copy_src_platform_files(platform):
|
||||
src_dir = os.path.join('src', platform.src_dir)
|
||||
dst_dir = os.path.join(platform.directory, 'src', platform.src_dir)
|
||||
copy_files(src_dir, dst_dir, filelist=platform.src_files, file_suffix=platform.arch, prefix=platform.prefix, suffix=platform.suffix)
|
||||
|
||||
|
||||
def build_target(platform, platform_headers):
|
||||
def xcrun_cmd(cmd):
|
||||
return 'xcrun -sdk %s %s -arch %s' % (platform.sdk, cmd, platform.arch)
|
||||
|
||||
tag='%s-%s' % (platform.sdk, platform.arch)
|
||||
build_dir = 'build_%s' % tag
|
||||
mkdir_p(build_dir)
|
||||
env = dict(CC=xcrun_cmd('clang'),
|
||||
LD=xcrun_cmd('ld'),
|
||||
CFLAGS='%s' % (platform.version_min))
|
||||
working_dir = os.getcwd()
|
||||
try:
|
||||
os.chdir(build_dir)
|
||||
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
|
||||
finally:
|
||||
os.chdir(working_dir)
|
||||
|
||||
for src_dir in [build_dir, os.path.join(build_dir, 'include')]:
|
||||
copy_files(src_dir,
|
||||
os.path.join(platform.directory, 'include'),
|
||||
pattern='*.h',
|
||||
file_suffix=platform.arch,
|
||||
prefix=platform.prefix,
|
||||
suffix=platform.suffix)
|
||||
|
||||
for filename in list_files(src_dir, pattern='*.h'):
|
||||
platform_headers[filename].add((platform.prefix, platform.arch, platform.suffix))
|
||||
|
||||
|
||||
def make_tramp():
|
||||
with open('src/arm/trampoline.S', 'w') as tramp_out:
|
||||
p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)
|
||||
p.wait()
|
||||
|
||||
|
||||
def generate_source_and_headers(generate_osx=True, generate_ios=True):
|
||||
copy_files('src', 'darwin_common/src', pattern='*.c')
|
||||
copy_files('include', 'darwin_common/include', pattern='*.h')
|
||||
|
||||
if generate_ios:
|
||||
make_tramp()
|
||||
copy_src_platform_files(simulator_platform)
|
||||
copy_src_platform_files(simulator64_platform)
|
||||
copy_src_platform_files(device_platform)
|
||||
copy_src_platform_files(device64_platform)
|
||||
if generate_osx:
|
||||
copy_src_platform_files(desktop32_platform)
|
||||
copy_src_platform_files(desktop64_platform)
|
||||
|
||||
platform_headers = collections.defaultdict(set)
|
||||
|
||||
if generate_ios:
|
||||
build_target(simulator_platform, platform_headers)
|
||||
build_target(simulator64_platform, platform_headers)
|
||||
build_target(device_platform, platform_headers)
|
||||
build_target(device64_platform, platform_headers)
|
||||
if generate_osx:
|
||||
build_target(desktop32_platform, platform_headers)
|
||||
build_target(desktop64_platform, platform_headers)
|
||||
|
||||
mkdir_p('darwin_common/include')
|
||||
for header_name, tag_tuples in platform_headers.iteritems():
|
||||
basename, suffix = os.path.splitext(header_name)
|
||||
with open(os.path.join('darwin_common/include', header_name), 'w') as header:
|
||||
for tag_tuple in tag_tuples:
|
||||
header.write('%s#include <%s_%s%s>\n%s\n' % (tag_tuple[0], basename, tag_tuple[1], suffix, tag_tuple[2]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--only-ios', action='store_true', default=False)
|
||||
parser.add_argument('--only-osx', action='store_true', default=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
generate_source_and_headers(generate_osx=not args.only_ios, generate_ios=not args.only_osx)
|
|
@ -1,160 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
import os
|
||||
import errno
|
||||
import collections
|
||||
import sys
|
||||
|
||||
class Platform(object):
|
||||
pass
|
||||
|
||||
sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
|
||||
|
||||
def sdkinfo(sdkname):
|
||||
ret = {}
|
||||
for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
|
||||
kv = line.strip().split(': ', 1)
|
||||
if len(kv) == 2:
|
||||
k,v = kv
|
||||
ret[k] = v
|
||||
return ret
|
||||
|
||||
sim_sdk_info = sdkinfo('iphonesimulator')
|
||||
device_sdk_info = sdkinfo('iphoneos')
|
||||
|
||||
def latest_sdks():
|
||||
latest_sim = None
|
||||
latest_device = None
|
||||
for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
|
||||
match = sdk_re.match(line)
|
||||
if match:
|
||||
if 'Simulator' in line:
|
||||
latest_sim = match.group(1)
|
||||
elif 'iOS' in line:
|
||||
latest_device = match.group(1)
|
||||
|
||||
return latest_sim, latest_device
|
||||
|
||||
sim_sdk, device_sdk = latest_sdks()
|
||||
|
||||
class simulator_platform(Platform):
|
||||
sdk='iphonesimulator'
|
||||
arch = 'i386'
|
||||
name = 'simulator'
|
||||
triple = 'i386-apple-darwin10'
|
||||
sdkroot = sim_sdk_info['Path']
|
||||
|
||||
prefix = "#if !defined(__arm__) && defined(__i386__)\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
|
||||
class device_platform(Platform):
|
||||
sdk='iphoneos'
|
||||
name = 'ios'
|
||||
arch = 'armv7'
|
||||
triple = 'arm-apple-darwin10'
|
||||
sdkroot = device_sdk_info['Path']
|
||||
|
||||
prefix = "#ifdef __arm__\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
|
||||
|
||||
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
|
||||
if not os.path.exists(dst_dir):
|
||||
os.makedirs(dst_dir)
|
||||
|
||||
out_filename = filename
|
||||
|
||||
if file_suffix:
|
||||
split_name = os.path.splitext(filename)
|
||||
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
|
||||
|
||||
with open(os.path.join(src_dir, filename)) as in_file:
|
||||
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
|
||||
if prefix:
|
||||
out_file.write(prefix)
|
||||
|
||||
out_file.write(in_file.read())
|
||||
|
||||
if suffix:
|
||||
out_file.write(suffix)
|
||||
|
||||
headers_seen = collections.defaultdict(set)
|
||||
|
||||
def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
|
||||
for root, dirs, files in os.walk(src_dir, followlinks=True):
|
||||
relroot = os.path.relpath(root,src_dir)
|
||||
|
||||
def move_dir(arch, prefix='', suffix='', files=[]):
|
||||
for file in files:
|
||||
file_suffix = None
|
||||
if file.endswith('.h'):
|
||||
if dest_include_dir:
|
||||
file_suffix = arch
|
||||
if arch:
|
||||
headers_seen[file].add(arch)
|
||||
move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
|
||||
|
||||
elif dest_dir:
|
||||
outroot = os.path.join(dest_dir, relroot)
|
||||
move_file(root, outroot, file, prefix=prefix, suffix=suffix)
|
||||
|
||||
if relroot == '.':
|
||||
move_dir(arch=arch,
|
||||
files=files,
|
||||
prefix=prefix,
|
||||
suffix=suffix)
|
||||
elif relroot == 'arm':
|
||||
move_dir(arch='arm',
|
||||
prefix="#ifdef __arm__\n\n",
|
||||
suffix="\n\n#endif",
|
||||
files=files)
|
||||
elif relroot == 'x86':
|
||||
move_dir(arch='i386',
|
||||
prefix="#if !defined(__arm__) && defined(__i386__)\n\n",
|
||||
suffix="\n\n#endif",
|
||||
files=files)
|
||||
|
||||
def build_target(platform):
|
||||
def xcrun_cmd(cmd):
|
||||
return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
|
||||
|
||||
build_dir = 'build_' + platform.name
|
||||
if not os.path.exists(build_dir):
|
||||
os.makedirs(build_dir)
|
||||
env = dict(CC=xcrun_cmd('clang'),
|
||||
LD=xcrun_cmd('ld'),
|
||||
CFLAGS='-arch %s -isysroot %s -miphoneos-version-min=4.0' % (platform.arch, platform.sdkroot))
|
||||
working_dir=os.getcwd()
|
||||
try:
|
||||
os.chdir(build_dir)
|
||||
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
|
||||
move_source_tree('.', None, '../ios/include',
|
||||
arch=platform.arch,
|
||||
prefix=platform.prefix,
|
||||
suffix=platform.suffix)
|
||||
move_source_tree('./include', None, '../ios/include',
|
||||
arch=platform.arch,
|
||||
prefix=platform.prefix,
|
||||
suffix=platform.suffix)
|
||||
finally:
|
||||
os.chdir(working_dir)
|
||||
|
||||
for header_name, archs in headers_seen.iteritems():
|
||||
basename, suffix = os.path.splitext(header_name)
|
||||
|
||||
def main():
|
||||
move_source_tree('src', 'ios/src', 'ios/include')
|
||||
move_source_tree('include', None, 'ios/include')
|
||||
build_target(simulator_platform)
|
||||
build_target(device_platform)
|
||||
|
||||
for header_name, archs in headers_seen.iteritems():
|
||||
basename, suffix = os.path.splitext(header_name)
|
||||
with open(os.path.join('ios/include', header_name), 'w') as header:
|
||||
for arch in archs:
|
||||
header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,153 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
import subprocess
|
||||
import re
|
||||
import os
|
||||
import errno
|
||||
import collections
|
||||
import sys
|
||||
|
||||
class Platform(object):
|
||||
pass
|
||||
|
||||
sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)')
|
||||
|
||||
def sdkinfo(sdkname):
|
||||
ret = {}
|
||||
for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout:
|
||||
kv = line.strip().split(': ', 1)
|
||||
if len(kv) == 2:
|
||||
k,v = kv
|
||||
ret[k] = v
|
||||
return ret
|
||||
|
||||
desktop_sdk_info = sdkinfo('macosx')
|
||||
|
||||
def latest_sdks():
|
||||
latest_desktop = None
|
||||
for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout:
|
||||
match = sdk_re.match(line)
|
||||
if match:
|
||||
if 'OS X' in line:
|
||||
latest_desktop = match.group(1)
|
||||
|
||||
return latest_desktop
|
||||
|
||||
desktop_sdk = latest_sdks()
|
||||
|
||||
class desktop_platform_32(Platform):
|
||||
sdk='macosx'
|
||||
arch = 'i386'
|
||||
name = 'mac32'
|
||||
triple = 'i386-apple-darwin10'
|
||||
sdkroot = desktop_sdk_info['Path']
|
||||
|
||||
prefix = "#if defined(__i386__) && !defined(__x86_64__)\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
|
||||
class desktop_platform_64(Platform):
|
||||
sdk='macosx'
|
||||
arch = 'x86_64'
|
||||
name = 'mac'
|
||||
triple = 'x86_64-apple-darwin10'
|
||||
sdkroot = desktop_sdk_info['Path']
|
||||
|
||||
prefix = "#if !defined(__i386__) && defined(__x86_64__)\n\n"
|
||||
suffix = "\n\n#endif"
|
||||
|
||||
def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''):
|
||||
if not os.path.exists(dst_dir):
|
||||
os.makedirs(dst_dir)
|
||||
|
||||
out_filename = filename
|
||||
|
||||
if file_suffix:
|
||||
split_name = os.path.splitext(filename)
|
||||
out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1])
|
||||
|
||||
with open(os.path.join(src_dir, filename)) as in_file:
|
||||
with open(os.path.join(dst_dir, out_filename), 'w') as out_file:
|
||||
if prefix:
|
||||
out_file.write(prefix)
|
||||
|
||||
out_file.write(in_file.read())
|
||||
|
||||
if suffix:
|
||||
out_file.write(suffix)
|
||||
|
||||
headers_seen = collections.defaultdict(set)
|
||||
|
||||
def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None):
|
||||
for root, dirs, files in os.walk(src_dir, followlinks=True):
|
||||
relroot = os.path.relpath(root,src_dir)
|
||||
|
||||
def move_dir(arch, prefix='', suffix='', files=[]):
|
||||
for file in files:
|
||||
file_suffix = None
|
||||
if file.endswith('.h'):
|
||||
if dest_include_dir:
|
||||
file_suffix = arch
|
||||
if arch:
|
||||
headers_seen[file].add(arch)
|
||||
move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix)
|
||||
|
||||
elif dest_dir:
|
||||
outroot = os.path.join(dest_dir, relroot)
|
||||
move_file(root, outroot, file, prefix=prefix, suffix=suffix)
|
||||
|
||||
if relroot == '.':
|
||||
move_dir(arch=arch,
|
||||
files=files,
|
||||
prefix=prefix,
|
||||
suffix=suffix)
|
||||
elif relroot == 'x86':
|
||||
move_dir(arch='i386',
|
||||
prefix="#if defined(__i386__) && !defined(__x86_64__)\n\n",
|
||||
suffix="\n\n#endif",
|
||||
files=files)
|
||||
move_dir(arch='x86_64',
|
||||
prefix="#if !defined(__i386__) && defined(__x86_64__)\n\n",
|
||||
suffix="\n\n#endif",
|
||||
files=files)
|
||||
|
||||
def build_target(platform):
|
||||
def xcrun_cmd(cmd):
|
||||
return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip()
|
||||
|
||||
build_dir = 'build_' + platform.name
|
||||
if not os.path.exists(build_dir):
|
||||
os.makedirs(build_dir)
|
||||
env = dict(CC=xcrun_cmd('clang'),
|
||||
LD=xcrun_cmd('ld'),
|
||||
CFLAGS='-arch %s -isysroot %s -mmacosx-version-min=10.6' % (platform.arch, platform.sdkroot))
|
||||
working_dir=os.getcwd()
|
||||
try:
|
||||
os.chdir(build_dir)
|
||||
subprocess.check_call(['../configure', '-host', platform.triple], env=env)
|
||||
move_source_tree('.', None, '../osx/include',
|
||||
arch=platform.arch,
|
||||
prefix=platform.prefix,
|
||||
suffix=platform.suffix)
|
||||
move_source_tree('./include', None, '../osx/include',
|
||||
arch=platform.arch,
|
||||
prefix=platform.prefix,
|
||||
suffix=platform.suffix)
|
||||
finally:
|
||||
os.chdir(working_dir)
|
||||
|
||||
for header_name, archs in headers_seen.iteritems():
|
||||
basename, suffix = os.path.splitext(header_name)
|
||||
|
||||
def main():
|
||||
move_source_tree('src', 'osx/src', 'osx/include')
|
||||
move_source_tree('include', None, 'osx/include')
|
||||
build_target(desktop_platform_32)
|
||||
build_target(desktop_platform_64)
|
||||
|
||||
for header_name, archs in headers_seen.iteritems():
|
||||
basename, suffix = os.path.splitext(header_name)
|
||||
with open(os.path.join('osx/include', header_name), 'w') as header:
|
||||
for arch in archs:
|
||||
header.write('#include <%s_%s%s>\n' % (basename, arch, suffix))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -3,7 +3,8 @@
|
|||
AUTOMAKE_OPTIONS=foreign
|
||||
|
||||
DISTCLEANFILES=ffitarget.h
|
||||
EXTRA_DIST=ffi.h.in ffi_common.h
|
||||
noinst_HEADERS=ffi_common.h ffi_cfi.h
|
||||
EXTRA_DIST=ffi.h.in
|
||||
|
||||
# Where generated headers like ffitarget.h get installed.
|
||||
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
|
||||
|
|
|
@ -37,7 +37,7 @@ host_triplet = @host@
|
|||
target_triplet = @target@
|
||||
subdir = include
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(srcdir)/ffi.h.in $(toollibffi_HEADERS)
|
||||
$(srcdir)/ffi.h.in $(noinst_HEADERS) $(toollibffi_HEADERS)
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
|
||||
$(top_srcdir)/../config/asmcfi.m4 \
|
||||
|
@ -78,7 +78,7 @@ am__base_list = \
|
|||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__installdirs = "$(DESTDIR)$(toollibffidir)"
|
||||
HEADERS = $(toollibffi_HEADERS)
|
||||
HEADERS = $(noinst_HEADERS) $(toollibffi_HEADERS)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
ACLOCAL = @ACLOCAL@
|
||||
|
@ -99,6 +99,10 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -151,12 +155,14 @@ SHELL = @SHELL@
|
|||
STRIP = @STRIP@
|
||||
TARGET = @TARGET@
|
||||
TARGETDIR = @TARGETDIR@
|
||||
TARGET_OBJ = @TARGET_OBJ@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
|
@ -212,7 +218,8 @@ top_builddir = @top_builddir@
|
|||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
DISTCLEANFILES = ffitarget.h
|
||||
EXTRA_DIST = ffi.h.in ffi_common.h
|
||||
noinst_HEADERS = ffi_common.h ffi_cfi.h
|
||||
EXTRA_DIST = ffi.h.in
|
||||
|
||||
# Where generated headers like ffitarget.h get installed.
|
||||
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
libffi @VERSION@ - Copyright (c) 2011 Anthony Green
|
||||
libffi @VERSION@ - Copyright (c) 2011, 2014 Anthony Green
|
||||
- Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
|
@ -68,7 +68,7 @@ extern "C" {
|
|||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define __attribute__(X)
|
||||
#endif
|
||||
|
||||
|
@ -166,25 +166,49 @@ typedef struct _ffi_type
|
|||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
/* Need minimal decorations for DLLs to works on Windows. */
|
||||
/* GCC has autoimport and autoexport. Rely on Libtool to */
|
||||
/* help MSVC export from a DLL, but always declare data */
|
||||
/* to be imported for MSVC clients. This costs an extra */
|
||||
/* indirection for MSVC clients using the static version */
|
||||
/* of the library, but don't worry about that. Besides, */
|
||||
/* as a workaround, they can define FFI_BUILDING if they */
|
||||
/* *know* they are going to link with the static library. */
|
||||
#if defined _MSC_VER && !defined FFI_BUILDING
|
||||
#define FFI_EXTERN extern __declspec(dllimport)
|
||||
#else
|
||||
#define FFI_EXTERN extern
|
||||
#endif
|
||||
|
||||
/* These are defined in types.c */
|
||||
extern ffi_type ffi_type_void;
|
||||
extern ffi_type ffi_type_uint8;
|
||||
extern ffi_type ffi_type_sint8;
|
||||
extern ffi_type ffi_type_uint16;
|
||||
extern ffi_type ffi_type_sint16;
|
||||
extern ffi_type ffi_type_uint32;
|
||||
extern ffi_type ffi_type_sint32;
|
||||
extern ffi_type ffi_type_uint64;
|
||||
extern ffi_type ffi_type_sint64;
|
||||
extern ffi_type ffi_type_float;
|
||||
extern ffi_type ffi_type_double;
|
||||
extern ffi_type ffi_type_pointer;
|
||||
FFI_EXTERN ffi_type ffi_type_void;
|
||||
FFI_EXTERN ffi_type ffi_type_uint8;
|
||||
FFI_EXTERN ffi_type ffi_type_sint8;
|
||||
FFI_EXTERN ffi_type ffi_type_uint16;
|
||||
FFI_EXTERN ffi_type ffi_type_sint16;
|
||||
FFI_EXTERN ffi_type ffi_type_uint32;
|
||||
FFI_EXTERN ffi_type ffi_type_sint32;
|
||||
FFI_EXTERN ffi_type ffi_type_uint64;
|
||||
FFI_EXTERN ffi_type ffi_type_sint64;
|
||||
FFI_EXTERN ffi_type ffi_type_float;
|
||||
FFI_EXTERN ffi_type ffi_type_double;
|
||||
FFI_EXTERN ffi_type ffi_type_pointer;
|
||||
|
||||
#if @HAVE_LONG_DOUBLE@
|
||||
extern ffi_type ffi_type_longdouble;
|
||||
FFI_EXTERN ffi_type ffi_type_longdouble;
|
||||
#else
|
||||
#define ffi_type_longdouble ffi_type_double
|
||||
#endif
|
||||
|
||||
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
FFI_EXTERN ffi_type ffi_type_complex_float;
|
||||
FFI_EXTERN ffi_type ffi_type_complex_double;
|
||||
#if @HAVE_LONG_DOUBLE@
|
||||
FFI_EXTERN ffi_type ffi_type_complex_longdouble;
|
||||
#else
|
||||
#define ffi_type_complex_longdouble ffi_type_complex_double
|
||||
#endif
|
||||
#endif
|
||||
#endif /* LIBFFI_HIDE_BASIC_TYPES */
|
||||
|
||||
typedef enum {
|
||||
|
@ -207,10 +231,10 @@ typedef struct {
|
|||
#endif
|
||||
} ffi_cif;
|
||||
|
||||
#if HAVE_LONG_DOUBLE_VARIANT
|
||||
#if @HAVE_LONG_DOUBLE_VARIANT@
|
||||
/* Used to adjust size/alignment of ffi types. */
|
||||
void ffi_prep_types (ffi_abi abi);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Used internally, but overridden by some architectures */
|
||||
ffi_status ffi_prep_cif_core(ffi_cif *cif,
|
||||
|
@ -288,7 +312,12 @@ size_t ffi_java_raw_size (ffi_cif *cif);
|
|||
__declspec(align(8))
|
||||
#endif
|
||||
typedef struct {
|
||||
#if @FFI_EXEC_TRAMPOLINE_TABLE@
|
||||
void *trampoline_table;
|
||||
void *trampoline_table_entry;
|
||||
#else
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
#endif
|
||||
ffi_cif *cif;
|
||||
void (*fun)(ffi_cif*,void*,void**,void*);
|
||||
void *user_data;
|
||||
|
@ -321,8 +350,12 @@ ffi_prep_closure_loc (ffi_closure*,
|
|||
# pragma pack 8
|
||||
#endif
|
||||
typedef struct {
|
||||
#if @FFI_EXEC_TRAMPOLINE_TABLE@
|
||||
void *trampoline_table;
|
||||
void *trampoline_table_entry;
|
||||
#else
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
|
||||
#endif
|
||||
ffi_cif *cif;
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
@ -342,7 +375,12 @@ typedef struct {
|
|||
} ffi_raw_closure;
|
||||
|
||||
typedef struct {
|
||||
#if @FFI_EXEC_TRAMPOLINE_TABLE@
|
||||
void *trampoline_table;
|
||||
void *trampoline_table_entry;
|
||||
#else
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
#endif
|
||||
|
||||
ffi_cif *cif;
|
||||
|
||||
|
@ -390,6 +428,22 @@ ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
|
|||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
||||
#if FFI_GO_CLOSURES
|
||||
|
||||
typedef struct {
|
||||
void *tramp;
|
||||
ffi_cif *cif;
|
||||
void (*fun)(ffi_cif*,void*,void**,void*);
|
||||
} ffi_go_closure;
|
||||
|
||||
ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*));
|
||||
|
||||
void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, void *closure);
|
||||
|
||||
#endif /* FFI_GO_CLOSURES */
|
||||
|
||||
/* ---- Public interface definition -------------------------------------- */
|
||||
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif,
|
||||
|
@ -437,9 +491,10 @@ void ffi_call(ffi_cif *cif,
|
|||
#define FFI_TYPE_SINT64 12
|
||||
#define FFI_TYPE_STRUCT 13
|
||||
#define FFI_TYPE_POINTER 14
|
||||
#define FFI_TYPE_COMPLEX 15
|
||||
|
||||
/* This should always refer to the last type code (for sanity checks) */
|
||||
#define FFI_TYPE_LAST FFI_TYPE_POINTER
|
||||
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
55
libffi/include/ffi_cfi.h
Normal file
55
libffi/include/ffi_cfi.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc.
|
||||
|
||||
Conditionally assemble cfi directives. Only necessary for building libffi.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef FFI_CFI_H
|
||||
#define FFI_CFI_H
|
||||
|
||||
#ifdef HAVE_AS_CFI_PSEUDO_OP
|
||||
|
||||
# define cfi_startproc .cfi_startproc
|
||||
# define cfi_endproc .cfi_endproc
|
||||
# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off
|
||||
# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
|
||||
# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off
|
||||
# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
|
||||
# define cfi_offset(reg, off) .cfi_offset reg, off
|
||||
# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
|
||||
# define cfi_register(r1, r2) .cfi_register r1, r2
|
||||
# define cfi_return_column(reg) .cfi_return_column reg
|
||||
# define cfi_restore(reg) .cfi_restore reg
|
||||
# define cfi_same_value(reg) .cfi_same_value reg
|
||||
# define cfi_undefined(reg) .cfi_undefined reg
|
||||
# define cfi_remember_state .cfi_remember_state
|
||||
# define cfi_restore_state .cfi_restore_state
|
||||
# define cfi_window_save .cfi_window_save
|
||||
# define cfi_personality(enc, exp) .cfi_personality enc, exp
|
||||
# define cfi_lsda(enc, exp) .cfi_lsda enc, exp
|
||||
# define cfi_escape(...) .cfi_escape __VA_ARGS__
|
||||
|
||||
#else
|
||||
|
||||
# define cfi_startproc
|
||||
# define cfi_endproc
|
||||
# define cfi_def_cfa(reg, off)
|
||||
# define cfi_def_cfa_register(reg)
|
||||
# define cfi_def_cfa_offset(off)
|
||||
# define cfi_adjust_cfa_offset(off)
|
||||
# define cfi_offset(reg, off)
|
||||
# define cfi_rel_offset(reg, off)
|
||||
# define cfi_register(r1, r2)
|
||||
# define cfi_return_column(reg)
|
||||
# define cfi_restore(reg)
|
||||
# define cfi_same_value(reg)
|
||||
# define cfi_undefined(reg)
|
||||
# define cfi_remember_state
|
||||
# define cfi_restore_state
|
||||
# define cfi_window_save
|
||||
# define cfi_personality(enc, exp)
|
||||
# define cfi_lsda(enc, exp)
|
||||
# define cfi_escape(...)
|
||||
|
||||
#endif /* HAVE_AS_CFI_PSEUDO_OP */
|
||||
#endif /* FFI_CFI_H */
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi_common.h - Copyright (C) 2011, 2012 Anthony Green
|
||||
ffi_common.h - Copyright (C) 2011, 2012, 2013 Anthony Green
|
||||
Copyright (C) 2007 Free Software Foundation, Inc
|
||||
Copyright (c) 1996 Red Hat, Inc.
|
||||
|
||||
|
@ -19,10 +19,14 @@ extern "C" {
|
|||
/* Do not move this. Some versions of AIX are very picky about where
|
||||
this is positioned. */
|
||||
#ifdef __GNUC__
|
||||
/* mingw64 defines this already in malloc.h. */
|
||||
#ifndef alloca
|
||||
# define alloca __builtin_alloca
|
||||
#endif
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
/* mingw64 defines this already in malloc.h. */
|
||||
# ifndef alloca
|
||||
# define alloca __builtin_alloca
|
||||
# endif
|
||||
# endif
|
||||
# define MAYBE_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
# define MAYBE_UNUSED
|
||||
|
@ -30,17 +34,17 @@ extern "C" {
|
|||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# pragma alloca
|
||||
# else
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
# ifdef _MSC_VER
|
||||
# define alloca _alloca
|
||||
# else
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Check for the existence of memcpy. */
|
||||
|
@ -87,7 +91,7 @@ typedef struct
|
|||
} extended_cif;
|
||||
|
||||
/* Terse sized type definitions. */
|
||||
#if defined(_MSC_VER) || defined(__sgi)
|
||||
#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C)
|
||||
typedef unsigned char UINT8;
|
||||
typedef signed char SINT8;
|
||||
typedef unsigned short UINT16;
|
||||
|
|
11
libffi/libffi.pc.in
Normal file
11
libffi/libffi.pc.in
Normal file
|
@ -0,0 +1,11 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
toolexeclibdir=@toolexeclibdir@
|
||||
includedir=${libdir}/@PACKAGE_NAME@-@PACKAGE_VERSION@/include
|
||||
|
||||
Name: @PACKAGE_NAME@
|
||||
Description: Library supporting Foreign Function Interfaces
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${toolexeclibdir} -lffi
|
||||
Cflags: -I${includedir}
|
|
@ -7,473 +7,448 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
6C43CBDC1534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBD1534F76F00162364 /* ffi.c */; };
|
||||
6C43CBDD1534F76F00162364 /* sysv.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBF1534F76F00162364 /* sysv.S */; };
|
||||
6C43CBDE1534F76F00162364 /* trampoline.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC01534F76F00162364 /* trampoline.S */; };
|
||||
6C43CBE61534F76F00162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC91534F76F00162364 /* darwin.S */; };
|
||||
6C43CBE81534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBCB1534F76F00162364 /* ffi.c */; };
|
||||
6C43CC1F1534F77800162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC051534F77800162364 /* darwin.S */; };
|
||||
6C43CC201534F77800162364 /* darwin64.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC061534F77800162364 /* darwin64.S */; };
|
||||
6C43CC211534F77800162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC071534F77800162364 /* ffi.c */; };
|
||||
6C43CC221534F77800162364 /* ffi64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC081534F77800162364 /* ffi64.c */; };
|
||||
6C43CC2F1534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
|
||||
6C43CC301534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
|
||||
6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
|
||||
6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
|
||||
6C43CC371534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
|
||||
6C43CC381534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
|
||||
6C43CC391534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
|
||||
6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
|
||||
6C43CC3B1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
|
||||
6C43CC3C1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
|
||||
6C43CC971535032600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8D1535032600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CC981535032600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8E1535032600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CC991535032600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8F1535032600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC901535032600162364 /* ffi_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CC9B1535032600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC911535032600162364 /* fficonfig.h */; };
|
||||
6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC921535032600162364 /* fficonfig_i386.h */; };
|
||||
6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC931535032600162364 /* fficonfig_x86_64.h */; };
|
||||
6C43CC9E1535032600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC941535032600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC951535032600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC961535032600162364 /* ffitarget_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCAD1535039600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA21535039600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA31535039600162364 /* ffi_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCAF1535039600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA41535039600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCB01535039600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA51535039600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCB11535039600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA61535039600162364 /* fficonfig.h */; };
|
||||
6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA71535039600162364 /* fficonfig_armv7.h */; };
|
||||
6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA81535039600162364 /* fficonfig_i386.h */; };
|
||||
6C43CCB41535039600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA91535039600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAA1535039600162364 /* ffitarget_arm.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAB1535039600162364 /* ffitarget_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAC1535039600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DBFA714A187F1D8600A76262 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; };
|
||||
DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713F187F1D8600A76262 /* ffi_common.h */; };
|
||||
DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7140187F1D8600A76262 /* fficonfig.h */; };
|
||||
DBFA714D187F1D8600A76262 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; };
|
||||
DBFA714E187F1D8600A76262 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; };
|
||||
DBFA714F187F1D8600A76262 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; };
|
||||
DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; };
|
||||
DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; };
|
||||
DBFA7158187F1D8600A76262 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; };
|
||||
DBFA7159187F1D8600A76262 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; };
|
||||
DBFA715A187F1D8600A76262 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; };
|
||||
DBFA715B187F1D8600A76262 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; };
|
||||
DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716C187F1D9B00A76262 /* ffi_arm64.c */; };
|
||||
DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; };
|
||||
DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; };
|
||||
DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; };
|
||||
DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */; };
|
||||
DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */; };
|
||||
DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7174187F1D9B00A76262 /* darwin_i386.S */; };
|
||||
DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; };
|
||||
DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7176187F1D9B00A76262 /* ffi_i386.c */; };
|
||||
DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7182187F1DA100A76262 /* ffi_i386.h */; };
|
||||
DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7183187F1DA100A76262 /* ffi_x86_64.h */; };
|
||||
DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7184187F1DA100A76262 /* fficonfig_i386.h */; };
|
||||
DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */; };
|
||||
DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7186187F1DA100A76262 /* ffitarget_i386.h */; };
|
||||
DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */; };
|
||||
DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */; };
|
||||
DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718B187F1DA100A76262 /* darwin_i386.S */; };
|
||||
DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; };
|
||||
DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718D187F1DA100A76262 /* ffi_i386.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
DB13B1641849DF1E0010F42D /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 8;
|
||||
dstPath = "include/$(PRODUCT_NAME)";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
6C43CB3D1534E9D100162364 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6C43CBBD1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
|
||||
6C43CBBF1534F76F00162364 /* sysv.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv.S; sourceTree = "<group>"; };
|
||||
6C43CBC01534F76F00162364 /* trampoline.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline.S; sourceTree = "<group>"; };
|
||||
6C43CBC91534F76F00162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
|
||||
6C43CBCB1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
|
||||
6C43CC051534F77800162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
|
||||
6C43CC061534F77800162364 /* darwin64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64.S; sourceTree = "<group>"; };
|
||||
6C43CC071534F77800162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
|
||||
6C43CC081534F77800162364 /* ffi64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64.c; sourceTree = "<group>"; };
|
||||
6C43CC281534F7BE00162364 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = closures.c; path = src/closures.c; sourceTree = SOURCE_ROOT; };
|
||||
6C43CC2B1534F7BE00162364 /* java_raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = java_raw_api.c; path = src/java_raw_api.c; sourceTree = SOURCE_ROOT; };
|
||||
6C43CC2C1534F7BE00162364 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = prep_cif.c; path = src/prep_cif.c; sourceTree = SOURCE_ROOT; };
|
||||
6C43CC2D1534F7BE00162364 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = raw_api.c; path = src/raw_api.c; sourceTree = SOURCE_ROOT; };
|
||||
6C43CC2E1534F7BE00162364 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = types.c; path = src/types.c; sourceTree = SOURCE_ROOT; };
|
||||
6C43CC8D1535032600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
|
||||
6C43CC8E1535032600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
|
||||
6C43CC8F1535032600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
|
||||
6C43CC901535032600162364 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
|
||||
6C43CC911535032600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
|
||||
6C43CC921535032600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
|
||||
6C43CC931535032600162364 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
|
||||
6C43CC941535032600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
|
||||
6C43CC951535032600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
|
||||
6C43CC961535032600162364 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
|
||||
6C43CCA21535039600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
|
||||
6C43CCA31535039600162364 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; };
|
||||
6C43CCA41535039600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
|
||||
6C43CCA51535039600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
|
||||
6C43CCA61535039600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
|
||||
6C43CCA71535039600162364 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; };
|
||||
6C43CCA81535039600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
|
||||
6C43CCA91535039600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
|
||||
6C43CCAA1535039600162364 /* ffitarget_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm.h; sourceTree = "<group>"; };
|
||||
6C43CCAB1535039600162364 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; };
|
||||
6C43CCAC1535039600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
|
||||
F6F980BA147386130008F121 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DB13B1661849DF1E0010F42D /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DB13B1911849DF510010F42D /* ffi.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = ffi.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DBFA713E187F1D8600A76262 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
|
||||
DBFA713F187F1D8600A76262 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
|
||||
DBFA7140187F1D8600A76262 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
|
||||
DBFA7141187F1D8600A76262 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
|
||||
DBFA7143187F1D8600A76262 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = closures.c; sourceTree = "<group>"; };
|
||||
DBFA7145187F1D8600A76262 /* dlmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dlmalloc.c; sourceTree = "<group>"; };
|
||||
DBFA7147187F1D8600A76262 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prep_cif.c; sourceTree = "<group>"; };
|
||||
DBFA7148187F1D8600A76262 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw_api.c; sourceTree = "<group>"; };
|
||||
DBFA7149187F1D8600A76262 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = types.c; sourceTree = "<group>"; };
|
||||
DBFA715E187F1D9B00A76262 /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = "<group>"; };
|
||||
DBFA715F187F1D9B00A76262 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; };
|
||||
DBFA7160187F1D9B00A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
|
||||
DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
|
||||
DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_arm64.h; sourceTree = "<group>"; };
|
||||
DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; };
|
||||
DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
|
||||
DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
|
||||
DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = "<group>"; };
|
||||
DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; };
|
||||
DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
|
||||
DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
|
||||
DBFA716C187F1D9B00A76262 /* ffi_arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_arm64.c; sourceTree = "<group>"; };
|
||||
DBFA716D187F1D9B00A76262 /* sysv_arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_arm64.S; sourceTree = "<group>"; };
|
||||
DBFA716F187F1D9B00A76262 /* ffi_armv7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_armv7.c; sourceTree = "<group>"; };
|
||||
DBFA7170187F1D9B00A76262 /* sysv_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_armv7.S; sourceTree = "<group>"; };
|
||||
DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline_armv7.S; sourceTree = "<group>"; };
|
||||
DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = "<group>"; };
|
||||
DBFA7174187F1D9B00A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = "<group>"; };
|
||||
DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; };
|
||||
DBFA7176187F1D9B00A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = "<group>"; };
|
||||
DBFA7182187F1DA100A76262 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
|
||||
DBFA7183187F1DA100A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
|
||||
DBFA7184187F1DA100A76262 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
|
||||
DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
|
||||
DBFA7186187F1DA100A76262 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
|
||||
DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
|
||||
DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = "<group>"; };
|
||||
DBFA718B187F1DA100A76262 /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = "<group>"; };
|
||||
DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = "<group>"; };
|
||||
DBFA718D187F1DA100A76262 /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
6C43CB3A1534E9D100162364 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F6F980B7147386130008F121 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
6C43CBAF1534F76F00162364 /* iOS */ = {
|
||||
DB13B15B1849DEB70010F42D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CCA11535039600162364 /* include */,
|
||||
6C43CBBB1534F76F00162364 /* src */,
|
||||
DBFA713C187F1D8600A76262 /* darwin_common */,
|
||||
DBFA715C187F1D9B00A76262 /* darwin_ios */,
|
||||
DBFA7180187F1DA100A76262 /* darwin_osx */,
|
||||
DB13B1671849DF1E0010F42D /* Products */,
|
||||
);
|
||||
name = iOS;
|
||||
path = ios;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CBBB1534F76F00162364 /* src */ = {
|
||||
DB13B1671849DF1E0010F42D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CBC81534F76F00162364 /* x86 */,
|
||||
6C43CBBC1534F76F00162364 /* arm */,
|
||||
DB13B1661849DF1E0010F42D /* libffi.a */,
|
||||
DB13B1911849DF510010F42D /* ffi.dylib */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DBFA713C187F1D8600A76262 /* darwin_common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DBFA713D187F1D8600A76262 /* include */,
|
||||
DBFA7142187F1D8600A76262 /* src */,
|
||||
);
|
||||
path = "darwin_common";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DBFA713D187F1D8600A76262 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DBFA713E187F1D8600A76262 /* ffi.h */,
|
||||
DBFA713F187F1D8600A76262 /* ffi_common.h */,
|
||||
DBFA7140187F1D8600A76262 /* fficonfig.h */,
|
||||
DBFA7141187F1D8600A76262 /* ffitarget.h */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DBFA7142187F1D8600A76262 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DBFA7143187F1D8600A76262 /* closures.c */,
|
||||
DBFA7145187F1D8600A76262 /* dlmalloc.c */,
|
||||
DBFA7147187F1D8600A76262 /* prep_cif.c */,
|
||||
DBFA7148187F1D8600A76262 /* raw_api.c */,
|
||||
DBFA7149187F1D8600A76262 /* types.c */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CBBC1534F76F00162364 /* arm */ = {
|
||||
DBFA715C187F1D9B00A76262 /* darwin_ios */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CBBD1534F76F00162364 /* ffi.c */,
|
||||
6C43CBBF1534F76F00162364 /* sysv.S */,
|
||||
6C43CBC01534F76F00162364 /* trampoline.S */,
|
||||
DBFA715D187F1D9B00A76262 /* include */,
|
||||
DBFA716A187F1D9B00A76262 /* src */,
|
||||
);
|
||||
path = "darwin_ios";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DBFA715D187F1D9B00A76262 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DBFA715E187F1D9B00A76262 /* ffi_arm64.h */,
|
||||
DBFA715F187F1D9B00A76262 /* ffi_armv7.h */,
|
||||
DBFA7160187F1D9B00A76262 /* ffi_i386.h */,
|
||||
DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */,
|
||||
DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */,
|
||||
DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */,
|
||||
DBFA7164187F1D9B00A76262 /* fficonfig_i386.h */,
|
||||
DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */,
|
||||
DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */,
|
||||
DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */,
|
||||
DBFA7168187F1D9B00A76262 /* ffitarget_i386.h */,
|
||||
DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DBFA716A187F1D9B00A76262 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DBFA716B187F1D9B00A76262 /* aarch64 */,
|
||||
DBFA716E187F1D9B00A76262 /* arm */,
|
||||
DBFA7172187F1D9B00A76262 /* x86 */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DBFA716B187F1D9B00A76262 /* aarch64 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DBFA716C187F1D9B00A76262 /* ffi_arm64.c */,
|
||||
DBFA716D187F1D9B00A76262 /* sysv_arm64.S */,
|
||||
);
|
||||
path = aarch64;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DBFA716E187F1D9B00A76262 /* arm */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DBFA716F187F1D9B00A76262 /* ffi_armv7.c */,
|
||||
DBFA7170187F1D9B00A76262 /* sysv_armv7.S */,
|
||||
DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */,
|
||||
);
|
||||
path = arm;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CBC81534F76F00162364 /* x86 */ = {
|
||||
DBFA7172187F1D9B00A76262 /* x86 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CBC91534F76F00162364 /* darwin.S */,
|
||||
6C43CBCB1534F76F00162364 /* ffi.c */,
|
||||
DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */,
|
||||
DBFA7174187F1D9B00A76262 /* darwin_i386.S */,
|
||||
DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */,
|
||||
DBFA7176187F1D9B00A76262 /* ffi_i386.c */,
|
||||
);
|
||||
path = x86;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CBF01534F77800162364 /* OS X */ = {
|
||||
DBFA7180187F1DA100A76262 /* darwin_osx */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CC8C1535032600162364 /* include */,
|
||||
6C43CBFC1534F77800162364 /* src */,
|
||||
DBFA7181187F1DA100A76262 /* include */,
|
||||
DBFA7188187F1DA100A76262 /* src */,
|
||||
);
|
||||
name = "OS X";
|
||||
path = osx;
|
||||
path = "darwin_osx";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CBFC1534F77800162364 /* src */ = {
|
||||
DBFA7181187F1DA100A76262 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CC041534F77800162364 /* x86 */,
|
||||
DBFA7182187F1DA100A76262 /* ffi_i386.h */,
|
||||
DBFA7183187F1DA100A76262 /* ffi_x86_64.h */,
|
||||
DBFA7184187F1DA100A76262 /* fficonfig_i386.h */,
|
||||
DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */,
|
||||
DBFA7186187F1DA100A76262 /* ffitarget_i386.h */,
|
||||
DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DBFA7188187F1DA100A76262 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DBFA7189187F1DA100A76262 /* x86 */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CC041534F77800162364 /* x86 */ = {
|
||||
DBFA7189187F1DA100A76262 /* x86 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CC051534F77800162364 /* darwin.S */,
|
||||
6C43CC061534F77800162364 /* darwin64.S */,
|
||||
6C43CC071534F77800162364 /* ffi.c */,
|
||||
6C43CC081534F77800162364 /* ffi64.c */,
|
||||
DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */,
|
||||
DBFA718B187F1DA100A76262 /* darwin_i386.S */,
|
||||
DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */,
|
||||
DBFA718D187F1DA100A76262 /* ffi_i386.c */,
|
||||
);
|
||||
path = x86;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CC3D1534F7C400162364 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CC281534F7BE00162364 /* closures.c */,
|
||||
6C43CC2B1534F7BE00162364 /* java_raw_api.c */,
|
||||
6C43CC2C1534F7BE00162364 /* prep_cif.c */,
|
||||
6C43CC2D1534F7BE00162364 /* raw_api.c */,
|
||||
6C43CC2E1534F7BE00162364 /* types.c */,
|
||||
);
|
||||
name = src;
|
||||
path = ios;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CC8C1535032600162364 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CC8D1535032600162364 /* ffi.h */,
|
||||
6C43CC8E1535032600162364 /* ffi_common.h */,
|
||||
6C43CC8F1535032600162364 /* ffi_i386.h */,
|
||||
6C43CC901535032600162364 /* ffi_x86_64.h */,
|
||||
6C43CC911535032600162364 /* fficonfig.h */,
|
||||
6C43CC921535032600162364 /* fficonfig_i386.h */,
|
||||
6C43CC931535032600162364 /* fficonfig_x86_64.h */,
|
||||
6C43CC941535032600162364 /* ffitarget.h */,
|
||||
6C43CC951535032600162364 /* ffitarget_i386.h */,
|
||||
6C43CC961535032600162364 /* ffitarget_x86_64.h */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6C43CCA11535039600162364 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CCA21535039600162364 /* ffi.h */,
|
||||
6C43CCA31535039600162364 /* ffi_armv7.h */,
|
||||
6C43CCA41535039600162364 /* ffi_common.h */,
|
||||
6C43CCA51535039600162364 /* ffi_i386.h */,
|
||||
6C43CCA61535039600162364 /* fficonfig.h */,
|
||||
6C43CCA71535039600162364 /* fficonfig_armv7.h */,
|
||||
6C43CCA81535039600162364 /* fficonfig_i386.h */,
|
||||
6C43CCA91535039600162364 /* ffitarget.h */,
|
||||
6C43CCAA1535039600162364 /* ffitarget_arm.h */,
|
||||
6C43CCAB1535039600162364 /* ffitarget_armv7.h */,
|
||||
6C43CCAC1535039600162364 /* ffitarget_i386.h */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F6B0839514721EE50031D8A1 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6C43CC3D1534F7C400162364 /* src */,
|
||||
6C43CBAF1534F76F00162364 /* iOS */,
|
||||
6C43CBF01534F77800162364 /* OS X */,
|
||||
F6F980C6147386260008F121 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F6F980C6147386260008F121 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F6F980BA147386130008F121 /* libffi.a */,
|
||||
6C43CB3D1534E9D100162364 /* libffi.a */,
|
||||
);
|
||||
name = Products;
|
||||
path = ../..;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
6C43CB3B1534E9D100162364 /* Headers */ = {
|
||||
DB13B18F1849DF510010F42D /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6C43CC971535032600162364 /* ffi.h in Headers */,
|
||||
6C43CC981535032600162364 /* ffi_common.h in Headers */,
|
||||
6C43CC991535032600162364 /* ffi_i386.h in Headers */,
|
||||
6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */,
|
||||
6C43CC9E1535032600162364 /* ffitarget.h in Headers */,
|
||||
6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */,
|
||||
6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */,
|
||||
6C43CC9B1535032600162364 /* fficonfig.h in Headers */,
|
||||
6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */,
|
||||
6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F6F980B8147386130008F121 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6C43CCAD1535039600162364 /* ffi.h in Headers */,
|
||||
6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */,
|
||||
6C43CCAF1535039600162364 /* ffi_common.h in Headers */,
|
||||
6C43CCB01535039600162364 /* ffi_i386.h in Headers */,
|
||||
6C43CCB41535039600162364 /* ffitarget.h in Headers */,
|
||||
6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */,
|
||||
6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */,
|
||||
6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */,
|
||||
6C43CCB11535039600162364 /* fficonfig.h in Headers */,
|
||||
6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */,
|
||||
6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */,
|
||||
DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */,
|
||||
DBFA714D187F1D8600A76262 /* ffitarget.h in Headers */,
|
||||
DBFA714A187F1D8600A76262 /* ffi.h in Headers */,
|
||||
DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */,
|
||||
DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */,
|
||||
DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */,
|
||||
DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */,
|
||||
DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */,
|
||||
DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */,
|
||||
DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
6C43CB3C1534E9D100162364 /* libffi OS X */ = {
|
||||
DB13B1651849DF1E0010F42D /* libffi-iOS */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */;
|
||||
buildConfigurationList = DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */;
|
||||
buildPhases = (
|
||||
6C43CC401534FF3B00162364 /* Generate Source and Headers */,
|
||||
6C43CB391534E9D100162364 /* Sources */,
|
||||
6C43CB3A1534E9D100162364 /* Frameworks */,
|
||||
6C43CB3B1534E9D100162364 /* Headers */,
|
||||
DB13B3051849E01C0010F42D /* ShellScript */,
|
||||
DB13B1621849DF1E0010F42D /* Sources */,
|
||||
DB13B1641849DF1E0010F42D /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "libffi OS X";
|
||||
productName = "ffi OS X";
|
||||
productReference = 6C43CB3D1534E9D100162364 /* libffi.a */;
|
||||
name = "libffi-iOS";
|
||||
productName = ffi;
|
||||
productReference = DB13B1661849DF1E0010F42D /* libffi.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
F6F980B9147386130008F121 /* libffi iOS */ = {
|
||||
DB13B1901849DF510010F42D /* libffi-Mac */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */;
|
||||
buildConfigurationList = DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */;
|
||||
buildPhases = (
|
||||
6C43CC3E1534F8E200162364 /* Generate Trampoline */,
|
||||
6C43CC3F1534FF1B00162364 /* Generate Source and Headers */,
|
||||
F6F980B6147386130008F121 /* Sources */,
|
||||
F6F980B7147386130008F121 /* Frameworks */,
|
||||
F6F980B8147386130008F121 /* Headers */,
|
||||
DB13B3061849E0490010F42D /* ShellScript */,
|
||||
DB13B18D1849DF510010F42D /* Sources */,
|
||||
DB13B18F1849DF510010F42D /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "libffi iOS";
|
||||
name = "libffi-Mac";
|
||||
productName = ffi;
|
||||
productReference = F6F980BA147386130008F121 /* libffi.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
productReference = DB13B1911849DF510010F42D /* ffi.dylib */;
|
||||
productType = "com.apple.product-type.library.dynamic";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
F6B0839714721EE50031D8A1 /* Project object */ = {
|
||||
DB13B15C1849DEB70010F42D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0430;
|
||||
LastUpgradeCheck = 0510;
|
||||
};
|
||||
buildConfigurationList = F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */;
|
||||
buildConfigurationList = DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = F6B0839514721EE50031D8A1;
|
||||
productRefGroup = F6B0839514721EE50031D8A1;
|
||||
mainGroup = DB13B15B1849DEB70010F42D;
|
||||
productRefGroup = DB13B1671849DF1E0010F42D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
F6F980B9147386130008F121 /* libffi iOS */,
|
||||
6C43CB3C1534E9D100162364 /* libffi OS X */,
|
||||
DB13B1651849DF1E0010F42D /* libffi-iOS */,
|
||||
DB13B1901849DF510010F42D /* libffi-Mac */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
6C43CC3E1534F8E200162364 /* Generate Trampoline */ = {
|
||||
DB13B3051849E01C0010F42D /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Generate Trampoline";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /usr/bin/python;
|
||||
shellScript = "import subprocess\nimport re\nimport os\nimport errno\nimport sys\n\ndef main():\n with open('src/arm/trampoline.S', 'w') as tramp_out:\n p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)\n p.wait()\n\nif __name__ == '__main__':\n main()";
|
||||
};
|
||||
6C43CC3F1534FF1B00162364 /* Generate Source and Headers */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Generate Source and Headers";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/usr/bin/python generate-ios-source-and-headers.py";
|
||||
shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-ios";
|
||||
};
|
||||
6C43CC401534FF3B00162364 /* Generate Source and Headers */ = {
|
||||
DB13B3061849E0490010F42D /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Generate Source and Headers";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/usr/bin/python generate-osx-source-and-headers.py";
|
||||
shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-osx";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
6C43CB391534E9D100162364 /* Sources */ = {
|
||||
DB13B1621849DF1E0010F42D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6C43CC1F1534F77800162364 /* darwin.S in Sources */,
|
||||
6C43CC201534F77800162364 /* darwin64.S in Sources */,
|
||||
6C43CC211534F77800162364 /* ffi.c in Sources */,
|
||||
6C43CC221534F77800162364 /* ffi64.c in Sources */,
|
||||
6C43CC301534F7BE00162364 /* closures.c in Sources */,
|
||||
6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */,
|
||||
6C43CC381534F7BE00162364 /* prep_cif.c in Sources */,
|
||||
6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */,
|
||||
6C43CC3C1534F7BE00162364 /* types.c in Sources */,
|
||||
DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */,
|
||||
DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */,
|
||||
DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */,
|
||||
DBFA714E187F1D8600A76262 /* closures.c in Sources */,
|
||||
DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */,
|
||||
DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */,
|
||||
DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */,
|
||||
DBFA717F187F1D9B00A76262 /* ffi_i386.c in Sources */,
|
||||
DBFA7158187F1D8600A76262 /* raw_api.c in Sources */,
|
||||
DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */,
|
||||
DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */,
|
||||
DBFA715A187F1D8600A76262 /* types.c in Sources */,
|
||||
DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F6F980B6147386130008F121 /* Sources */ = {
|
||||
DB13B18D1849DF510010F42D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6C43CBDC1534F76F00162364 /* ffi.c in Sources */,
|
||||
6C43CBDD1534F76F00162364 /* sysv.S in Sources */,
|
||||
6C43CBDE1534F76F00162364 /* trampoline.S in Sources */,
|
||||
6C43CBE61534F76F00162364 /* darwin.S in Sources */,
|
||||
6C43CBE81534F76F00162364 /* ffi.c in Sources */,
|
||||
6C43CC2F1534F7BE00162364 /* closures.c in Sources */,
|
||||
6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */,
|
||||
6C43CC371534F7BE00162364 /* prep_cif.c in Sources */,
|
||||
6C43CC391534F7BE00162364 /* raw_api.c in Sources */,
|
||||
6C43CC3B1534F7BE00162364 /* types.c in Sources */,
|
||||
DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */,
|
||||
DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */,
|
||||
DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */,
|
||||
DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */,
|
||||
DBFA715B187F1D8600A76262 /* types.c in Sources */,
|
||||
DBFA7159187F1D8600A76262 /* raw_api.c in Sources */,
|
||||
DBFA714F187F1D8600A76262 /* closures.c in Sources */,
|
||||
DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
6C43CB4B1534E9D100162364 /* Debug */ = {
|
||||
DB13B1601849DEB70010F42D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||
DSTROOT = /tmp/ffi.dst;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
|
||||
"darwin_common/include",
|
||||
);
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_NAME = ffi;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6C43CB4C1534E9D100162364 /* Release */ = {
|
||||
DB13B1611849DEB70010F42D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DSTROOT = /tmp/ffi.dst;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
|
||||
"darwin_common/include",
|
||||
);
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
PRODUCT_NAME = ffi;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F6B083AB14721EE50031D8A1 /* Debug */ = {
|
||||
DB13B1871849DF1E0010F42D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DSTROOT = /tmp/ffi.dst;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
@ -482,98 +457,181 @@
|
|||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VALUE = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = ios/include;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"darwin_ios/include",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
|
||||
"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = ffi;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F6B083AC14721EE50031D8A1 /* Release */ = {
|
||||
DB13B1881849DF1E0010F42D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DSTROOT = /tmp/ffi.dst;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "";
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VALUE = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = ios/include;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"darwin_ios/include",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
|
||||
"IPHONEOS_DEPLOYMENT_TARGET[arch=arm64]" = 7.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = ffi;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F6F980C2147386130008F121 /* Debug */ = {
|
||||
DB13B1B11849DF520010F42D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
armv6,
|
||||
armv7,
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
DSTROOT = /tmp/ffi.dst;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_THUMB_SUPPORT = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"darwin_osx/include",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = "-Wl,-no_compact_unwind";
|
||||
PRODUCT_NAME = ffi;
|
||||
SKIP_INSTALL = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F6F980C3147386130008F121 /* Release */ = {
|
||||
DB13B1B21849DF520010F42D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
armv6,
|
||||
armv7,
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"darwin_osx/include",
|
||||
);
|
||||
DSTROOT = /tmp/ffi.dst;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_THUMB_SUPPORT = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
OTHER_LDFLAGS = "-Wl,-no_compact_unwind";
|
||||
PRODUCT_NAME = ffi;
|
||||
SKIP_INSTALL = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */ = {
|
||||
DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6C43CB4B1534E9D100162364 /* Debug */,
|
||||
6C43CB4C1534E9D100162364 /* Release */,
|
||||
DB13B1601849DEB70010F42D /* Debug */,
|
||||
DB13B1611849DEB70010F42D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */ = {
|
||||
DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F6B083AB14721EE50031D8A1 /* Debug */,
|
||||
F6B083AC14721EE50031D8A1 /* Release */,
|
||||
DB13B1871849DF1E0010F42D /* Debug */,
|
||||
DB13B1881849DF1E0010F42D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */ = {
|
||||
DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F6F980C2147386130008F121 /* Debug */,
|
||||
F6F980C3147386130008F121 /* Release */,
|
||||
DB13B1B11849DF520010F42D /* Debug */,
|
||||
DB13B1B21849DF520010F42D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = F6B0839714721EE50031D8A1 /* Project object */;
|
||||
rootObject = DB13B15C1849DEB70010F42D /* Project object */;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,10 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -149,12 +153,14 @@ SHELL = @SHELL@
|
|||
STRIP = @STRIP@
|
||||
TARGET = @TARGET@
|
||||
TARGETDIR = @TARGETDIR@
|
||||
TARGET_OBJ = @TARGET_OBJ@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
|
|
|
@ -61,10 +61,8 @@ does not refer to a valid ABI,
|
|||
.Nm FFI_BAD_ABI
|
||||
will be returned. Available ABIs are
|
||||
defined in
|
||||
.Nm <ffitarget.h>
|
||||
.
|
||||
.Nm <ffitarget.h> .
|
||||
.Sh SEE ALSO
|
||||
.Xr ffi 3 ,
|
||||
.Xr ffi_call 3 ,
|
||||
.Xr ffi_prep_cif_var 3
|
||||
|
||||
|
|
|
@ -42,8 +42,10 @@
|
|||
# format and translated into something sensible for cl or ml.
|
||||
#
|
||||
|
||||
args_orig=$@
|
||||
args="-nologo -W3"
|
||||
md=-MD
|
||||
static_crt=
|
||||
debug_crt=
|
||||
cl="cl"
|
||||
ml="ml"
|
||||
safeseh="-safeseh"
|
||||
|
@ -62,31 +64,65 @@ do
|
|||
shift 1
|
||||
;;
|
||||
-m64)
|
||||
cl="cl" # "$MSVC/x86_amd64/cl"
|
||||
ml="ml64" # "$MSVC/x86_amd64/ml64"
|
||||
safeseh=
|
||||
shift 1
|
||||
;;
|
||||
-clang-cl)
|
||||
cl="clang-cl"
|
||||
safeseh=
|
||||
shift 1
|
||||
;;
|
||||
-O0)
|
||||
args="$args -Od"
|
||||
shift 1
|
||||
;;
|
||||
-O*)
|
||||
# If we're optimizing, make sure we explicitly turn on some optimizations
|
||||
# that are implicitly disabled by debug symbols (-Zi).
|
||||
args="$args $1 -OPT:REF -OPT:ICF -INCREMENTAL:NO"
|
||||
# Runtime error checks (enabled by setting -RTC1 in the -DFFI_DEBUG
|
||||
# case below) are not compatible with optimization flags and will
|
||||
# cause the build to fail. Therefore, drop the optimization flag if
|
||||
# -DFFI_DEBUG is also set.
|
||||
case $args_orig in
|
||||
*-DFFI_DEBUG*)
|
||||
args="$args"
|
||||
;;
|
||||
*)
|
||||
# The ax_cc_maxopt.m4 macro from the upstream autoconf-archive
|
||||
# project doesn't support MSVC and therefore ends up trying to
|
||||
# use -O3. Use the equivalent "max optimization" flag for MSVC
|
||||
# instead of erroring out.
|
||||
case $1 in
|
||||
-O3)
|
||||
args="$args -O2"
|
||||
;;
|
||||
*)
|
||||
args="$args $1"
|
||||
;;
|
||||
esac
|
||||
opt="true"
|
||||
;;
|
||||
esac
|
||||
shift 1
|
||||
;;
|
||||
-g)
|
||||
# Enable debug symbol generation.
|
||||
args="$args -Zi -DEBUG"
|
||||
args="$args -Zi"
|
||||
shift 1
|
||||
;;
|
||||
-DFFI_DEBUG)
|
||||
# Link against debug CRT and enable runtime error checks.
|
||||
# Enable runtime error checks.
|
||||
args="$args -RTC1"
|
||||
defines="$defines $1"
|
||||
md=-MDd
|
||||
shift 1
|
||||
;;
|
||||
-DUSE_STATIC_RTL)
|
||||
# Link against static CRT.
|
||||
static_crt=1
|
||||
shift 1
|
||||
;;
|
||||
-DUSE_DEBUG_RTL)
|
||||
# Link against debug CRT.
|
||||
debug_crt=1
|
||||
shift 1
|
||||
;;
|
||||
-c)
|
||||
|
@ -126,6 +162,10 @@ do
|
|||
# to do here.
|
||||
shift 1
|
||||
;;
|
||||
-pedantic)
|
||||
# libffi tests -pedantic with -Wall, so drop it also.
|
||||
shift 1
|
||||
;;
|
||||
-Werror)
|
||||
args="$args -WX"
|
||||
shift 1
|
||||
|
@ -170,6 +210,23 @@ do
|
|||
esac
|
||||
done
|
||||
|
||||
# If -Zi is specified, certain optimizations are implicitly disabled
|
||||
# by MSVC. Add back those optimizations if this is an optimized build.
|
||||
# NOTE: These arguments must come after all others.
|
||||
if [ -n "$opt" ]; then
|
||||
args="$args -link -OPT:REF -OPT:ICF -INCREMENTAL:NO"
|
||||
fi
|
||||
|
||||
if [ -n "$static_crt" ]; then
|
||||
md=-MT
|
||||
else
|
||||
md=-MD
|
||||
fi
|
||||
|
||||
if [ -n "$debug_crt" ]; then
|
||||
md="${md}d"
|
||||
fi
|
||||
|
||||
if [ -n "$assembly" ]; then
|
||||
if [ -z "$outdir" ]; then
|
||||
outdir="."
|
||||
|
@ -189,7 +246,10 @@ if [ -n "$assembly" ]; then
|
|||
else
|
||||
args="$md $args"
|
||||
echo "$cl $args"
|
||||
eval "\"$cl\" $args"
|
||||
# Return an error code of 1 if an invalid command line parameter is passed
|
||||
# instead of just ignoring it.
|
||||
eval "(\"$cl\" $args 2>&1 1>&3 | \
|
||||
awk '{print \$0} /D9002/ {error=1} END{exit error}' >&2) 3>&1"
|
||||
result=$?
|
||||
fi
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,18 +42,20 @@ typedef enum ffi_abi
|
|||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 36
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
/* ---- Internal ---- */
|
||||
|
||||
#if defined (__APPLE__)
|
||||
#define FFI_TARGET_SPECIFIC_VARIADIC
|
||||
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
|
||||
#else
|
||||
/* iOS reserves x18 for the system. Disable Go closures until
|
||||
a new static chain is chosen. */
|
||||
#define FFI_GO_CLOSURES 1
|
||||
#endif
|
||||
|
||||
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
|
||||
|
||||
#define AARCH64_FFI_WITH_V_BIT 0
|
||||
|
||||
#define AARCH64_N_XREG 32
|
||||
#define AARCH64_N_VREG 32
|
||||
#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16)
|
||||
#define FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
|
||||
#endif
|
||||
|
|
67
libffi/src/aarch64/internal.h
Normal file
67
libffi/src/aarch64/internal.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
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 AARCH64_RET_VOID 0
|
||||
#define AARCH64_RET_INT64 1
|
||||
#define AARCH64_RET_INT128 2
|
||||
|
||||
#define AARCH64_RET_UNUSED3 3
|
||||
#define AARCH64_RET_UNUSED4 4
|
||||
#define AARCH64_RET_UNUSED5 5
|
||||
#define AARCH64_RET_UNUSED6 6
|
||||
#define AARCH64_RET_UNUSED7 7
|
||||
|
||||
/* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4,
|
||||
so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT). */
|
||||
#define AARCH64_RET_S4 8
|
||||
#define AARCH64_RET_S3 9
|
||||
#define AARCH64_RET_S2 10
|
||||
#define AARCH64_RET_S1 11
|
||||
|
||||
#define AARCH64_RET_D4 12
|
||||
#define AARCH64_RET_D3 13
|
||||
#define AARCH64_RET_D2 14
|
||||
#define AARCH64_RET_D1 15
|
||||
|
||||
#define AARCH64_RET_Q4 16
|
||||
#define AARCH64_RET_Q3 17
|
||||
#define AARCH64_RET_Q2 18
|
||||
#define AARCH64_RET_Q1 19
|
||||
|
||||
/* Note that each of the sub-64-bit integers gets two entries. */
|
||||
#define AARCH64_RET_UINT8 20
|
||||
#define AARCH64_RET_UINT16 22
|
||||
#define AARCH64_RET_UINT32 24
|
||||
|
||||
#define AARCH64_RET_SINT8 26
|
||||
#define AARCH64_RET_SINT16 28
|
||||
#define AARCH64_RET_SINT32 30
|
||||
|
||||
#define AARCH64_RET_MASK 31
|
||||
|
||||
#define AARCH64_RET_IN_MEM (1 << 5)
|
||||
#define AARCH64_RET_NEED_COPY (1 << 6)
|
||||
|
||||
#define AARCH64_FLAG_ARG_V_BIT 7
|
||||
#define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT)
|
||||
|
||||
#define N_X_ARG_REG 8
|
||||
#define N_V_ARG_REG 8
|
||||
#define CALL_CONTEXT_SIZE (N_V_ARG_REG * 16 + N_X_ARG_REG * 8)
|
|
@ -22,286 +22,382 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <ffi_cfi.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
|
||||
#define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
|
||||
#define cfi_restore(reg) .cfi_restore reg
|
||||
#define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a ## b
|
||||
|
||||
.text
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV, #function
|
||||
/* Use the right prefix for global labels. */
|
||||
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
||||
#else
|
||||
#define CNAME(x) x
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ffi_call_SYSV()
|
||||
#ifdef __AARCH64EB__
|
||||
# define BE(X) X
|
||||
#else
|
||||
# define BE(X) 0
|
||||
#endif
|
||||
|
||||
Create a stack frame, setup an argument context, call the callee
|
||||
and extract the result.
|
||||
.text
|
||||
.align 4
|
||||
|
||||
The maximum required argument stack size is provided,
|
||||
ffi_call_SYSV() allocates that stack space then calls the
|
||||
prepare_fn to populate register context and stack. The
|
||||
argument passing registers are loaded from the register
|
||||
context and the callee called, on return the register passing
|
||||
register are saved back to the context. Our caller will
|
||||
extract the return value from the final state of the saved
|
||||
register context.
|
||||
|
||||
Prototype:
|
||||
|
||||
extern unsigned
|
||||
ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *,
|
||||
extended_cif *),
|
||||
struct call_context *context,
|
||||
extended_cif *,
|
||||
unsigned required_stack_size,
|
||||
void (*fn)(void));
|
||||
/* ffi_call_SYSV
|
||||
extern void ffi_call_SYSV (void *stack, void *frame,
|
||||
void (*fn)(void), void *rvalue,
|
||||
int flags, void *closure);
|
||||
|
||||
Therefore on entry we have:
|
||||
|
||||
x0 prepare_fn
|
||||
x1 &context
|
||||
x2 &ecif
|
||||
x3 bytes
|
||||
x4 fn
|
||||
x0 stack
|
||||
x1 frame
|
||||
x2 fn
|
||||
x3 rvalue
|
||||
x4 flags
|
||||
x5 closure
|
||||
*/
|
||||
|
||||
This function uses the following stack frame layout:
|
||||
cfi_startproc
|
||||
CNAME(ffi_call_SYSV):
|
||||
/* Use a stack frame allocated by our caller. */
|
||||
cfi_def_cfa(x1, 32);
|
||||
stp x29, x30, [x1]
|
||||
mov x29, x1
|
||||
mov sp, x0
|
||||
cfi_def_cfa_register(x29)
|
||||
cfi_rel_offset (x29, 0)
|
||||
cfi_rel_offset (x30, 8)
|
||||
|
||||
==
|
||||
saved x30(lr)
|
||||
x29(fp)-> saved x29(fp)
|
||||
saved x24
|
||||
saved x23
|
||||
saved x22
|
||||
sp' -> saved x21
|
||||
...
|
||||
sp -> (constructed callee stack arguments)
|
||||
==
|
||||
mov x9, x2 /* save fn */
|
||||
mov x8, x3 /* install structure return */
|
||||
#ifdef FFI_GO_CLOSURES
|
||||
mov x18, x5 /* install static chain */
|
||||
#endif
|
||||
stp x3, x4, [x29, #16] /* save rvalue and flags */
|
||||
|
||||
Voila! */
|
||||
|
||||
#define ffi_call_SYSV_FS (8 * 4)
|
||||
|
||||
.cfi_startproc
|
||||
ffi_call_SYSV:
|
||||
stp x29, x30, [sp, #-16]!
|
||||
cfi_adjust_cfa_offset (16)
|
||||
cfi_rel_offset (x29, 0)
|
||||
cfi_rel_offset (x30, 8)
|
||||
|
||||
mov x29, sp
|
||||
cfi_def_cfa_register (x29)
|
||||
sub sp, sp, #ffi_call_SYSV_FS
|
||||
|
||||
stp x21, x22, [sp, 0]
|
||||
cfi_rel_offset (x21, 0 - ffi_call_SYSV_FS)
|
||||
cfi_rel_offset (x22, 8 - ffi_call_SYSV_FS)
|
||||
|
||||
stp x23, x24, [sp, 16]
|
||||
cfi_rel_offset (x23, 16 - ffi_call_SYSV_FS)
|
||||
cfi_rel_offset (x24, 24 - ffi_call_SYSV_FS)
|
||||
|
||||
mov x21, x1
|
||||
mov x22, x2
|
||||
mov x24, x4
|
||||
|
||||
/* Allocate the stack space for the actual arguments, many
|
||||
arguments will be passed in registers, but we assume
|
||||
worst case and allocate sufficient stack for ALL of
|
||||
the arguments. */
|
||||
sub sp, sp, x3
|
||||
|
||||
/* unsigned (*prepare_fn) (struct call_context *context,
|
||||
unsigned char *stack, extended_cif *ecif);
|
||||
*/
|
||||
mov x23, x0
|
||||
mov x0, x1
|
||||
mov x1, sp
|
||||
/* x2 already in place */
|
||||
blr x23
|
||||
|
||||
/* Preserve the flags returned. */
|
||||
mov x23, x0
|
||||
|
||||
/* Figure out if we should touch the vector registers. */
|
||||
tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f
|
||||
|
||||
/* Load the vector argument passing registers. */
|
||||
ldp q0, q1, [x21, #8*32 + 0]
|
||||
ldp q2, q3, [x21, #8*32 + 32]
|
||||
ldp q4, q5, [x21, #8*32 + 64]
|
||||
ldp q6, q7, [x21, #8*32 + 96]
|
||||
/* Load the vector argument passing registers, if necessary. */
|
||||
tbz w4, #AARCH64_FLAG_ARG_V_BIT, 1f
|
||||
ldp q0, q1, [sp, #0]
|
||||
ldp q2, q3, [sp, #32]
|
||||
ldp q4, q5, [sp, #64]
|
||||
ldp q6, q7, [sp, #96]
|
||||
1:
|
||||
/* Load the core argument passing registers. */
|
||||
ldp x0, x1, [x21, #0]
|
||||
ldp x2, x3, [x21, #16]
|
||||
ldp x4, x5, [x21, #32]
|
||||
ldp x6, x7, [x21, #48]
|
||||
/* Load the core argument passing registers, including
|
||||
the structure return pointer. */
|
||||
ldp x0, x1, [sp, #16*N_V_ARG_REG + 0]
|
||||
ldp x2, x3, [sp, #16*N_V_ARG_REG + 16]
|
||||
ldp x4, x5, [sp, #16*N_V_ARG_REG + 32]
|
||||
ldp x6, x7, [sp, #16*N_V_ARG_REG + 48]
|
||||
|
||||
/* Don't forget x8 which may be holding the address of a return buffer.
|
||||
*/
|
||||
ldr x8, [x21, #8*8]
|
||||
/* Deallocate the context, leaving the stacked arguments. */
|
||||
add sp, sp, #CALL_CONTEXT_SIZE
|
||||
|
||||
blr x24
|
||||
blr x9 /* call fn */
|
||||
|
||||
/* Save the core argument passing registers. */
|
||||
stp x0, x1, [x21, #0]
|
||||
stp x2, x3, [x21, #16]
|
||||
stp x4, x5, [x21, #32]
|
||||
stp x6, x7, [x21, #48]
|
||||
ldp x3, x4, [x29, #16] /* reload rvalue and flags */
|
||||
|
||||
/* Note nothing useful ever comes back in x8! */
|
||||
|
||||
/* Figure out if we should touch the vector registers. */
|
||||
tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f
|
||||
|
||||
/* Save the vector argument passing registers. */
|
||||
stp q0, q1, [x21, #8*32 + 0]
|
||||
stp q2, q3, [x21, #8*32 + 32]
|
||||
stp q4, q5, [x21, #8*32 + 64]
|
||||
stp q6, q7, [x21, #8*32 + 96]
|
||||
1:
|
||||
/* All done, unwind our stack frame. */
|
||||
ldp x21, x22, [x29, # - ffi_call_SYSV_FS]
|
||||
cfi_restore (x21)
|
||||
cfi_restore (x22)
|
||||
|
||||
ldp x23, x24, [x29, # - ffi_call_SYSV_FS + 16]
|
||||
cfi_restore (x23)
|
||||
cfi_restore (x24)
|
||||
|
||||
mov sp, x29
|
||||
/* Partially deconstruct the stack frame. */
|
||||
mov sp, x29
|
||||
cfi_def_cfa_register (sp)
|
||||
ldp x29, x30, [x29]
|
||||
|
||||
ldp x29, x30, [sp], #16
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
cfi_restore (x29)
|
||||
cfi_restore (x30)
|
||||
/* Save the return value as directed. */
|
||||
adr x5, 0f
|
||||
and w4, w4, #AARCH64_RET_MASK
|
||||
add x5, x5, x4, lsl #3
|
||||
br x5
|
||||
|
||||
ret
|
||||
/* Note that each table entry is 2 insns, and thus 8 bytes.
|
||||
For integer data, note that we're storing into ffi_arg
|
||||
and therefore we want to extend to 64 bits; these types
|
||||
have two consecutive entries allocated for them. */
|
||||
.align 4
|
||||
0: ret /* VOID */
|
||||
nop
|
||||
1: str x0, [x3] /* INT64 */
|
||||
ret
|
||||
2: stp x0, x1, [x3] /* INT128 */
|
||||
ret
|
||||
3: brk #1000 /* UNUSED */
|
||||
ret
|
||||
4: brk #1000 /* UNUSED */
|
||||
ret
|
||||
5: brk #1000 /* UNUSED */
|
||||
ret
|
||||
6: brk #1000 /* UNUSED */
|
||||
ret
|
||||
7: brk #1000 /* UNUSED */
|
||||
ret
|
||||
8: st4 { v0.s-v3.s }[0], [x3] /* S4 */
|
||||
ret
|
||||
9: st3 { v0.s-v2.s }[0], [x3] /* S3 */
|
||||
ret
|
||||
10: stp s0, s1, [x3] /* S2 */
|
||||
ret
|
||||
11: str s0, [x3] /* S1 */
|
||||
ret
|
||||
12: st4 { v0.d-v3.d }[0], [x3] /* D4 */
|
||||
ret
|
||||
13: st3 { v0.d-v2.d }[0], [x3] /* D3 */
|
||||
ret
|
||||
14: stp d0, d1, [x3] /* D2 */
|
||||
ret
|
||||
15: str d0, [x3] /* D1 */
|
||||
ret
|
||||
16: str q3, [x3, #48] /* Q4 */
|
||||
nop
|
||||
17: str q2, [x3, #32] /* Q3 */
|
||||
nop
|
||||
18: stp q0, q1, [x3] /* Q2 */
|
||||
ret
|
||||
19: str q0, [x3] /* Q1 */
|
||||
ret
|
||||
20: uxtb w0, w0 /* UINT8 */
|
||||
str x0, [x3]
|
||||
21: ret /* reserved */
|
||||
nop
|
||||
22: uxth w0, w0 /* UINT16 */
|
||||
str x0, [x3]
|
||||
23: ret /* reserved */
|
||||
nop
|
||||
24: mov w0, w0 /* UINT32 */
|
||||
str x0, [x3]
|
||||
25: ret /* reserved */
|
||||
nop
|
||||
26: sxtb x0, w0 /* SINT8 */
|
||||
str x0, [x3]
|
||||
27: ret /* reserved */
|
||||
nop
|
||||
28: sxth x0, w0 /* SINT16 */
|
||||
str x0, [x3]
|
||||
29: ret /* reserved */
|
||||
nop
|
||||
30: sxtw x0, w0 /* SINT32 */
|
||||
str x0, [x3]
|
||||
31: ret /* reserved */
|
||||
nop
|
||||
|
||||
.cfi_endproc
|
||||
.size ffi_call_SYSV, .-ffi_call_SYSV
|
||||
cfi_endproc
|
||||
|
||||
#define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE)
|
||||
.globl CNAME(ffi_call_SYSV)
|
||||
#ifdef __ELF__
|
||||
.type CNAME(ffi_call_SYSV), #function
|
||||
.hidden CNAME(ffi_call_SYSV)
|
||||
.size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV)
|
||||
#endif
|
||||
|
||||
/* ffi_closure_SYSV
|
||||
|
||||
Closure invocation glue. This is the low level code invoked directly by
|
||||
the closure trampoline to setup and call a closure.
|
||||
|
||||
On entry x17 points to a struct trampoline_data, x16 has been clobbered
|
||||
On entry x17 points to a struct ffi_closure, x16 has been clobbered
|
||||
all other registers are preserved.
|
||||
|
||||
We allocate a call context and save the argument passing registers,
|
||||
then invoked the generic C ffi_closure_SYSV_inner() function to do all
|
||||
the real work, on return we load the result passing registers back from
|
||||
the call context.
|
||||
*/
|
||||
|
||||
On entry
|
||||
#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64)
|
||||
|
||||
extern void
|
||||
ffi_closure_SYSV (struct trampoline_data *);
|
||||
.align 4
|
||||
CNAME(ffi_closure_SYSV_V):
|
||||
cfi_startproc
|
||||
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
|
||||
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
|
||||
cfi_rel_offset (x29, 0)
|
||||
cfi_rel_offset (x30, 8)
|
||||
|
||||
struct trampoline_data
|
||||
{
|
||||
UINT64 *ffi_closure;
|
||||
UINT64 flags;
|
||||
};
|
||||
/* Save the argument passing vector registers. */
|
||||
stp q0, q1, [sp, #16 + 0]
|
||||
stp q2, q3, [sp, #16 + 32]
|
||||
stp q4, q5, [sp, #16 + 64]
|
||||
stp q6, q7, [sp, #16 + 96]
|
||||
b 0f
|
||||
cfi_endproc
|
||||
|
||||
This function uses the following stack frame layout:
|
||||
.globl CNAME(ffi_closure_SYSV_V)
|
||||
#ifdef __ELF__
|
||||
.type CNAME(ffi_closure_SYSV_V), #function
|
||||
.hidden CNAME(ffi_closure_SYSV_V)
|
||||
.size CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V)
|
||||
#endif
|
||||
|
||||
==
|
||||
saved x30(lr)
|
||||
x29(fp)-> saved x29(fp)
|
||||
saved x22
|
||||
saved x21
|
||||
...
|
||||
sp -> call_context
|
||||
==
|
||||
.align 4
|
||||
cfi_startproc
|
||||
CNAME(ffi_closure_SYSV):
|
||||
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
|
||||
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
|
||||
cfi_rel_offset (x29, 0)
|
||||
cfi_rel_offset (x30, 8)
|
||||
0:
|
||||
mov x29, sp
|
||||
|
||||
Voila! */
|
||||
/* Save the argument passing core registers. */
|
||||
stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
|
||||
stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
|
||||
stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
|
||||
stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
|
||||
|
||||
.text
|
||||
.globl ffi_closure_SYSV
|
||||
.cfi_startproc
|
||||
ffi_closure_SYSV:
|
||||
stp x29, x30, [sp, #-16]!
|
||||
cfi_adjust_cfa_offset (16)
|
||||
cfi_rel_offset (x29, 0)
|
||||
cfi_rel_offset (x30, 8)
|
||||
/* Load ffi_closure_inner arguments. */
|
||||
ldp x0, x1, [x17, #FFI_TRAMPOLINE_SIZE] /* load cif, fn */
|
||||
ldr x2, [x17, #FFI_TRAMPOLINE_SIZE+16] /* load user_data */
|
||||
.Ldo_closure:
|
||||
add x3, sp, #16 /* load context */
|
||||
add x4, sp, #ffi_closure_SYSV_FS /* load stack */
|
||||
add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */
|
||||
mov x6, x8 /* load struct_rval */
|
||||
bl CNAME(ffi_closure_SYSV_inner)
|
||||
|
||||
mov x29, sp
|
||||
cfi_def_cfa_register (x29)
|
||||
/* Load the return value as directed. */
|
||||
adr x1, 0f
|
||||
and w0, w0, #AARCH64_RET_MASK
|
||||
add x1, x1, x0, lsl #3
|
||||
add x3, sp, #16+CALL_CONTEXT_SIZE
|
||||
br x1
|
||||
|
||||
sub sp, sp, #ffi_closure_SYSV_FS
|
||||
/* Note that each table entry is 2 insns, and thus 8 bytes. */
|
||||
.align 4
|
||||
0: b 99f /* VOID */
|
||||
nop
|
||||
1: ldr x0, [x3] /* INT64 */
|
||||
b 99f
|
||||
2: ldp x0, x1, [x3] /* INT128 */
|
||||
b 99f
|
||||
3: brk #1000 /* UNUSED */
|
||||
nop
|
||||
4: brk #1000 /* UNUSED */
|
||||
nop
|
||||
5: brk #1000 /* UNUSED */
|
||||
nop
|
||||
6: brk #1000 /* UNUSED */
|
||||
nop
|
||||
7: brk #1000 /* UNUSED */
|
||||
nop
|
||||
8: ldr s3, [x3, #12] /* S4 */
|
||||
nop
|
||||
9: ldr s2, [x2, #8] /* S3 */
|
||||
nop
|
||||
10: ldp s0, s1, [x3] /* S2 */
|
||||
b 99f
|
||||
11: ldr s0, [x3] /* S1 */
|
||||
b 99f
|
||||
12: ldr d3, [x3, #24] /* D4 */
|
||||
nop
|
||||
13: ldr d2, [x3, #16] /* D3 */
|
||||
nop
|
||||
14: ldp d0, d1, [x3] /* D2 */
|
||||
b 99f
|
||||
15: ldr d0, [x3] /* D1 */
|
||||
b 99f
|
||||
16: ldr q3, [x3, #48] /* Q4 */
|
||||
nop
|
||||
17: ldr q2, [x3, #32] /* Q3 */
|
||||
nop
|
||||
18: ldp q0, q1, [x3] /* Q2 */
|
||||
b 99f
|
||||
19: ldr q0, [x3] /* Q1 */
|
||||
b 99f
|
||||
20: ldrb w0, [x3, #BE(7)] /* UINT8 */
|
||||
b 99f
|
||||
21: brk #1000 /* reserved */
|
||||
nop
|
||||
22: ldrh w0, [x3, #BE(6)] /* UINT16 */
|
||||
b 99f
|
||||
23: brk #1000 /* reserved */
|
||||
nop
|
||||
24: ldr w0, [x3, #BE(4)] /* UINT32 */
|
||||
b 99f
|
||||
25: brk #1000 /* reserved */
|
||||
nop
|
||||
26: ldrsb x0, [x3, #BE(7)] /* SINT8 */
|
||||
b 99f
|
||||
27: brk #1000 /* reserved */
|
||||
nop
|
||||
28: ldrsh x0, [x3, #BE(6)] /* SINT16 */
|
||||
b 99f
|
||||
29: brk #1000 /* reserved */
|
||||
nop
|
||||
30: ldrsw x0, [x3, #BE(4)] /* SINT32 */
|
||||
nop
|
||||
31: /* reserved */
|
||||
99: ldp x29, x30, [sp], #ffi_closure_SYSV_FS
|
||||
cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
|
||||
cfi_restore (x29)
|
||||
cfi_restore (x30)
|
||||
ret
|
||||
cfi_endproc
|
||||
|
||||
stp x21, x22, [x29, #-16]
|
||||
cfi_rel_offset (x21, -16)
|
||||
cfi_rel_offset (x22, -8)
|
||||
.globl CNAME(ffi_closure_SYSV)
|
||||
#ifdef __ELF__
|
||||
.type CNAME(ffi_closure_SYSV), #function
|
||||
.hidden CNAME(ffi_closure_SYSV)
|
||||
.size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
|
||||
#endif
|
||||
|
||||
/* Load x21 with &call_context. */
|
||||
mov x21, sp
|
||||
/* Preserve our struct trampoline_data * */
|
||||
mov x22, x17
|
||||
#ifdef FFI_GO_CLOSURES
|
||||
.align 4
|
||||
CNAME(ffi_go_closure_SYSV_V):
|
||||
cfi_startproc
|
||||
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
|
||||
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
|
||||
cfi_rel_offset (x29, 0)
|
||||
cfi_rel_offset (x30, 8)
|
||||
|
||||
/* Save the rest of the argument passing registers. */
|
||||
stp x0, x1, [x21, #0]
|
||||
stp x2, x3, [x21, #16]
|
||||
stp x4, x5, [x21, #32]
|
||||
stp x6, x7, [x21, #48]
|
||||
/* Don't forget we may have been given a result scratch pad address.
|
||||
*/
|
||||
str x8, [x21, #64]
|
||||
/* Save the argument passing vector registers. */
|
||||
stp q0, q1, [sp, #16 + 0]
|
||||
stp q2, q3, [sp, #16 + 32]
|
||||
stp q4, q5, [sp, #16 + 64]
|
||||
stp q6, q7, [sp, #16 + 96]
|
||||
b 0f
|
||||
cfi_endproc
|
||||
|
||||
/* Figure out if we should touch the vector registers. */
|
||||
ldr x0, [x22, #8]
|
||||
tbz x0, #AARCH64_FFI_WITH_V_BIT, 1f
|
||||
.globl CNAME(ffi_go_closure_SYSV_V)
|
||||
#ifdef __ELF__
|
||||
.type CNAME(ffi_go_closure_SYSV_V), #function
|
||||
.hidden CNAME(ffi_go_closure_SYSV_V)
|
||||
.size CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V)
|
||||
#endif
|
||||
|
||||
/* Save the argument passing vector registers. */
|
||||
stp q0, q1, [x21, #8*32 + 0]
|
||||
stp q2, q3, [x21, #8*32 + 32]
|
||||
stp q4, q5, [x21, #8*32 + 64]
|
||||
stp q6, q7, [x21, #8*32 + 96]
|
||||
1:
|
||||
/* Load &ffi_closure.. */
|
||||
ldr x0, [x22, #0]
|
||||
mov x1, x21
|
||||
/* Compute the location of the stack at the point that the
|
||||
trampoline was called. */
|
||||
add x2, x29, #16
|
||||
.align 4
|
||||
cfi_startproc
|
||||
CNAME(ffi_go_closure_SYSV):
|
||||
stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
|
||||
cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
|
||||
cfi_rel_offset (x29, 0)
|
||||
cfi_rel_offset (x30, 8)
|
||||
0:
|
||||
mov x29, sp
|
||||
|
||||
bl ffi_closure_SYSV_inner
|
||||
/* Save the argument passing core registers. */
|
||||
stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
|
||||
stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
|
||||
stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
|
||||
stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
|
||||
|
||||
/* Figure out if we should touch the vector registers. */
|
||||
ldr x0, [x22, #8]
|
||||
tbz x0, #AARCH64_FFI_WITH_V_BIT, 1f
|
||||
/* Load ffi_closure_inner arguments. */
|
||||
ldp x0, x1, [x18, #8] /* load cif, fn */
|
||||
mov x2, x18 /* load user_data */
|
||||
b .Ldo_closure
|
||||
cfi_endproc
|
||||
|
||||
/* Load the result passing vector registers. */
|
||||
ldp q0, q1, [x21, #8*32 + 0]
|
||||
ldp q2, q3, [x21, #8*32 + 32]
|
||||
ldp q4, q5, [x21, #8*32 + 64]
|
||||
ldp q6, q7, [x21, #8*32 + 96]
|
||||
1:
|
||||
/* Load the result passing core registers. */
|
||||
ldp x0, x1, [x21, #0]
|
||||
ldp x2, x3, [x21, #16]
|
||||
ldp x4, x5, [x21, #32]
|
||||
ldp x6, x7, [x21, #48]
|
||||
/* Note nothing usefull is returned in x8. */
|
||||
.globl CNAME(ffi_go_closure_SYSV)
|
||||
#ifdef __ELF__
|
||||
.type CNAME(ffi_go_closure_SYSV), #function
|
||||
.hidden CNAME(ffi_go_closure_SYSV)
|
||||
.size CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV)
|
||||
#endif
|
||||
#endif /* FFI_GO_CLOSURES */
|
||||
|
||||
/* We are done, unwind our frame. */
|
||||
ldp x21, x22, [x29, #-16]
|
||||
cfi_restore (x21)
|
||||
cfi_restore (x22)
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
||||
mov sp, x29
|
||||
cfi_def_cfa_register (sp)
|
||||
|
||||
ldp x29, x30, [sp], #16
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
cfi_restore (x29)
|
||||
cfi_restore (x30)
|
||||
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size ffi_closure_SYSV, .-ffi_closure_SYSV
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2012 Anthony Green
|
||||
Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Alpha Foreign Function Interface
|
||||
Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Alpha Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
#include "internal.h"
|
||||
|
||||
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
|
||||
all further uses in this file will refer to the 128-bit type. */
|
||||
|
@ -39,135 +41,286 @@
|
|||
# define FFI_TYPE_LONGDOUBLE 4
|
||||
#endif
|
||||
|
||||
extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void))
|
||||
FFI_HIDDEN;
|
||||
extern void ffi_call_osf(void *stack, void *frame, unsigned flags,
|
||||
void *raddr, void (*fn)(void), void *closure)
|
||||
FFI_HIDDEN;
|
||||
extern void ffi_closure_osf(void) FFI_HIDDEN;
|
||||
extern void ffi_go_closure_osf(void) FFI_HIDDEN;
|
||||
|
||||
/* Promote a float value to its in-register double representation.
|
||||
Unlike actually casting to double, this does not trap on NaN. */
|
||||
static inline UINT64 lds(void *ptr)
|
||||
{
|
||||
UINT64 ret;
|
||||
asm("lds %0,%1" : "=f"(ret) : "m"(*(UINT32 *)ptr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ffi_status
|
||||
/* And the reverse. */
|
||||
static inline void sts(void *ptr, UINT64 val)
|
||||
{
|
||||
asm("sts %1,%0" : "=m"(*(UINT32 *)ptr) : "f"(val));
|
||||
}
|
||||
|
||||
ffi_status FFI_HIDDEN
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Adjust cif->bytes to represent a minimum 6 words for the temporary
|
||||
register argument loading area. */
|
||||
if (cif->bytes < 6*FFI_SIZEOF_ARG)
|
||||
cif->bytes = 6*FFI_SIZEOF_ARG;
|
||||
size_t bytes = 0;
|
||||
int flags, i, avn;
|
||||
ffi_type *rtype, *itype;
|
||||
|
||||
if (cif->abi != FFI_OSF)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
/* Compute the size of the argument area. */
|
||||
for (i = 0, avn = cif->nargs; i < avn; i++)
|
||||
{
|
||||
itype = cif->arg_types[i];
|
||||
switch (itype->type)
|
||||
{
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* All take one 8 byte slot. */
|
||||
bytes += 8;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Passed by value in N slots. */
|
||||
bytes += ALIGN(itype->size, FFI_SIZEOF_ARG);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* _Complex long double passed by reference; others in 2 slots. */
|
||||
if (itype->elements[0]->type == FFI_TYPE_LONGDOUBLE)
|
||||
bytes += 8;
|
||||
else
|
||||
bytes += 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
rtype = cif->rtype;
|
||||
switch (rtype->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_VOID:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_VOID, ALPHA_LD_VOID);
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT32);
|
||||
break;
|
||||
case FFI_TYPE_FLOAT:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_FLOAT, ALPHA_LD_FLOAT);
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = cif->rtype->type;
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_DOUBLE, ALPHA_LD_DOUBLE);
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT8);
|
||||
break;
|
||||
case FFI_TYPE_SINT8:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT8);
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT16);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT16);
|
||||
break;
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* 128-bit long double is returned in memory, like a struct. */
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Passed in memory, with a hidden pointer. */
|
||||
flags = ALPHA_RET_IN_MEM;
|
||||
break;
|
||||
case FFI_TYPE_COMPLEX:
|
||||
itype = rtype->elements[0];
|
||||
switch (itype->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_CPLXF, ALPHA_LD_CPLXF);
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_CPLXD, ALPHA_LD_CPLXD);
|
||||
break;
|
||||
default:
|
||||
if (rtype->size <= 8)
|
||||
flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
|
||||
else
|
||||
flags = ALPHA_RET_IN_MEM;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
abort();
|
||||
}
|
||||
|
||||
cif->flags = flags;
|
||||
|
||||
/* Include the hidden structure pointer in args requirement. */
|
||||
if (flags == ALPHA_RET_IN_MEM)
|
||||
bytes += 8;
|
||||
/* Minimum size is 6 slots, so that ffi_call_osf can pop them. */
|
||||
if (bytes < 6*8)
|
||||
bytes = 6*8;
|
||||
cif->bytes = bytes;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
static unsigned long
|
||||
extend_basic_type(void *valp, int type, int argn)
|
||||
{
|
||||
unsigned long *stack, *argp;
|
||||
long i, avn;
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
return *(SINT8 *)valp;
|
||||
case FFI_TYPE_UINT8:
|
||||
return *(UINT8 *)valp;
|
||||
case FFI_TYPE_SINT16:
|
||||
return *(SINT16 *)valp;
|
||||
case FFI_TYPE_UINT16:
|
||||
return *(UINT16 *)valp;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (argn < 6)
|
||||
return lds(valp);
|
||||
/* FALLTHRU */
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
/* Note that unsigned 32-bit quantities are sign extended. */
|
||||
return *(SINT32 *)valp;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
return *(UINT64 *)valp;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, void *closure)
|
||||
{
|
||||
unsigned long *argp;
|
||||
long i, avn, argn, flags = cif->flags;
|
||||
ffi_type **arg_types;
|
||||
|
||||
void *frame;
|
||||
|
||||
/* If the return value is a struct and we don't have a return
|
||||
value address then we need to make one. */
|
||||
if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT)
|
||||
if (rvalue == NULL && flags == ALPHA_RET_IN_MEM)
|
||||
rvalue = alloca(cif->rtype->size);
|
||||
|
||||
/* Allocate the space for the arguments, plus 4 words of temp
|
||||
space for ffi_call_osf. */
|
||||
argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
|
||||
argp = frame = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
|
||||
frame += cif->bytes;
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
*(void **) argp++ = rvalue;
|
||||
argn = 0;
|
||||
if (flags == ALPHA_RET_IN_MEM)
|
||||
argp[argn++] = (unsigned long)rvalue;
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
while (i < avn)
|
||||
for (i = 0, avn = cif->nargs; i < avn; i++)
|
||||
{
|
||||
size_t size = (*arg_types)->size;
|
||||
ffi_type *ty = arg_types[i];
|
||||
void *valp = avalue[i];
|
||||
int type = ty->type;
|
||||
size_t size;
|
||||
|
||||
switch ((*arg_types)->type)
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT64 *) argp = *(SINT8 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(SINT64 *) argp = *(UINT8 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT64 *) argp = *(SINT16 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(SINT64 *) argp = *(UINT16 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
/* Note that unsigned 32-bit quantities are sign extended. */
|
||||
*(SINT64 *) argp = *(SINT32 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(UINT64 *) argp = *(UINT64 *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (argp - stack < 6)
|
||||
{
|
||||
/* Note the conversion -- all the fp regs are loaded as
|
||||
doubles. The in-register format is the same. */
|
||||
*(double *) argp = *(float *)(* avalue);
|
||||
}
|
||||
else
|
||||
*(float *) argp = *(float *)(* avalue);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*(double *) argp = *(double *)(* avalue);
|
||||
argp[argn] = extend_basic_type(valp, type, argn);
|
||||
argn++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* 128-bit long double is passed by reference. */
|
||||
*(long double **) argp = (long double *)(* avalue);
|
||||
size = sizeof (long double *);
|
||||
by_reference:
|
||||
/* Note that 128-bit long double is passed by reference. */
|
||||
argp[argn++] = (unsigned long)valp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *avalue, (*arg_types)->size);
|
||||
size = ty->size;
|
||||
memcpy(argp + argn, valp, size);
|
||||
argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
type = ty->elements[0]->type;
|
||||
if (type == FFI_TYPE_LONGDOUBLE)
|
||||
goto by_reference;
|
||||
|
||||
/* Most complex types passed as two separate arguments. */
|
||||
size = ty->elements[0]->size;
|
||||
argp[argn] = extend_basic_type(valp, type, argn);
|
||||
argp[argn + 1] = extend_basic_type(valp + size, type, argn + 1);
|
||||
argn += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
abort();
|
||||
}
|
||||
|
||||
argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
i++, arg_types++, avalue++;
|
||||
}
|
||||
|
||||
ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
|
||||
flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
|
||||
ffi_call_osf(argp, frame, flags, rvalue, fn, closure);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
ffi_call_int(cif, fn, rvalue, avalue, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, void *closure)
|
||||
{
|
||||
ffi_call_int(cif, fn, rvalue, avalue, closure);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
|
@ -203,39 +356,56 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_go_closure (ffi_go_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*))
|
||||
{
|
||||
if (cif->abi != FFI_OSF)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
closure->tramp = (void *)ffi_go_closure_osf;
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
long FFI_HIDDEN
|
||||
ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
|
||||
ffi_closure_osf_inner (ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *rvalue, unsigned long *argp)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
ffi_type **arg_types;
|
||||
long i, avn, argn;
|
||||
long i, avn, argn, flags;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
||||
flags = cif->flags;
|
||||
argn = 0;
|
||||
|
||||
/* Copy the caller's structure return address to that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
if (flags == ALPHA_RET_IN_MEM)
|
||||
{
|
||||
rvalue = (void *) argp[0];
|
||||
argn = 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
while (i < avn)
|
||||
{
|
||||
size_t size = arg_types[i]->size;
|
||||
|
||||
switch (arg_types[i]->type)
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0, avn = cif->nargs; i < avn; i++)
|
||||
{
|
||||
ffi_type *ty = arg_types[i];
|
||||
int type = ty->type;
|
||||
void *valp = &argp[argn];
|
||||
size_t size;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
|
@ -245,43 +415,107 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
|
|||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
argn += 1;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = &argp[argn];
|
||||
size = ty->size;
|
||||
argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* Floats coming from registers need conversion from double
|
||||
back to float format. */
|
||||
if (argn < 6)
|
||||
{
|
||||
/* Floats coming from registers need conversion from double
|
||||
back to float format. */
|
||||
*(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
|
||||
avalue[i] = &argp[argn - 6];
|
||||
valp = &argp[argn - 6];
|
||||
sts(valp, argp[argn - 6]);
|
||||
}
|
||||
else
|
||||
avalue[i] = &argp[argn];
|
||||
argn += 1;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
|
||||
if (argn < 6)
|
||||
valp = &argp[argn - 6];
|
||||
argn += 1;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
by_reference:
|
||||
/* 128-bit long double is passed by reference. */
|
||||
avalue[i] = (long double *) argp[argn];
|
||||
size = sizeof (long double *);
|
||||
valp = (void *)argp[argn];
|
||||
argn += 1;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
type = ty->elements[0]->type;
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
/* Passed as separate arguments, but they wind up sequential. */
|
||||
break;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
/* Passed as separate arguments. Disjoint, but there's room
|
||||
enough in one slot to hold the pair. */
|
||||
size = ty->elements[0]->size;
|
||||
memcpy(valp + size, valp + 8, size);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* Passed as separate arguments. Disjoint, and each piece
|
||||
may need conversion back to float. */
|
||||
if (argn < 6)
|
||||
{
|
||||
valp = &argp[argn - 6];
|
||||
sts(valp, argp[argn - 6]);
|
||||
}
|
||||
if (argn + 1 < 6)
|
||||
sts(valp + 4, argp[argn + 1 - 6]);
|
||||
else
|
||||
*(UINT32 *)(valp + 4) = argp[argn + 1];
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* Passed as separate arguments. Only disjoint if one part
|
||||
is in fp regs and the other is on the stack. */
|
||||
if (argn < 5)
|
||||
valp = &argp[argn - 6];
|
||||
else if (argn == 5)
|
||||
{
|
||||
valp = alloca(16);
|
||||
((UINT64 *)valp)[0] = argp[5 - 6];
|
||||
((UINT64 *)valp)[1] = argp[6];
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
goto by_reference;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
argn += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
abort ();
|
||||
}
|
||||
|
||||
argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
i++;
|
||||
avalue[i] = valp;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||
fun (cif, rvalue, avalue, user_data);
|
||||
|
||||
/* Tell ffi_closure_osf how to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
return (flags >> ALPHA_LD_SHIFT) & 0xff;
|
||||
}
|
||||
|
|
|
@ -44,9 +44,13 @@ typedef enum ffi_abi {
|
|||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
#define FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_GO_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
|
|
23
libffi/src/alpha/internal.h
Normal file
23
libffi/src/alpha/internal.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#define ALPHA_ST_VOID 0
|
||||
#define ALPHA_ST_INT 1
|
||||
#define ALPHA_ST_FLOAT 2
|
||||
#define ALPHA_ST_DOUBLE 3
|
||||
#define ALPHA_ST_CPLXF 4
|
||||
#define ALPHA_ST_CPLXD 5
|
||||
|
||||
#define ALPHA_LD_VOID 0
|
||||
#define ALPHA_LD_INT64 1
|
||||
#define ALPHA_LD_INT32 2
|
||||
#define ALPHA_LD_UINT16 3
|
||||
#define ALPHA_LD_SINT16 4
|
||||
#define ALPHA_LD_UINT8 5
|
||||
#define ALPHA_LD_SINT8 6
|
||||
#define ALPHA_LD_FLOAT 7
|
||||
#define ALPHA_LD_DOUBLE 8
|
||||
#define ALPHA_LD_CPLXF 9
|
||||
#define ALPHA_LD_CPLXD 10
|
||||
|
||||
#define ALPHA_ST_SHIFT 0
|
||||
#define ALPHA_LD_SHIFT 8
|
||||
#define ALPHA_RET_IN_MEM 0x10000
|
||||
#define ALPHA_FLAGS(S, L) (((L) << ALPHA_LD_SHIFT) | (S))
|
|
@ -1,7 +1,7 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat
|
||||
|
||||
Alpha/OSF Foreign Function Interface
|
||||
osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat
|
||||
|
||||
Alpha/OSF Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -24,40 +24,49 @@
|
|||
DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <ffi_cfi.h>
|
||||
#include "internal.h"
|
||||
|
||||
.arch ev6
|
||||
.text
|
||||
|
||||
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
|
||||
void *raddr, void (*fnaddr)(void));
|
||||
/* Aid in building a direct addressed jump table, 4 insns per entry. */
|
||||
.macro E index
|
||||
.align 4
|
||||
.org 99b + \index * 16
|
||||
.endm
|
||||
|
||||
Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
|
||||
/* ffi_call_osf (void *stack, void *frame, unsigned flags,
|
||||
void *raddr, void (*fnaddr)(void), void *closure)
|
||||
|
||||
Bit o trickiness here -- FRAME is the base of the stack frame
|
||||
for this function. This has been allocated by ffi_call. We also
|
||||
deallocate some of the stack that has been alloca'd. */
|
||||
|
||||
.align 3
|
||||
.align 4
|
||||
.globl ffi_call_osf
|
||||
.ent ffi_call_osf
|
||||
FFI_HIDDEN(ffi_call_osf)
|
||||
|
||||
ffi_call_osf:
|
||||
.frame $15, 32, $26, 0
|
||||
.mask 0x4008000, -32
|
||||
$LFB1:
|
||||
addq $16,$17,$1
|
||||
cfi_startproc
|
||||
cfi_def_cfa($17, 32)
|
||||
mov $16, $30
|
||||
stq $26, 0($1)
|
||||
stq $15, 8($1)
|
||||
stq $18, 16($1)
|
||||
mov $1, $15
|
||||
$LCFI1:
|
||||
stq $26, 0($17)
|
||||
stq $15, 8($17)
|
||||
mov $17, $15
|
||||
.prologue 0
|
||||
cfi_def_cfa_register($15)
|
||||
cfi_rel_offset($26, 0)
|
||||
cfi_rel_offset($15, 8)
|
||||
|
||||
stq $19, 24($1)
|
||||
mov $20, $27
|
||||
stq $18, 16($17) # save flags into frame
|
||||
stq $19, 24($17) # save rvalue into frame
|
||||
mov $20, $27 # fn into place for call
|
||||
mov $21, $1 # closure into static chain
|
||||
|
||||
# Load up all of the (potential) argument registers.
|
||||
ldq $16, 0($30)
|
||||
|
@ -77,310 +86,196 @@ $LCFI1:
|
|||
lda $30, 48($30)
|
||||
|
||||
jsr $26, ($27), 0
|
||||
ldgp $29, 0($26)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
ldq $19, 24($15)
|
||||
ldq $18, 16($15)
|
||||
0:
|
||||
ldah $29, 0($26) !gpdisp!1
|
||||
ldq $2, 24($15) # reload rvalue
|
||||
lda $29, 0($29) !gpdisp!1
|
||||
ldq $3, 16($15) # reload flags
|
||||
lda $1, 99f-0b($26)
|
||||
ldq $26, 0($15)
|
||||
$LCFI2:
|
||||
beq $19, $noretval
|
||||
|
||||
# Store the return value out in the proper type.
|
||||
cmpeq $18, FFI_TYPE_INT, $1
|
||||
bne $1, $retint
|
||||
cmpeq $18, FFI_TYPE_FLOAT, $2
|
||||
bne $2, $retfloat
|
||||
cmpeq $18, FFI_TYPE_DOUBLE, $3
|
||||
bne $3, $retdouble
|
||||
|
||||
.align 3
|
||||
$noretval:
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
cfi_restore($26)
|
||||
cfi_restore($15)
|
||||
cfi_def_cfa($sp, 0)
|
||||
cmoveq $2, ALPHA_ST_VOID, $3 # mash null rvalue to void
|
||||
addq $3, $3, $3
|
||||
s8addq $3, $1, $1 # 99f + stcode * 16
|
||||
jmp $31, ($1), $st_int
|
||||
|
||||
.align 4
|
||||
$retint:
|
||||
stq $0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
99:
|
||||
E ALPHA_ST_VOID
|
||||
ret
|
||||
E ALPHA_ST_INT
|
||||
$st_int:
|
||||
stq $0, 0($2)
|
||||
ret
|
||||
E ALPHA_ST_FLOAT
|
||||
sts $f0, 0($2)
|
||||
ret
|
||||
E ALPHA_ST_DOUBLE
|
||||
stt $f0, 0($2)
|
||||
ret
|
||||
E ALPHA_ST_CPLXF
|
||||
sts $f0, 0($2)
|
||||
sts $f1, 4($2)
|
||||
ret
|
||||
E ALPHA_ST_CPLXD
|
||||
stt $f0, 0($2)
|
||||
stt $f1, 8($2)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retfloat:
|
||||
sts $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$retdouble:
|
||||
stt $f0, 0($19)
|
||||
nop
|
||||
ldq $15, 8($15)
|
||||
ret
|
||||
$LFE1:
|
||||
|
||||
cfi_endproc
|
||||
.end ffi_call_osf
|
||||
|
||||
/* ffi_closure_osf(...)
|
||||
|
||||
Receives the closure argument in $1. */
|
||||
|
||||
.align 3
|
||||
#define CLOSURE_FS (16*8)
|
||||
|
||||
.align 4
|
||||
.globl ffi_go_closure_osf
|
||||
.ent ffi_go_closure_osf
|
||||
FFI_HIDDEN(ffi_go_closure_osf)
|
||||
|
||||
ffi_go_closure_osf:
|
||||
cfi_startproc
|
||||
ldgp $29, 0($27)
|
||||
subq $30, CLOSURE_FS, $30
|
||||
cfi_adjust_cfa_offset(CLOSURE_FS)
|
||||
stq $26, 0($30)
|
||||
.prologue 1
|
||||
cfi_rel_offset($26, 0)
|
||||
|
||||
stq $16, 10*8($30)
|
||||
stq $17, 11*8($30)
|
||||
stq $18, 12*8($30)
|
||||
|
||||
ldq $16, 8($1) # load cif
|
||||
ldq $17, 16($1) # load fun
|
||||
mov $1, $18 # closure is user_data
|
||||
br $do_closure
|
||||
|
||||
cfi_endproc
|
||||
.end ffi_go_closure_osf
|
||||
|
||||
.align 4
|
||||
.globl ffi_closure_osf
|
||||
.ent ffi_closure_osf
|
||||
FFI_HIDDEN(ffi_closure_osf)
|
||||
|
||||
ffi_closure_osf:
|
||||
.frame $30, 16*8, $26, 0
|
||||
.mask 0x4000000, -16*8
|
||||
$LFB2:
|
||||
cfi_startproc
|
||||
ldgp $29, 0($27)
|
||||
subq $30, 16*8, $30
|
||||
$LCFI5:
|
||||
subq $30, CLOSURE_FS, $30
|
||||
cfi_adjust_cfa_offset(CLOSURE_FS)
|
||||
stq $26, 0($30)
|
||||
$LCFI6:
|
||||
.prologue 1
|
||||
cfi_rel_offset($26, 0)
|
||||
|
||||
# Store all of the potential argument registers in va_list format.
|
||||
stq $16, 10*8($30)
|
||||
stq $17, 11*8($30)
|
||||
stq $18, 12*8($30)
|
||||
|
||||
ldq $16, 24($1) # load cif
|
||||
ldq $17, 32($1) # load fun
|
||||
ldq $18, 40($1) # load user_data
|
||||
|
||||
$do_closure:
|
||||
stq $19, 13*8($30)
|
||||
stq $20, 14*8($30)
|
||||
stq $21, 15*8($30)
|
||||
stt $f16, 4*8($30)
|
||||
stt $f17, 5*8($30)
|
||||
stt $f18, 6*8($30)
|
||||
stt $f19, 7*8($30)
|
||||
stt $f20, 8*8($30)
|
||||
stt $f21, 9*8($30)
|
||||
stq $16, 10*8($30)
|
||||
stq $17, 11*8($30)
|
||||
stq $18, 12*8($30)
|
||||
stq $19, 13*8($30)
|
||||
stq $20, 14*8($30)
|
||||
stq $21, 15*8($30)
|
||||
|
||||
# Call ffi_closure_osf_inner to do the bulk of the work.
|
||||
mov $1, $16
|
||||
lda $17, 2*8($30)
|
||||
lda $18, 10*8($30)
|
||||
lda $19, 2*8($30)
|
||||
lda $20, 10*8($30)
|
||||
jsr $26, ffi_closure_osf_inner
|
||||
ldgp $29, 0($26)
|
||||
0:
|
||||
ldah $29, 0($26) !gpdisp!2
|
||||
lda $2, 99f-0b($26)
|
||||
s4addq $0, 0, $1 # ldcode * 4
|
||||
ldq $0, 16($30) # preload return value
|
||||
s4addq $1, $2, $1 # 99f + ldcode * 16
|
||||
lda $29, 0($29) !gpdisp!2
|
||||
ldq $26, 0($30)
|
||||
|
||||
# Load up the return value in the proper type.
|
||||
lda $1, $load_table
|
||||
s4addq $0, $1, $1
|
||||
ldl $1, 0($1)
|
||||
addq $1, $29, $1
|
||||
cfi_restore($26)
|
||||
jmp $31, ($1), $load_32
|
||||
|
||||
.align 4
|
||||
$load_none:
|
||||
addq $30, 16*8, $30
|
||||
.macro epilogue
|
||||
addq $30, CLOSURE_FS, $30
|
||||
cfi_adjust_cfa_offset(-CLOSURE_FS)
|
||||
ret
|
||||
.align 4
|
||||
cfi_adjust_cfa_offset(CLOSURE_FS)
|
||||
.endm
|
||||
|
||||
.align 4
|
||||
$load_float:
|
||||
lds $f0, 16($30)
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
99:
|
||||
E ALPHA_LD_VOID
|
||||
epilogue
|
||||
|
||||
.align 4
|
||||
$load_double:
|
||||
ldt $f0, 16($30)
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
E ALPHA_LD_INT64
|
||||
epilogue
|
||||
|
||||
.align 4
|
||||
$load_u8:
|
||||
#ifdef __alpha_bwx__
|
||||
ldbu $0, 16($30)
|
||||
nop
|
||||
#else
|
||||
ldq $0, 16($30)
|
||||
and $0, 255, $0
|
||||
#endif
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
E ALPHA_LD_INT32
|
||||
$load_32:
|
||||
sextl $0, $0
|
||||
epilogue
|
||||
|
||||
.align 4
|
||||
$load_s8:
|
||||
#ifdef __alpha_bwx__
|
||||
ldbu $0, 16($30)
|
||||
sextb $0, $0
|
||||
#else
|
||||
ldq $0, 16($30)
|
||||
sll $0, 56, $0
|
||||
sra $0, 56, $0
|
||||
#endif
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
|
||||
.align 4
|
||||
$load_u16:
|
||||
#ifdef __alpha_bwx__
|
||||
ldwu $0, 16($30)
|
||||
nop
|
||||
#else
|
||||
ldq $0, 16($30)
|
||||
E ALPHA_LD_UINT16
|
||||
zapnot $0, 3, $0
|
||||
#endif
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
epilogue
|
||||
|
||||
.align 4
|
||||
$load_s16:
|
||||
E ALPHA_LD_SINT16
|
||||
#ifdef __alpha_bwx__
|
||||
ldwu $0, 16($30)
|
||||
sextw $0, $0
|
||||
#else
|
||||
ldq $0, 16($30)
|
||||
sll $0, 48, $0
|
||||
sra $0, 48, $0
|
||||
#endif
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
epilogue
|
||||
|
||||
.align 4
|
||||
$load_32:
|
||||
ldl $0, 16($30)
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
E ALPHA_LD_UINT8
|
||||
and $0, 0xff, $0
|
||||
epilogue
|
||||
|
||||
.align 4
|
||||
$load_64:
|
||||
ldq $0, 16($30)
|
||||
nop
|
||||
addq $30, 16*8, $30
|
||||
ret
|
||||
$LFE2:
|
||||
|
||||
.end ffi_closure_osf
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .rodata
|
||||
E ALPHA_LD_SINT8
|
||||
#ifdef __alpha_bwx__
|
||||
sextb $0, $0
|
||||
#else
|
||||
.rdata
|
||||
sll $0, 56, $0
|
||||
sra $0, 56, $0
|
||||
#endif
|
||||
$load_table:
|
||||
.gprel32 $load_none # FFI_TYPE_VOID
|
||||
.gprel32 $load_32 # FFI_TYPE_INT
|
||||
.gprel32 $load_float # FFI_TYPE_FLOAT
|
||||
.gprel32 $load_double # FFI_TYPE_DOUBLE
|
||||
.gprel32 $load_none # FFI_TYPE_LONGDOUBLE
|
||||
.gprel32 $load_u8 # FFI_TYPE_UINT8
|
||||
.gprel32 $load_s8 # FFI_TYPE_SINT8
|
||||
.gprel32 $load_u16 # FFI_TYPE_UINT16
|
||||
.gprel32 $load_s16 # FFI_TYPE_SINT16
|
||||
.gprel32 $load_32 # FFI_TYPE_UINT32
|
||||
.gprel32 $load_32 # FFI_TYPE_SINT32
|
||||
.gprel32 $load_64 # FFI_TYPE_UINT64
|
||||
.gprel32 $load_64 # FFI_TYPE_SINT64
|
||||
.gprel32 $load_none # FFI_TYPE_STRUCT
|
||||
.gprel32 $load_64 # FFI_TYPE_POINTER
|
||||
epilogue
|
||||
|
||||
/* Assert that the table above is in sync with ffi.h. */
|
||||
E ALPHA_LD_FLOAT
|
||||
lds $f0, 16($sp)
|
||||
epilogue
|
||||
|
||||
#if FFI_TYPE_FLOAT != 2 \
|
||||
|| FFI_TYPE_DOUBLE != 3 \
|
||||
|| 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 \
|
||||
|| FFI_TYPE_SINT64 != 12 \
|
||||
|| FFI_TYPE_STRUCT != 13 \
|
||||
|| FFI_TYPE_POINTER != 14 \
|
||||
|| FFI_TYPE_LAST != 14
|
||||
#error "osf.S out of sync with ffi.h"
|
||||
#endif
|
||||
E ALPHA_LD_DOUBLE
|
||||
ldt $f0, 16($sp)
|
||||
epilogue
|
||||
|
||||
#ifdef __ELF__
|
||||
# define UA_SI .4byte
|
||||
# define FDE_ENCODING 0x1b /* pcrel sdata4 */
|
||||
# define FDE_ENCODE(X) .4byte X-.
|
||||
# define FDE_ARANGE(X) .4byte X
|
||||
#elif defined __osf__
|
||||
# define UA_SI .align 0; .long
|
||||
# define FDE_ENCODING 0x50 /* aligned absolute */
|
||||
# define FDE_ENCODE(X) .align 3; .quad X
|
||||
# define FDE_ARANGE(X) .align 0; .quad X
|
||||
#endif
|
||||
E ALPHA_LD_CPLXF
|
||||
lds $f0, 16($sp)
|
||||
lds $f1, 20($sp)
|
||||
epilogue
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
#elif defined __osf__
|
||||
.data
|
||||
.align 3
|
||||
.globl _GLOBAL__F_ffi_call_osf
|
||||
_GLOBAL__F_ffi_call_osf:
|
||||
#endif
|
||||
__FRAME_BEGIN__:
|
||||
UA_SI $LECIE1-$LSCIE1 # Length of Common Information Entry
|
||||
$LSCIE1:
|
||||
UA_SI 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 26 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte FDE_ENCODING # FDE Encoding
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 30 # uleb128 column 30
|
||||
.byte 0 # uleb128 offset 0
|
||||
.align 3
|
||||
$LECIE1:
|
||||
$LSFDE1:
|
||||
UA_SI $LEFDE1-$LASFDE1 # FDE Length
|
||||
$LASFDE1:
|
||||
UA_SI $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset
|
||||
FDE_ENCODE($LFB1) # FDE initial location
|
||||
FDE_ARANGE($LFE1-$LFB1) # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
E ALPHA_LD_CPLXD
|
||||
ldt $f0, 16($sp)
|
||||
ldt $f1, 24($sp)
|
||||
epilogue
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
UA_SI $LCFI1-$LFB1
|
||||
.byte 0x9a # DW_CFA_offset, column 26
|
||||
.byte 4 # uleb128 4*-8
|
||||
.byte 0x8f # DW_CFA_offset, column 15
|
||||
.byte 0x3 # uleb128 3*-8
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 15 # uleb128 column 15
|
||||
.byte 32 # uleb128 offset 32
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
UA_SI $LCFI2-$LCFI1
|
||||
.byte 0xda # DW_CFA_restore, column 26
|
||||
.align 3
|
||||
$LEFDE1:
|
||||
|
||||
$LSFDE3:
|
||||
UA_SI $LEFDE3-$LASFDE3 # FDE Length
|
||||
$LASFDE3:
|
||||
UA_SI $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset
|
||||
FDE_ENCODE($LFB2) # FDE initial location
|
||||
FDE_ARANGE($LFE2-$LFB2) # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
UA_SI $LCFI5-$LFB2
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x80,0x1 # uleb128 128
|
||||
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
UA_SI $LCFI6-$LCFI5
|
||||
.byte 0x9a # DW_CFA_offset, column 26
|
||||
.byte 16 # uleb128 offset 16*-8
|
||||
.align 3
|
||||
$LEFDE3:
|
||||
#if defined __osf__
|
||||
.align 0
|
||||
.long 0 # End of Table
|
||||
#endif
|
||||
cfi_endproc
|
||||
.end ffi_closure_osf
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
|
|
135
libffi/src/arc/arcompact.S
Normal file
135
libffi/src/arc/arcompact.S
Normal file
|
@ -0,0 +1,135 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
arcompact.S - Copyright (c) 2013 Synposys, Inc. (www.synopsys.com)
|
||||
|
||||
ARCompact 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 RENESAS TECHNOLOGY 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>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
#define CNAME(x) x
|
||||
#define ENTRY(x) .globl CNAME(x)` .type CNAME(x),%function` CNAME(x):
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
/* R0: ffi_prep_args */
|
||||
/* R1: &ecif */
|
||||
/* R2: cif->bytes */
|
||||
/* R3: fig->flags */
|
||||
/* R4: ecif.rvalue */
|
||||
/* R5: fn */
|
||||
ENTRY(ffi_call_ARCompact)
|
||||
/* Save registers. */
|
||||
st.a fp, [sp, -4] /* fp + 20, fp */
|
||||
push_s blink /* fp + 16, blink */
|
||||
st.a r4, [sp, -4] /* fp + 12, ecif.rvalue */
|
||||
push_s r3 /* fp + 8, fig->flags */
|
||||
st.a r5, [sp, -4] /* fp + 4, fn */
|
||||
push_s r2 /* fp + 0, cif->bytes */
|
||||
mov fp, sp
|
||||
|
||||
/* Make room for all of the new args. */
|
||||
sub sp, sp, r2
|
||||
|
||||
/* Place all of the ffi_prep_args in position. */
|
||||
/* ffi_prep_args(char *stack, extended_cif *ecif) */
|
||||
/* R1 already set. */
|
||||
|
||||
/* And call. */
|
||||
jl_s.d [r0]
|
||||
mov_s r0, sp
|
||||
|
||||
ld.ab r12, [fp, 4] /* cif->bytes */
|
||||
ld.ab r11, [fp, 4] /* fn */
|
||||
|
||||
/* Move first 8 parameters in registers... */
|
||||
ld_s r0, [sp]
|
||||
ld_s r1, [sp, 4]
|
||||
ld_s r2, [sp, 8]
|
||||
ld_s r3, [sp, 12]
|
||||
ld r4, [sp, 16]
|
||||
ld r5, [sp, 20]
|
||||
ld r6, [sp, 24]
|
||||
ld r7, [sp, 28]
|
||||
|
||||
/* ...and adjust the stack. */
|
||||
min r12, r12, 32
|
||||
|
||||
/* Call the function. */
|
||||
jl.d [r11]
|
||||
add sp, sp, r12
|
||||
|
||||
mov sp, fp
|
||||
pop_s r3 /* fig->flags, return type */
|
||||
pop_s r2 /* ecif.rvalue, pointer for return value */
|
||||
|
||||
/* If the return value pointer is NULL, assume no return value. */
|
||||
breq.d r2, 0, epilogue
|
||||
pop_s blink
|
||||
|
||||
/* Return INT. */
|
||||
brne r3, FFI_TYPE_INT, return_double
|
||||
b.d epilogue
|
||||
st_s r0, [r2]
|
||||
|
||||
return_double:
|
||||
brne r3, FFI_TYPE_DOUBLE, epilogue
|
||||
st_s r0, [r2]
|
||||
st_s r1, [r2,4]
|
||||
|
||||
epilogue:
|
||||
j_s.d [blink]
|
||||
ld.ab fp, [sp, 4]
|
||||
|
||||
ENTRY(ffi_closure_ARCompact)
|
||||
st.a r0, [sp, -32]
|
||||
st_s r1, [sp, 4]
|
||||
st_s r2, [sp, 8]
|
||||
st_s r3, [sp, 12]
|
||||
st r4, [sp, 16]
|
||||
st r5, [sp, 20]
|
||||
st r6, [sp, 24]
|
||||
st r7, [sp, 28]
|
||||
|
||||
/* pointer to arguments */
|
||||
mov_s r2, sp
|
||||
|
||||
/* return value goes here */
|
||||
sub sp, sp, 8
|
||||
mov_s r1, sp
|
||||
|
||||
push_s blink
|
||||
|
||||
bl.d ffi_closure_inner_ARCompact
|
||||
mov_s r0, r8 /* codeloc, set by trampoline */
|
||||
|
||||
pop_s blink
|
||||
|
||||
/* set return value to r1:r0 */
|
||||
pop_s r0
|
||||
pop_s r1
|
||||
j_s.d [blink]
|
||||
add_s sp, sp, 32
|
268
libffi/src/arc/ffi.c
Normal file
268
libffi/src/arc/ffi.c
Normal file
|
@ -0,0 +1,268 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com)
|
||||
|
||||
ARC 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 RENESAS TECHNOLOGY 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 <sys/cachectl.h>
|
||||
|
||||
/* for little endian ARC, the code is in fact stored as mixed endian for
|
||||
performance reasons */
|
||||
#if __BIG_ENDIAN__
|
||||
#define CODE_ENDIAN(x) (x)
|
||||
#else
|
||||
#define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16))
|
||||
#endif
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack
|
||||
space has been allocated for the function's arguments. */
|
||||
|
||||
void
|
||||
ffi_prep_args (char *stack, extended_cif * ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
int tmp;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
tmp = 0;
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
int alignment;
|
||||
|
||||
/* align alignment to 4 */
|
||||
alignment = (((*p_arg)->alignment - 1) | 3) + 1;
|
||||
|
||||
/* Align if necessary. */
|
||||
if ((alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, alignment);
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
z = sizeof (int);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof (int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Double or long long 64bit. */
|
||||
memcpy (argp, *p_argv, z);
|
||||
}
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif * cif)
|
||||
{
|
||||
/* Set the return type flag. */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = FFI_TYPE_DOUBLE;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_ARCompact (void (*)(char *, extended_cif *),
|
||||
extended_cif *, unsigned, unsigned,
|
||||
unsigned *, void (*fn) (void));
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have
|
||||
a return value address then we need to make one. */
|
||||
if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_ARCOMPACT:
|
||||
ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue,
|
||||
ffi_arg * args)
|
||||
{
|
||||
void **arg_area, **p_argv;
|
||||
ffi_cif *cif = closure->cif;
|
||||
char *argp = (char *) args;
|
||||
ffi_type **p_argt;
|
||||
int i;
|
||||
|
||||
arg_area = (void **) alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
/* handle hidden argument */
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = *(void **) argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = arg_area;
|
||||
|
||||
for (i = 0, p_argt = cif->arg_types; i < cif->nargs;
|
||||
i++, p_argt++, p_argv++)
|
||||
{
|
||||
size_t z;
|
||||
int alignment;
|
||||
|
||||
/* align alignment to 4 */
|
||||
alignment = (((*p_argt)->alignment - 1) | 3) + 1;
|
||||
|
||||
/* Align if necessary. */
|
||||
if ((alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, alignment);
|
||||
|
||||
z = (*p_argt)->size;
|
||||
*p_argv = (void *) argp;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
(closure->fun) (cif, rvalue, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
extern void ffi_closure_ARCompact (void);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data, void *codeloc)
|
||||
{
|
||||
uint32_t *tramp = (uint32_t *) & (closure->tramp[0]);
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_ARCOMPACT:
|
||||
FFI_ASSERT (tramp == codeloc);
|
||||
tramp[0] = CODE_ENDIAN (0x200a1fc0); /* mov r8, pcl */
|
||||
tramp[1] = CODE_ENDIAN (0x20200f80); /* j [long imm] */
|
||||
tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
53
libffi/src/arc/ffitarget.h
Normal file
53
libffi/src/arc/ffitarget.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffitarget.h - Copyright (c) 2012 Anthony Green
|
||||
Copyright (c) 2013 Synopsys, Inc. (www.synopsys.com)
|
||||
Target configuration macros for ARC.
|
||||
|
||||
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 RENESAS TECHNOLOGY 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
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi
|
||||
{
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_ARCOMPACT,
|
||||
FFI_LAST_ABI,
|
||||
FFI_DEFAULT_ABI = FFI_ARCOMPACT
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 12
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
1211
libffi/src/arm/ffi.c
1211
libffi/src/arm/ffi.c
File diff suppressed because it is too large
Load diff
|
@ -53,19 +53,17 @@ typedef enum ffi_abi {
|
|||
|
||||
#define FFI_EXTRA_CIF_FIELDS \
|
||||
int vfp_used; \
|
||||
short vfp_reg_free, vfp_nargs; \
|
||||
unsigned short vfp_reg_free, vfp_nargs; \
|
||||
signed char vfp_args[16] \
|
||||
|
||||
/* Internally used. */
|
||||
#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1)
|
||||
#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_VARIADIC
|
||||
#define FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#define FFI_GO_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 12
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc.
|
||||
#
|
||||
# ARM Trampoline Page Generator
|
||||
#
|
||||
# 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.
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
PROGNAME=$0
|
||||
|
||||
# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change,
|
||||
# the entire arm trampoline implementation must be updated to match, too.
|
||||
|
||||
# Size of an individual trampoline, in bytes
|
||||
TRAMPOLINE_SIZE=12
|
||||
|
||||
# Page size, in bytes
|
||||
PAGE_SIZE=4096
|
||||
|
||||
# Compute the size of the reachable config page; The first 16 bytes of the config page
|
||||
# are unreachable due to our maximum pc-relative ldr offset.
|
||||
PAGE_AVAIL=`expr $PAGE_SIZE - 16`
|
||||
|
||||
# Compute the number of of available trampolines.
|
||||
TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE`
|
||||
|
||||
header () {
|
||||
echo "# GENERATED CODE - DO NOT EDIT"
|
||||
echo "# This file was generated by $PROGNAME"
|
||||
echo ""
|
||||
|
||||
# Write out the license header
|
||||
cat << EOF
|
||||
# Copyright (c) 2010, Plausible Labs Cooperative, Inc.
|
||||
#
|
||||
# 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.
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
EOF
|
||||
|
||||
# Write out the trampoline table, aligned to the page boundary
|
||||
echo ".text"
|
||||
echo ".align 12"
|
||||
echo ".globl _ffi_closure_trampoline_table_page"
|
||||
echo "_ffi_closure_trampoline_table_page:"
|
||||
}
|
||||
|
||||
|
||||
# WARNING - Don't modify the trampoline code size without also updating the relevent libffi code
|
||||
trampoline () {
|
||||
cat << END
|
||||
|
||||
// trampoline
|
||||
// Save to stack
|
||||
stmfd sp!, {r0-r3}
|
||||
|
||||
// Load the context argument from the config page.
|
||||
// This places the first usable config value at _ffi_closure_trampoline_table-4080
|
||||
// This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
|
||||
ldr r0, [pc, #-4092]
|
||||
|
||||
// Load the jump address from the config page.
|
||||
ldr pc, [pc, #-4092]
|
||||
|
||||
END
|
||||
}
|
||||
|
||||
main () {
|
||||
# Write out the header
|
||||
header
|
||||
|
||||
# Write out the trampolines
|
||||
local i=0
|
||||
while [ $i -lt ${TRAMPOLINE_COUNT} ]; do
|
||||
trampoline
|
||||
local i=`expr $i + 1`
|
||||
done
|
||||
}
|
||||
|
||||
main
|
7
libffi/src/arm/internal.h
Normal file
7
libffi/src/arm/internal.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#define ARM_TYPE_VFP_S 0
|
||||
#define ARM_TYPE_VFP_D 1
|
||||
#define ARM_TYPE_VFP_N 2
|
||||
#define ARM_TYPE_INT64 3
|
||||
#define ARM_TYPE_INT 4
|
||||
#define ARM_TYPE_VOID 5
|
||||
#define ARM_TYPE_STRUCT 6
|
|
@ -1,8 +1,8 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
|
||||
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
|
||||
|
||||
ARM Foreign Function Interface
|
||||
|
||||
ARM Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -28,477 +28,307 @@
|
|||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a ## b
|
||||
#include <ffi_cfi.h>
|
||||
#include "internal.h"
|
||||
|
||||
/* Use the right prefix for global labels. */
|
||||
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
||||
#else
|
||||
#define CNAME(x) x
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#define ENTRY(x) .globl _##x; _##x:
|
||||
#else
|
||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
||||
#endif /* __APPLE__ */
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
#define LSYM(x) .x
|
||||
#else
|
||||
#define LSYM(x) x
|
||||
#endif
|
||||
|
||||
/* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
|
||||
Function Call Guide */
|
||||
#ifdef __APPLE__
|
||||
#define __SOFTFP__
|
||||
#endif
|
||||
|
||||
/* We need a better way of testing for this, but for now, this is all
|
||||
we can do. */
|
||||
@ This selects the minimum architecture level required.
|
||||
#define __ARM_ARCH__ 3
|
||||
|
||||
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 4
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 5
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
||||
/* GCC 4.8 provides __ARM_ARCH; construct it otherwise. */
|
||||
#ifndef __ARM_ARCH
|
||||
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|
||||
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|
||||
|| defined(__ARM_ARCH_7EM__)
|
||||
# define __ARM_ARCH 7
|
||||
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|
||||
|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
|
||||
|| defined(__ARM_ARCH_6M__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 6
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|
||||
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|
||||
|| defined(__ARM_ARCH_7EM__)
|
||||
# undef __ARM_ARCH__
|
||||
# define __ARM_ARCH__ 7
|
||||
#endif
|
||||
|
||||
#if __ARM_ARCH__ >= 5
|
||||
# define call_reg(x) blx x
|
||||
#elif defined (__ARM_ARCH_4T__)
|
||||
# define call_reg(x) mov lr, pc ; bx x
|
||||
# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
|
||||
# define __INTERWORKING__
|
||||
# define __ARM_ARCH 6
|
||||
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__)
|
||||
# define __ARM_ARCH 5
|
||||
# else
|
||||
# define __ARM_ARCH 4
|
||||
# endif
|
||||
#else
|
||||
# define call_reg(x) mov lr, pc ; mov pc, x
|
||||
#endif
|
||||
|
||||
/* Conditionally compile unwinder directives. */
|
||||
.macro UNWIND text:vararg
|
||||
#ifdef __ARM_EABI__
|
||||
#define UNWIND
|
||||
#else
|
||||
#define UNWIND @
|
||||
\text
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
.align 0
|
||||
.thumb
|
||||
.thumb_func
|
||||
#ifdef __APPLE__
|
||||
ENTRY($0)
|
||||
#else
|
||||
ENTRY(\name)
|
||||
#endif
|
||||
bx pc
|
||||
nop
|
||||
.arm
|
||||
UNWIND .fnstart
|
||||
/* A hook to tell gdb that we've switched to ARM mode. Also used to call
|
||||
directly from other local arm routines. */
|
||||
#ifdef __APPLE__
|
||||
_L__$0:
|
||||
#else
|
||||
_L__\name:
|
||||
#endif
|
||||
.endm
|
||||
#else
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
.align 0
|
||||
.arm
|
||||
#ifdef __APPLE__
|
||||
ENTRY($0)
|
||||
#else
|
||||
ENTRY(\name)
|
||||
#endif
|
||||
UNWIND .fnstart
|
||||
.endm
|
||||
#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
|
||||
.cfi_sections .debug_frame
|
||||
#endif
|
||||
|
||||
.macro RETLDM regs=, cond=, dirn=ia
|
||||
#if defined (__INTERWORKING__)
|
||||
.ifc "\regs",""
|
||||
ldr\cond lr, [sp], #4
|
||||
.else
|
||||
ldm\cond\dirn sp!, {\regs, lr}
|
||||
#define CONCAT(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a ## b
|
||||
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
# define CNAME(X) CONCAT (__USER_LABEL_PREFIX__, X)
|
||||
#else
|
||||
# define CNAME(X) X
|
||||
#endif
|
||||
#ifdef __ELF__
|
||||
# define SIZE(X) .size CNAME(X), . - CNAME(X)
|
||||
# define TYPE(X, Y) .type CNAME(X), Y
|
||||
#else
|
||||
# define SIZE(X)
|
||||
# define TYPE(X, Y)
|
||||
#endif
|
||||
|
||||
#define ARM_FUNC_START(name, gl) \
|
||||
.align 3; \
|
||||
.ifne gl; .globl CNAME(name); FFI_HIDDEN(CNAME(name)); .endif; \
|
||||
TYPE(name, %function); \
|
||||
CNAME(name):
|
||||
|
||||
#define ARM_FUNC_END(name) \
|
||||
SIZE(name)
|
||||
|
||||
/* Aid in defining a jump table with 8 bytes between entries. */
|
||||
.macro E index
|
||||
.if . - 0b - 8*\index
|
||||
.error "type table out of sync"
|
||||
.endif
|
||||
bx\cond lr
|
||||
#else
|
||||
.ifc "\regs",""
|
||||
ldr\cond pc, [sp], #4
|
||||
.else
|
||||
ldm\cond\dirn sp!, {\regs, pc}
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
@ r0: ffi_prep_args
|
||||
@ r1: &ecif
|
||||
@ r2: cif->bytes
|
||||
@ r3: fig->flags
|
||||
@ sp+0: ecif.rvalue
|
||||
.text
|
||||
.syntax unified
|
||||
.arm
|
||||
|
||||
@ This assumes we are using gas.
|
||||
ARM_FUNC_START ffi_call_SYSV
|
||||
@ Save registers
|
||||
stmfd sp!, {r0-r3, fp, lr}
|
||||
UNWIND .save {r0-r3, fp, lr}
|
||||
mov fp, sp
|
||||
/* We require interworking on LDM, which implies ARMv5T,
|
||||
which implies the existance of BLX. */
|
||||
.arch armv5t
|
||||
|
||||
UNWIND .setfp fp, sp
|
||||
/* Note that we use STC and LDC to encode VFP instructions,
|
||||
so that we do not need ".fpu vfp", nor get that added to
|
||||
the object file attributes. These will not be executed
|
||||
unless the FFI_VFP abi is used. */
|
||||
|
||||
@ Make room for all of the new args.
|
||||
sub sp, fp, r2
|
||||
@ r0: stack
|
||||
@ r1: frame
|
||||
@ r2: fn
|
||||
@ r3: vfp_used
|
||||
|
||||
@ Place all of the ffi_prep_args in position
|
||||
mov r0, sp
|
||||
@ r1 already set
|
||||
ARM_FUNC_START(ffi_call_VFP, 1)
|
||||
UNWIND .fnstart
|
||||
cfi_startproc
|
||||
|
||||
@ Call ffi_prep_args(stack, &ecif)
|
||||
bl CNAME(ffi_prep_args)
|
||||
cmp r3, #3 @ load only d0 if possible
|
||||
ldcle p11, cr0, [r0] @ vldrle d0, [sp]
|
||||
ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7}
|
||||
add r0, r0, #64 @ discard the vfp register args
|
||||
/* FALLTHRU */
|
||||
ARM_FUNC_END(ffi_call_VFP)
|
||||
|
||||
@ move first 4 parameters in registers
|
||||
ldmia sp, {r0-r3}
|
||||
ARM_FUNC_START(ffi_call_SYSV, 1)
|
||||
stm r1, {fp, lr}
|
||||
mov fp, r1
|
||||
|
||||
@ and adjust stack
|
||||
sub lr, fp, sp @ cif->bytes == fp - sp
|
||||
ldr ip, [fp] @ load fn() in advance
|
||||
cmp lr, #16
|
||||
movhs lr, #16
|
||||
add sp, sp, lr
|
||||
@ This is a bit of a lie wrt the origin of the unwind info, but
|
||||
@ now we've got the usual frame pointer and two saved registers.
|
||||
UNWIND .save {fp,lr}
|
||||
UNWIND .setfp fp, sp
|
||||
cfi_def_cfa(fp, 8)
|
||||
cfi_rel_offset(fp, 0)
|
||||
cfi_rel_offset(lr, 4)
|
||||
|
||||
@ call (fn) (...)
|
||||
call_reg(ip)
|
||||
|
||||
@ Remove the space we pushed for the args
|
||||
mov sp, fp
|
||||
mov sp, r0 @ install the stack pointer
|
||||
mov lr, r2 @ move the fn pointer out of the way
|
||||
ldr ip, [fp, #16] @ install the static chain
|
||||
ldmia sp!, {r0-r3} @ move first 4 parameters in registers.
|
||||
blx lr @ call fn
|
||||
|
||||
@ Load r2 with the pointer to storage for the return value
|
||||
ldr r2, [sp, #24]
|
||||
@ Load r3 with the return type code
|
||||
ldr r2, [fp, #8]
|
||||
ldr r3, [fp, #12]
|
||||
|
||||
@ Load r3 with the return type code
|
||||
ldr r3, [sp, #12]
|
||||
@ Deallocate the stack with the arguments.
|
||||
mov sp, fp
|
||||
cfi_def_cfa_register(sp)
|
||||
|
||||
@ If the return value pointer is NULL, assume no return value.
|
||||
cmp r2, #0
|
||||
beq LSYM(Lepilogue)
|
||||
@ Store values stored in registers.
|
||||
.align 3
|
||||
add pc, pc, r3, lsl #3
|
||||
nop
|
||||
0:
|
||||
E ARM_TYPE_VFP_S
|
||||
stc p10, cr0, [r2] @ vstr s0, [r2]
|
||||
pop {fp,pc}
|
||||
E ARM_TYPE_VFP_D
|
||||
stc p11, cr0, [r2] @ vstr d0, [r2]
|
||||
pop {fp,pc}
|
||||
E ARM_TYPE_VFP_N
|
||||
stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3}
|
||||
pop {fp,pc}
|
||||
E ARM_TYPE_INT64
|
||||
str r1, [r2, #4]
|
||||
nop
|
||||
E ARM_TYPE_INT
|
||||
str r0, [r2]
|
||||
pop {fp,pc}
|
||||
E ARM_TYPE_VOID
|
||||
pop {fp,pc}
|
||||
nop
|
||||
E ARM_TYPE_STRUCT
|
||||
pop {fp,pc}
|
||||
|
||||
@ return INT
|
||||
cmp r3, #FFI_TYPE_INT
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
cmpne r3, #FFI_TYPE_FLOAT
|
||||
#endif
|
||||
streq r0, [r2]
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return INT64
|
||||
cmp r3, #FFI_TYPE_SINT64
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
cmpne r3, #FFI_TYPE_DOUBLE
|
||||
#endif
|
||||
stmeqia r2, {r0, r1}
|
||||
|
||||
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return FLOAT
|
||||
cmp r3, #FFI_TYPE_FLOAT
|
||||
stfeqs f0, [r2]
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
@ return DOUBLE or LONGDOUBLE
|
||||
cmp r3, #FFI_TYPE_DOUBLE
|
||||
stfeqd f0, [r2]
|
||||
#endif
|
||||
|
||||
LSYM(Lepilogue):
|
||||
#if defined (__INTERWORKING__)
|
||||
ldmia sp!, {r0-r3,fp, lr}
|
||||
bx lr
|
||||
#else
|
||||
ldmia sp!, {r0-r3,fp, pc}
|
||||
#endif
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
UNWIND .fnend
|
||||
#ifdef __ELF__
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
#endif
|
||||
cfi_endproc
|
||||
UNWIND .fnend
|
||||
ARM_FUNC_END(ffi_call_SYSV)
|
||||
|
||||
|
||||
/*
|
||||
unsigned int FFI_HIDDEN
|
||||
ffi_closure_SYSV_inner (closure, respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
int ffi_closure_inner_* (cif, fun, user_data, frame)
|
||||
*/
|
||||
|
||||
ARM_FUNC_START ffi_closure_SYSV
|
||||
UNWIND .pad #16
|
||||
ARM_FUNC_START(ffi_go_closure_SYSV, 1)
|
||||
cfi_startproc
|
||||
stmdb sp!, {r0-r3} @ save argument regs
|
||||
cfi_adjust_cfa_offset(16)
|
||||
ldr r0, [ip, #4] @ load cif
|
||||
ldr r1, [ip, #8] @ load fun
|
||||
mov r2, ip @ load user_data
|
||||
b 0f
|
||||
cfi_endproc
|
||||
ARM_FUNC_END(ffi_go_closure_SYSV)
|
||||
|
||||
ARM_FUNC_START(ffi_closure_SYSV, 1)
|
||||
UNWIND .fnstart
|
||||
cfi_startproc
|
||||
stmdb sp!, {r0-r3} @ save argument regs
|
||||
cfi_adjust_cfa_offset(16)
|
||||
ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif
|
||||
ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun
|
||||
ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data
|
||||
0:
|
||||
add ip, sp, #16 @ compute entry sp
|
||||
sub sp, sp, #64+32 @ allocate frame
|
||||
cfi_adjust_cfa_offset(64+32)
|
||||
stmdb sp!, {ip,lr}
|
||||
|
||||
/* Remember that EABI unwind info only applies at call sites.
|
||||
We need do nothing except note the save of the stack pointer
|
||||
and the link registers. */
|
||||
UNWIND .save {sp,lr}
|
||||
cfi_adjust_cfa_offset(8)
|
||||
cfi_rel_offset(lr, 4)
|
||||
|
||||
add r3, sp, #8 @ load frame
|
||||
bl CNAME(ffi_closure_inner_SYSV)
|
||||
|
||||
@ Load values returned in registers.
|
||||
add r2, sp, #8+64 @ load result
|
||||
adr r3, CNAME(ffi_closure_ret)
|
||||
add pc, r3, r0, lsl #3
|
||||
cfi_endproc
|
||||
UNWIND .fnend
|
||||
ARM_FUNC_END(ffi_closure_SYSV)
|
||||
|
||||
ARM_FUNC_START(ffi_go_closure_VFP, 1)
|
||||
cfi_startproc
|
||||
stmdb sp!, {r0-r3} @ save argument regs
|
||||
cfi_adjust_cfa_offset(16)
|
||||
ldr r0, [ip, #4] @ load cif
|
||||
ldr r1, [ip, #8] @ load fun
|
||||
mov r2, ip @ load user_data
|
||||
b 0f
|
||||
cfi_endproc
|
||||
ARM_FUNC_END(ffi_go_closure_VFP)
|
||||
|
||||
ARM_FUNC_START(ffi_closure_VFP, 1)
|
||||
UNWIND .fnstart
|
||||
cfi_startproc
|
||||
stmdb sp!, {r0-r3} @ save argument regs
|
||||
cfi_adjust_cfa_offset(16)
|
||||
ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif
|
||||
ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun
|
||||
ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data
|
||||
0:
|
||||
add ip, sp, #16
|
||||
stmfd sp!, {ip, lr}
|
||||
UNWIND .save {r0, lr}
|
||||
add r2, sp, #8
|
||||
UNWIND .pad #16
|
||||
sub sp, sp, #16
|
||||
str sp, [sp, #8]
|
||||
add r1, sp, #8
|
||||
bl CNAME(ffi_closure_SYSV_inner)
|
||||
cmp r0, #FFI_TYPE_INT
|
||||
beq .Lretint
|
||||
sub sp, sp, #64+32 @ allocate frame
|
||||
cfi_adjust_cfa_offset(64+32)
|
||||
stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7}
|
||||
stmdb sp!, {ip,lr}
|
||||
|
||||
/* See above. */
|
||||
UNWIND .save {sp,lr}
|
||||
cfi_adjust_cfa_offset(8)
|
||||
cfi_rel_offset(lr, 4)
|
||||
|
||||
add r3, sp, #8 @ load frame
|
||||
bl CNAME(ffi_closure_inner_VFP)
|
||||
|
||||
@ Load values returned in registers.
|
||||
add r2, sp, #8+64 @ load result
|
||||
adr r3, CNAME(ffi_closure_ret)
|
||||
add pc, r3, r0, lsl #3
|
||||
cfi_endproc
|
||||
UNWIND .fnend
|
||||
ARM_FUNC_END(ffi_closure_VFP)
|
||||
|
||||
/* Load values returned in registers for both closure entry points.
|
||||
Note that we use LDM with SP in the register set. This is deprecated
|
||||
by ARM, but not yet unpredictable. */
|
||||
|
||||
ARM_FUNC_START(ffi_closure_ret, 0)
|
||||
cfi_startproc
|
||||
cfi_rel_offset(sp, 0)
|
||||
cfi_rel_offset(lr, 4)
|
||||
0:
|
||||
E ARM_TYPE_VFP_S
|
||||
ldc p10, cr0, [r2] @ vldr s0, [r2]
|
||||
ldm sp, {sp,pc}
|
||||
E ARM_TYPE_VFP_D
|
||||
ldc p11, cr0, [r2] @ vldr d0, [r2]
|
||||
ldm sp, {sp,pc}
|
||||
E ARM_TYPE_VFP_N
|
||||
ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3}
|
||||
ldm sp, {sp,pc}
|
||||
E ARM_TYPE_INT64
|
||||
ldr r1, [r2, #4]
|
||||
nop
|
||||
E ARM_TYPE_INT
|
||||
ldr r0, [r2]
|
||||
ldm sp, {sp,pc}
|
||||
E ARM_TYPE_VOID
|
||||
ldm sp, {sp,pc}
|
||||
nop
|
||||
E ARM_TYPE_STRUCT
|
||||
ldm sp, {sp,pc}
|
||||
cfi_endproc
|
||||
ARM_FUNC_END(ffi_closure_ret)
|
||||
|
||||
#if FFI_EXEC_TRAMPOLINE_TABLE
|
||||
|
||||
/* ??? The iOS support should be updated. The first insn used to
|
||||
be STMFD, but that's been moved into ffi_closure_SYSV. If the
|
||||
writable page is put after this one we can make use of the
|
||||
pc+8 feature of the architecture. We can also reduce the size
|
||||
of the thunk to 8 and pack more of these into the page.
|
||||
|
||||
In the meantime, simply replace the STMFD with a NOP so as to
|
||||
keep all the magic numbers the same within ffi.c. */
|
||||
|
||||
.align 12
|
||||
ARM_FUNC_START(ffi_closure_trampoline_table_page)
|
||||
.rept 4096 / 12
|
||||
nop
|
||||
ldr ip, [pc, #-4092]
|
||||
ldr pc, [pc, #-4092]
|
||||
.endr
|
||||
|
||||
cmp r0, #FFI_TYPE_FLOAT
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretint
|
||||
#else
|
||||
beq .Lretfloat
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_DOUBLE
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretlonglong
|
||||
#else
|
||||
beq .Lretdouble
|
||||
#endif
|
||||
ARM_FUNC_START(ffi_arm_trampoline, 1)
|
||||
0: adr ip, 0b
|
||||
ldr pc, 1f
|
||||
1: .long 0
|
||||
ARM_FUNC_END(ffi_arm_trampoline)
|
||||
|
||||
cmp r0, #FFI_TYPE_LONGDOUBLE
|
||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
||||
beq .Lretlonglong
|
||||
#else
|
||||
beq .Lretlongdouble
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_SINT64
|
||||
beq .Lretlonglong
|
||||
.Lclosure_epilogue:
|
||||
add sp, sp, #16
|
||||
ldmfd sp, {sp, pc}
|
||||
.Lretint:
|
||||
ldr r0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretlonglong:
|
||||
ldr r0, [sp]
|
||||
ldr r1, [sp, #4]
|
||||
b .Lclosure_epilogue
|
||||
|
||||
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
|
||||
.Lretfloat:
|
||||
ldfs f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretdouble:
|
||||
ldfd f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretlongdouble:
|
||||
ldfd f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
#endif
|
||||
|
||||
.ffi_closure_SYSV_end:
|
||||
UNWIND .fnend
|
||||
#ifdef __ELF__
|
||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
||||
#endif
|
||||
|
||||
|
||||
/* Below are VFP hard-float ABI call and closure implementations.
|
||||
Add VFP FPU directive here. This is only compiled into the library
|
||||
under EABI. */
|
||||
#ifdef __ARM_EABI__
|
||||
.fpu vfp
|
||||
|
||||
@ r0: fn
|
||||
@ r1: &ecif
|
||||
@ r2: cif->bytes
|
||||
@ r3: fig->flags
|
||||
@ sp+0: ecif.rvalue
|
||||
|
||||
ARM_FUNC_START ffi_call_VFP
|
||||
@ Save registers
|
||||
stmfd sp!, {r0-r3, fp, lr}
|
||||
UNWIND .save {r0-r3, fp, lr}
|
||||
mov fp, sp
|
||||
UNWIND .setfp fp, sp
|
||||
|
||||
@ Make room for all of the new args.
|
||||
sub sp, sp, r2
|
||||
|
||||
@ Make room for loading VFP args
|
||||
sub sp, sp, #64
|
||||
|
||||
@ Place all of the ffi_prep_args in position
|
||||
mov r0, sp
|
||||
@ r1 already set
|
||||
sub r2, fp, #64 @ VFP scratch space
|
||||
|
||||
@ Call ffi_prep_args(stack, &ecif, vfp_space)
|
||||
bl CNAME(ffi_prep_args)
|
||||
|
||||
@ Load VFP register args if needed
|
||||
cmp r0, #0
|
||||
beq LSYM(Lbase_args)
|
||||
|
||||
@ Load only d0 if possible
|
||||
cmp r0, #3
|
||||
sub ip, fp, #64
|
||||
flddle d0, [ip]
|
||||
fldmiadgt ip, {d0-d7}
|
||||
|
||||
LSYM(Lbase_args):
|
||||
@ move first 4 parameters in registers
|
||||
ldmia sp, {r0-r3}
|
||||
|
||||
@ and adjust stack
|
||||
sub lr, ip, sp @ cif->bytes == (fp - 64) - sp
|
||||
ldr ip, [fp] @ load fn() in advance
|
||||
cmp lr, #16
|
||||
movhs lr, #16
|
||||
add sp, sp, lr
|
||||
|
||||
@ call (fn) (...)
|
||||
call_reg(ip)
|
||||
|
||||
@ Remove the space we pushed for the args
|
||||
mov sp, fp
|
||||
|
||||
@ Load r2 with the pointer to storage for
|
||||
@ the return value
|
||||
ldr r2, [sp, #24]
|
||||
|
||||
@ Load r3 with the return type code
|
||||
ldr r3, [sp, #12]
|
||||
|
||||
@ If the return value pointer is NULL,
|
||||
@ assume no return value.
|
||||
cmp r2, #0
|
||||
beq LSYM(Lepilogue_vfp)
|
||||
|
||||
cmp r3, #FFI_TYPE_INT
|
||||
streq r0, [r2]
|
||||
beq LSYM(Lepilogue_vfp)
|
||||
|
||||
cmp r3, #FFI_TYPE_SINT64
|
||||
stmeqia r2, {r0, r1}
|
||||
beq LSYM(Lepilogue_vfp)
|
||||
|
||||
cmp r3, #FFI_TYPE_FLOAT
|
||||
fstseq s0, [r2]
|
||||
beq LSYM(Lepilogue_vfp)
|
||||
|
||||
cmp r3, #FFI_TYPE_DOUBLE
|
||||
fstdeq d0, [r2]
|
||||
beq LSYM(Lepilogue_vfp)
|
||||
|
||||
cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT
|
||||
cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
|
||||
fstmiadeq r2, {d0-d3}
|
||||
|
||||
LSYM(Lepilogue_vfp):
|
||||
RETLDM "r0-r3,fp"
|
||||
|
||||
.ffi_call_VFP_end:
|
||||
UNWIND .fnend
|
||||
.size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
|
||||
|
||||
|
||||
ARM_FUNC_START ffi_closure_VFP
|
||||
fstmfdd sp!, {d0-d7}
|
||||
@ r0-r3, then d0-d7
|
||||
UNWIND .pad #80
|
||||
add ip, sp, #80
|
||||
stmfd sp!, {ip, lr}
|
||||
UNWIND .save {r0, lr}
|
||||
add r2, sp, #72
|
||||
add r3, sp, #8
|
||||
UNWIND .pad #72
|
||||
sub sp, sp, #72
|
||||
str sp, [sp, #64]
|
||||
add r1, sp, #64
|
||||
bl CNAME(ffi_closure_SYSV_inner)
|
||||
|
||||
cmp r0, #FFI_TYPE_INT
|
||||
beq .Lretint_vfp
|
||||
|
||||
cmp r0, #FFI_TYPE_FLOAT
|
||||
beq .Lretfloat_vfp
|
||||
|
||||
cmp r0, #FFI_TYPE_DOUBLE
|
||||
cmpne r0, #FFI_TYPE_LONGDOUBLE
|
||||
beq .Lretdouble_vfp
|
||||
|
||||
cmp r0, #FFI_TYPE_SINT64
|
||||
beq .Lretlonglong_vfp
|
||||
|
||||
cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT
|
||||
beq .Lretfloat_struct_vfp
|
||||
|
||||
cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
|
||||
beq .Lretdouble_struct_vfp
|
||||
|
||||
.Lclosure_epilogue_vfp:
|
||||
add sp, sp, #72
|
||||
ldmfd sp, {sp, pc}
|
||||
|
||||
.Lretfloat_vfp:
|
||||
flds s0, [sp]
|
||||
b .Lclosure_epilogue_vfp
|
||||
.Lretdouble_vfp:
|
||||
fldd d0, [sp]
|
||||
b .Lclosure_epilogue_vfp
|
||||
.Lretint_vfp:
|
||||
ldr r0, [sp]
|
||||
b .Lclosure_epilogue_vfp
|
||||
.Lretlonglong_vfp:
|
||||
ldmia sp, {r0, r1}
|
||||
b .Lclosure_epilogue_vfp
|
||||
.Lretfloat_struct_vfp:
|
||||
fldmiad sp, {d0-d1}
|
||||
b .Lclosure_epilogue_vfp
|
||||
.Lretdouble_struct_vfp:
|
||||
fldmiad sp, {d0-d3}
|
||||
b .Lclosure_epilogue_vfp
|
||||
|
||||
.ffi_closure_VFP_end:
|
||||
UNWIND .fnend
|
||||
.size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
|
||||
#endif
|
||||
|
||||
ENTRY(ffi_arm_trampoline)
|
||||
stmfd sp!, {r0-r3}
|
||||
ldr r0, [pc]
|
||||
ldr pc, [pc]
|
||||
#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
|
||||
ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>,
|
||||
Paulo Pizarro <paulo.pizarro@gmail.com>
|
||||
|
||||
Blackfin Foreign Function Interface
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
|
||||
sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>,
|
||||
Paulo Pizarro <paulo.pizarro@gmail.com>
|
||||
|
||||
Blackfin Foreign Function Interface
|
||||
|
||||
|
@ -32,7 +33,7 @@
|
|||
.align 4
|
||||
|
||||
/*
|
||||
There is a "feature" in the bfin toolchain that it puts a _ before funcion names
|
||||
There is a "feature" in the bfin toolchain that it puts a _ before function names
|
||||
that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV
|
||||
*/
|
||||
.global _ffi_call_SYSV;
|
||||
|
@ -40,25 +41,26 @@
|
|||
.func ffi_call_SYSV
|
||||
|
||||
/*
|
||||
cif->bytes = R0 (fp+8)
|
||||
&ecif = R1 (fp+12)
|
||||
ffi_prep_args = R2 (fp+16)
|
||||
ret_type = stack (fp+20)
|
||||
ecif.rvalue = stack (fp+24)
|
||||
fn = stack (fp+28)
|
||||
got (fp+32)
|
||||
There is room for improvement here (we can use temporary registers
|
||||
instead of saving the values in the memory)
|
||||
REGS:
|
||||
P5 => Stack pointer (function arguments)
|
||||
R5 => cif->bytes
|
||||
R4 => ret->type
|
||||
cif->bytes = R0 (fp+8)
|
||||
&ecif = R1 (fp+12)
|
||||
ffi_prep_args = R2 (fp+16)
|
||||
ret_type = stack (fp+20)
|
||||
ecif.rvalue = stack (fp+24)
|
||||
fn = stack (fp+28)
|
||||
got (fp+32)
|
||||
|
||||
FP-20 = P3
|
||||
FP-16 = SP (parameters area)
|
||||
FP-12 = SP (temp)
|
||||
FP-08 = function return part 1 [R0]
|
||||
FP-04 = function return part 2 [R1]
|
||||
There is room for improvement here (we can use temporary registers
|
||||
instead of saving the values in the memory)
|
||||
REGS:
|
||||
P5 => Stack pointer (function arguments)
|
||||
R5 => cif->bytes
|
||||
R4 => ret->type
|
||||
|
||||
FP-20 = P3
|
||||
FP-16 = SP (parameters area)
|
||||
FP-12 = SP (temp)
|
||||
FP-08 = function return part 1 [R0]
|
||||
FP-04 = function return part 2 [R1]
|
||||
*/
|
||||
|
||||
_ffi_call_SYSV:
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <ffi_common.h>
|
||||
|
||||
#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
|
||||
# if __gnu_linux__
|
||||
# if __gnu_linux__ && !defined(__ANDROID__)
|
||||
/* This macro indicates it may be forbidden to map anonymous memory
|
||||
with both write and execute permission. Code compiled when this
|
||||
option is defined will attempt to map such pages once, but if it
|
||||
|
@ -181,10 +181,26 @@ static int emutramp_enabled = -1;
|
|||
static int
|
||||
emutramp_enabled_check (void)
|
||||
{
|
||||
if (getenv ("FFI_DISABLE_EMUTRAMP") == NULL)
|
||||
return 1;
|
||||
else
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
FILE *f;
|
||||
int ret;
|
||||
f = fopen ("/proc/self/status", "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
ret = 0;
|
||||
|
||||
while (getline (&buf, &len, f) != -1)
|
||||
if (!strncmp (buf, "PaX:", 4))
|
||||
{
|
||||
char emutramp;
|
||||
if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
|
||||
ret = (emutramp == 'E');
|
||||
break;
|
||||
}
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
|
||||
|
@ -249,9 +265,15 @@ static size_t execsize = 0;
|
|||
|
||||
/* Open a temporary file name, and immediately unlink it. */
|
||||
static int
|
||||
open_temp_exec_file_name (char *name)
|
||||
open_temp_exec_file_name (char *name, int flags)
|
||||
{
|
||||
int fd = mkstemp (name);
|
||||
int fd;
|
||||
|
||||
#ifdef HAVE_MKOSTEMP
|
||||
fd = mkostemp (name, flags);
|
||||
#else
|
||||
fd = mkstemp (name);
|
||||
#endif
|
||||
|
||||
if (fd != -1)
|
||||
unlink (name);
|
||||
|
@ -264,8 +286,30 @@ static int
|
|||
open_temp_exec_file_dir (const char *dir)
|
||||
{
|
||||
static const char suffix[] = "/ffiXXXXXX";
|
||||
int lendir = strlen (dir);
|
||||
char *tempname = __builtin_alloca (lendir + sizeof (suffix));
|
||||
int lendir, flags;
|
||||
char *tempname;
|
||||
#ifdef O_TMPFILE
|
||||
int fd;
|
||||
#endif
|
||||
|
||||
#ifdef O_CLOEXEC
|
||||
flags = O_CLOEXEC;
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
#ifdef O_TMPFILE
|
||||
fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700);
|
||||
/* If the running system does not support the O_TMPFILE flag then retry without it. */
|
||||
if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) {
|
||||
return fd;
|
||||
} else {
|
||||
errno = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
lendir = strlen (dir);
|
||||
tempname = __builtin_alloca (lendir + sizeof (suffix));
|
||||
|
||||
if (!tempname)
|
||||
return -1;
|
||||
|
@ -273,7 +317,7 @@ open_temp_exec_file_dir (const char *dir)
|
|||
memcpy (tempname, dir, lendir);
|
||||
memcpy (tempname + lendir, suffix, sizeof (suffix));
|
||||
|
||||
return open_temp_exec_file_name (tempname);
|
||||
return open_temp_exec_file_name (tempname, flags);
|
||||
}
|
||||
|
||||
/* Open a temporary file in the directory in the named environment
|
||||
|
@ -382,7 +426,7 @@ open_temp_exec_file_opts_next (void)
|
|||
}
|
||||
|
||||
/* Return a file descriptor of a temporary zero-sized file in a
|
||||
writable and exexutable filesystem. */
|
||||
writable and executable filesystem. */
|
||||
static int
|
||||
open_temp_exec_file (void)
|
||||
{
|
||||
|
|
|
@ -54,6 +54,11 @@ void ffi_type_test(ffi_type *a, char *file, int line)
|
|||
FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
|
||||
FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
|
||||
FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX)
|
||||
|| a->elements != NULL, file, line);
|
||||
FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX
|
||||
|| (a->elements != NULL
|
||||
&& a->elements[0] != NULL && a->elements[1] == NULL),
|
||||
file, line);
|
||||
|
||||
}
|
||||
|
|
|
@ -1255,7 +1255,7 @@ extern void* sbrk(ptrdiff_t);
|
|||
#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
|
||||
|
||||
/* Some constants coerced to size_t */
|
||||
/* Annoying but necessary to avoid errors on some plaftorms */
|
||||
/* Annoying but necessary to avoid errors on some platforms */
|
||||
#define SIZE_T_ZERO ((size_t)0)
|
||||
#define SIZE_T_ONE ((size_t)1)
|
||||
#define SIZE_T_TWO ((size_t)2)
|
||||
|
@ -1409,7 +1409,7 @@ static int win32munmap(void* ptr, size_t size) {
|
|||
#define CALL_MORECORE(S) MFAIL
|
||||
#endif /* HAVE_MORECORE */
|
||||
|
||||
/* mstate bit set if continguous morecore disabled or failed */
|
||||
/* mstate bit set if contiguous morecore disabled or failed */
|
||||
#define USE_NONCONTIGUOUS_BIT (4U)
|
||||
|
||||
/* segment bit set in create_mspace_with_base */
|
||||
|
@ -1661,7 +1661,7 @@ struct malloc_chunk {
|
|||
typedef struct malloc_chunk mchunk;
|
||||
typedef struct malloc_chunk* mchunkptr;
|
||||
typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
|
||||
typedef unsigned int bindex_t; /* Described below */
|
||||
typedef size_t bindex_t; /* Described below */
|
||||
typedef unsigned int binmap_t; /* Described below */
|
||||
typedef unsigned int flag_t; /* The type of various bit flag sets */
|
||||
|
||||
|
@ -2291,7 +2291,7 @@ static size_t traverse_and_check(mstate m);
|
|||
#define treebin_at(M,i) (&((M)->treebins[i]))
|
||||
|
||||
/* assign tree index for size S to variable I */
|
||||
#if defined(__GNUC__) && defined(i386)
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
#define compute_tree_index(S, I)\
|
||||
{\
|
||||
size_t X = S >> TREEBIN_SHIFT;\
|
||||
|
@ -2356,7 +2356,7 @@ static size_t traverse_and_check(mstate m);
|
|||
|
||||
/* index corresponding to given bit */
|
||||
|
||||
#if defined(__GNUC__) && defined(i386)
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
#define compute_bit2idx(X, I)\
|
||||
{\
|
||||
unsigned int J;\
|
||||
|
@ -3090,8 +3090,8 @@ static void internal_malloc_stats(mstate m) {
|
|||
and choose its bk node as its replacement.
|
||||
2. If x was the last node of its size, but not a leaf node, it must
|
||||
be replaced with a leaf node (not merely one with an open left or
|
||||
right), to make sure that lefts and rights of descendents
|
||||
correspond properly to bit masks. We use the rightmost descendent
|
||||
right), to make sure that lefts and rights of descendants
|
||||
correspond properly to bit masks. We use the rightmost descendant
|
||||
of x. We could use any other leaf, but this is easy to locate and
|
||||
tends to counteract removal of leftmosts elsewhere, and so keeps
|
||||
paths shorter than minimally guaranteed. This doesn't loop much
|
||||
|
@ -3388,7 +3388,7 @@ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
|
|||
*ss = m->seg; /* Push current record */
|
||||
m->seg.base = tbase;
|
||||
m->seg.size = tsize;
|
||||
set_segment_flags(&m->seg, mmapped);
|
||||
(void)set_segment_flags(&m->seg, mmapped);
|
||||
m->seg.next = ss;
|
||||
|
||||
/* Insert trailing fenceposts */
|
||||
|
@ -3548,7 +3548,7 @@ static void* sys_alloc(mstate m, size_t nb) {
|
|||
if (!is_initialized(m)) { /* first-time initialization */
|
||||
m->seg.base = m->least_addr = tbase;
|
||||
m->seg.size = tsize;
|
||||
set_segment_flags(&m->seg, mmap_flag);
|
||||
(void)set_segment_flags(&m->seg, mmap_flag);
|
||||
m->magic = mparams.magic;
|
||||
init_bins(m);
|
||||
if (is_global(m))
|
||||
|
@ -5091,10 +5091,10 @@ History:
|
|||
Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
|
||||
* Use last_remainder in more cases.
|
||||
* Pack bins using idea from colin@nyx10.cs.du.edu
|
||||
* Use ordered bins instead of best-fit threshhold
|
||||
* Use ordered bins instead of best-fit threshold
|
||||
* Eliminate block-local decls to simplify tracing and debugging.
|
||||
* Support another case of realloc via move into top
|
||||
* Fix error occuring when initial sbrk_base not word-aligned.
|
||||
* Fix error occurring when initial sbrk_base not word-aligned.
|
||||
* Rely on page size for units instead of SBRK_UNIT to
|
||||
avoid surprises about sbrk alignment conventions.
|
||||
* Add mallinfo, mallopt. Thanks to Raymond Nijssen
|
||||
|
|
|
@ -401,7 +401,7 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
the closure (in the "trampoline" area), but we replace the gp
|
||||
pointer with a pointer to the closure itself. We also add the real
|
||||
gp pointer to the closure. This allows the function entry code to
|
||||
both retrieve the user data, and to restire the correct gp pointer. */
|
||||
both retrieve the user data, and to restore the correct gp pointer. */
|
||||
|
||||
extern void ffi_closure_unix ();
|
||||
|
||||
|
|
|
@ -60,6 +60,9 @@ ffi_java_raw_size (ffi_cif *cif)
|
|||
case FFI_TYPE_STRUCT:
|
||||
/* No structure parameters in Java. */
|
||||
abort();
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
default:
|
||||
result += FFI_SIZEOF_JAVA_RAW;
|
||||
}
|
||||
|
@ -104,6 +107,10 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
|
|||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw +=
|
||||
|
@ -126,6 +133,9 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
|
|||
*args = (void*) raw;
|
||||
raw += 2;
|
||||
break;
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
default:
|
||||
*args = (void*) raw++;
|
||||
}
|
||||
|
@ -254,6 +264,10 @@ ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
|
|||
*(SINT64 *)rvalue <<= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -279,6 +293,10 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
|
|||
*(SINT64 *)rvalue >>= 32;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Not supported yet. */
|
||||
abort();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -123,6 +123,8 @@ ffi_prep_args (void *stack, extended_cif *ecif)
|
|||
#define CIF_FLAGS_POINTER 32
|
||||
#define CIF_FLAGS_STRUCT1 64
|
||||
#define CIF_FLAGS_STRUCT2 128
|
||||
#define CIF_FLAGS_SINT8 256
|
||||
#define CIF_FLAGS_SINT16 512
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
|
@ -200,6 +202,14 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
cif->flags = CIF_FLAGS_DINT;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
cif->flags = CIF_FLAGS_SINT16;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
cif->flags = CIF_FLAGS_SINT8;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = CIF_FLAGS_INT;
|
||||
break;
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
sysv.S - Copyright (c) 2012 Alan Hourihane
|
||||
Copyright (c) 1998, 2012 Andreas Schwab
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
m68k Foreign Function Interface
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
Copyright (c) 2012 Thorsten Glaser
|
||||
|
||||
m68k Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -168,8 +169,28 @@ retstruct1:
|
|||
|
||||
retstruct2:
|
||||
btst #7,%d2
|
||||
jbeq noretval
|
||||
jbeq retsint8
|
||||
move.w %d0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retsint8:
|
||||
btst #8,%d2
|
||||
jbeq retsint16
|
||||
| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
|
||||
#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
|
||||
ext.w %d0
|
||||
ext.l %d0
|
||||
#else
|
||||
extb.l %d0
|
||||
#endif
|
||||
move.l %d0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retsint16:
|
||||
btst #9,%d2
|
||||
jbeq noretval
|
||||
ext.l %d0
|
||||
move.l %d0,(%a1)
|
||||
|
||||
noretval:
|
||||
epilogue:
|
||||
|
@ -201,8 +222,10 @@ CALLFUNC(ffi_closure_SYSV):
|
|||
lsr.l #1,%d0
|
||||
jne 1f
|
||||
jcc .Lcls_epilogue
|
||||
| CIF_FLAGS_INT
|
||||
move.l -12(%fp),%d0
|
||||
.Lcls_epilogue:
|
||||
| no CIF_FLAGS_*
|
||||
unlk %fp
|
||||
rts
|
||||
1:
|
||||
|
@ -210,6 +233,7 @@ CALLFUNC(ffi_closure_SYSV):
|
|||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_float
|
||||
| CIF_FLAGS_DINT
|
||||
move.l (%a0)+,%d0
|
||||
move.l (%a0),%d1
|
||||
jra .Lcls_epilogue
|
||||
|
@ -224,6 +248,7 @@ CALLFUNC(ffi_closure_SYSV):
|
|||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_ldouble
|
||||
| CIF_FLAGS_DOUBLE
|
||||
#if defined(__MC68881__) || defined(__HAVE_68881__)
|
||||
fmove.d (%a0),%fp0
|
||||
#else
|
||||
|
@ -242,17 +267,37 @@ CALLFUNC(ffi_closure_SYSV):
|
|||
jra .Lcls_epilogue
|
||||
1:
|
||||
lsr.l #2,%d0
|
||||
jne .Lcls_ret_struct2
|
||||
jne 1f
|
||||
jcs .Lcls_ret_struct1
|
||||
| CIF_FLAGS_POINTER
|
||||
move.l (%a0),%a0
|
||||
move.l %a0,%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_struct1:
|
||||
move.b (%a0),%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_struct2:
|
||||
1:
|
||||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_sint8
|
||||
| CIF_FLAGS_STRUCT2
|
||||
move.w (%a0),%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_sint8:
|
||||
move.l (%a0),%d0
|
||||
| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
|
||||
#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
|
||||
ext.w %d0
|
||||
ext.l %d0
|
||||
#else
|
||||
extb.l %d0
|
||||
#endif
|
||||
jra .Lcls_epilogue
|
||||
1:
|
||||
| CIF_FLAGS_SINT16
|
||||
move.l (%a0),%d0
|
||||
ext.l %d0
|
||||
jra .Lcls_epilogue
|
||||
CFI_ENDPROC()
|
||||
|
||||
.size CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV)
|
||||
|
|
400
libffi/src/m88k/ffi.c
Normal file
400
libffi/src/m88k/ffi.c
Normal file
|
@ -0,0 +1,400 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* m88k Foreign Function Interface
|
||||
*
|
||||
* This file attempts to provide all the FFI entry points which can reliably
|
||||
* be implemented in C.
|
||||
*
|
||||
* Only OpenBSD/m88k is currently supported; other platforms (such as
|
||||
* Motorola's SysV/m88k) could be supported with the following tweaks:
|
||||
*
|
||||
* - non-OpenBSD systems use an `outgoing parameter area' as part of the
|
||||
* 88BCS calling convention, which is not supported under OpenBSD from
|
||||
* release 3.6 onwards. Supporting it should be as easy as taking it
|
||||
* into account when adjusting the stack, in the assembly code.
|
||||
*
|
||||
* - the logic deciding whether a function argument gets passed through
|
||||
* registers, or on the stack, has changed several times in OpenBSD in
|
||||
* edge cases (especially for structs larger than 32 bytes being passed
|
||||
* by value). The code below attemps to match the logic used by the
|
||||
* system compiler of OpenBSD 5.3, i.e. gcc 3.3.6 with many m88k backend
|
||||
* fixes.
|
||||
*/
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void ffi_call_OBSD (unsigned int, extended_cif *, unsigned int, void *,
|
||||
void (*fn) ());
|
||||
void *ffi_prep_args (void *, extended_cif *);
|
||||
void ffi_closure_OBSD (ffi_closure *);
|
||||
void ffi_closure_struct_OBSD (ffi_closure *);
|
||||
unsigned int ffi_closure_OBSD_inner (ffi_closure *, void *, unsigned int *,
|
||||
char *);
|
||||
void ffi_cacheflush_OBSD (unsigned int, unsigned int);
|
||||
|
||||
#define CIF_FLAGS_INT (1 << 0)
|
||||
#define CIF_FLAGS_DINT (1 << 1)
|
||||
|
||||
/*
|
||||
* Foreign Function Interface API
|
||||
*/
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space has
|
||||
been allocated for the function's arguments. */
|
||||
|
||||
void *
|
||||
ffi_prep_args (void *stack, extended_cif *ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
void **p_argv;
|
||||
char *argp, *stackp;
|
||||
unsigned int *regp;
|
||||
unsigned int regused;
|
||||
ffi_type **p_arg;
|
||||
void *struct_value_ptr;
|
||||
|
||||
regp = (unsigned int *)stack;
|
||||
stackp = (char *)(regp + 8);
|
||||
regused = 0;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& !ecif->cif->flags)
|
||||
struct_value_ptr = ecif->rvalue;
|
||||
else
|
||||
struct_value_ptr = NULL;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i != 0; i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
unsigned short t, a;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
t = (*p_arg)->type;
|
||||
a = (*p_arg)->alignment;
|
||||
|
||||
/*
|
||||
* Figure out whether the argument can be passed through registers
|
||||
* or on the stack.
|
||||
* The rule is that registers can only receive simple types not larger
|
||||
* than 64 bits, or structs the exact size of a register and aligned to
|
||||
* the size of a register.
|
||||
*/
|
||||
if (t == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (z == sizeof (int) && a == sizeof (int) && regused < 8)
|
||||
argp = (char *)regp;
|
||||
else
|
||||
argp = stackp;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (z > sizeof (int) && regused < 8 - 1)
|
||||
{
|
||||
/* align to an even register pair */
|
||||
if (regused & 1)
|
||||
{
|
||||
regp++;
|
||||
regused++;
|
||||
}
|
||||
}
|
||||
if (regused < 8)
|
||||
argp = (char *)regp;
|
||||
else
|
||||
argp = stackp;
|
||||
}
|
||||
|
||||
/* Enforce proper stack alignment of 64-bit types */
|
||||
if (argp == stackp && a > sizeof (int))
|
||||
{
|
||||
stackp = (char *) ALIGN(stackp, a);
|
||||
argp = stackp;
|
||||
}
|
||||
|
||||
switch (t)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(unsigned int *) argp = *(unsigned int *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp, *p_argv, z);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
|
||||
/* Align if necessary. */
|
||||
if ((sizeof (int) - 1) & z)
|
||||
z = ALIGN(z, sizeof (int));
|
||||
|
||||
p_argv++;
|
||||
|
||||
/* Be careful, once all registers are filled, and about to continue
|
||||
on stack, regp == stackp. Therefore the check for regused as well. */
|
||||
if (argp == (char *)regp && regused < 8)
|
||||
{
|
||||
regp += z / sizeof (int);
|
||||
regused += z / sizeof (int);
|
||||
}
|
||||
else
|
||||
stackp += z;
|
||||
}
|
||||
|
||||
return struct_value_ptr;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
cif->flags = 0;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size == sizeof (int) &&
|
||||
cif->rtype->alignment == sizeof (int))
|
||||
cif->flags = CIF_FLAGS_INT;
|
||||
else
|
||||
cif->flags = 0;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = CIF_FLAGS_DINT;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = CIF_FLAGS_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return value
|
||||
address then we need to make one. */
|
||||
|
||||
if (rvalue == NULL
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& (cif->rtype->size != sizeof (int)
|
||||
|| cif->rtype->alignment != sizeof (int)))
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_OBSD:
|
||||
ffi_call_OBSD (cif->bytes, &ecif, cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Closure API
|
||||
*/
|
||||
|
||||
static void
|
||||
ffi_prep_closure_args_OBSD (ffi_cif *cif, void **avalue, unsigned int *regp,
|
||||
char *stackp)
|
||||
{
|
||||
unsigned int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
unsigned int regused;
|
||||
ffi_type **p_arg;
|
||||
|
||||
regused = 0;
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
unsigned short t, a;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
t = (*p_arg)->type;
|
||||
a = (*p_arg)->alignment;
|
||||
|
||||
/*
|
||||
* Figure out whether the argument has been passed through registers
|
||||
* or on the stack.
|
||||
* The rule is that registers can only receive simple types not larger
|
||||
* than 64 bits, or structs the exact size of a register and aligned to
|
||||
* the size of a register.
|
||||
*/
|
||||
if (t == FFI_TYPE_STRUCT)
|
||||
{
|
||||
if (z == sizeof (int) && a == sizeof (int) && regused < 8)
|
||||
argp = (char *)regp;
|
||||
else
|
||||
argp = stackp;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (z > sizeof (int) && regused < 8 - 1)
|
||||
{
|
||||
/* align to an even register pair */
|
||||
if (regused & 1)
|
||||
{
|
||||
regp++;
|
||||
regused++;
|
||||
}
|
||||
}
|
||||
if (regused < 8)
|
||||
argp = (char *)regp;
|
||||
else
|
||||
argp = stackp;
|
||||
}
|
||||
|
||||
/* Enforce proper stack alignment of 64-bit types */
|
||||
if (argp == stackp && a > sizeof (int))
|
||||
{
|
||||
stackp = (char *) ALIGN(stackp, a);
|
||||
argp = stackp;
|
||||
}
|
||||
|
||||
if (z < sizeof (int) && t != FFI_TYPE_STRUCT)
|
||||
*p_argv = (void *) (argp + sizeof (int) - z);
|
||||
else
|
||||
*p_argv = (void *) argp;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof (int) - 1) & z)
|
||||
z = ALIGN(z, sizeof (int));
|
||||
|
||||
p_argv++;
|
||||
|
||||
/* Be careful, once all registers are exhausted, and about to fetch from
|
||||
stack, regp == stackp. Therefore the check for regused as well. */
|
||||
if (argp == (char *)regp && regused < 8)
|
||||
{
|
||||
regp += z / sizeof (int);
|
||||
regused += z / sizeof (int);
|
||||
}
|
||||
else
|
||||
stackp += z;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
ffi_closure_OBSD_inner (ffi_closure *closure, void *resp, unsigned int *regp,
|
||||
char *stackp)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
ffi_prep_closure_args_OBSD(cif, arg_area, regp, stackp);
|
||||
|
||||
(closure->fun) (cif, resp, 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)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) codeloc;
|
||||
void *fn;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_OBSD);
|
||||
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT && !cif->flags)
|
||||
fn = &ffi_closure_struct_OBSD;
|
||||
else
|
||||
fn = &ffi_closure_OBSD;
|
||||
|
||||
/* or.u %r10, %r0, %hi16(fn) */
|
||||
tramp[0] = 0x5d400000 | (((unsigned int)fn) >> 16);
|
||||
/* or.u %r13, %r0, %hi16(closure) */
|
||||
tramp[1] = 0x5da00000 | ((unsigned int)closure >> 16);
|
||||
/* or %r10, %r10, %lo16(fn) */
|
||||
tramp[2] = 0x594a0000 | (((unsigned int)fn) & 0xffff);
|
||||
/* jmp.n %r10 */
|
||||
tramp[3] = 0xf400c40a;
|
||||
/* or %r13, %r13, %lo16(closure) */
|
||||
tramp[4] = 0x59ad0000 | ((unsigned int)closure & 0xffff);
|
||||
|
||||
ffi_cacheflush_OBSD((unsigned int)codeloc, FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
49
libffi/src/m88k/ffitarget.h
Normal file
49
libffi/src/m88k/ffitarget.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* m88k Foreign Function Interface
|
||||
*/
|
||||
|
||||
#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_OBSD,
|
||||
FFI_DEFAULT_ABI = FFI_OBSD,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 0x14
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
209
libffi/src/m88k/obsd.S
Normal file
209
libffi/src/m88k/obsd.S
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* m88k Foreign Function Interface
|
||||
*/
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* ffi_cacheflush_OBSD(unsigned int addr, %r2
|
||||
* unsigned int size); %r3
|
||||
*/
|
||||
.align 4
|
||||
.globl ffi_cacheflush_OBSD
|
||||
.type ffi_cacheflush_OBSD,@function
|
||||
ffi_cacheflush_OBSD:
|
||||
tb0 0, %r0, 451
|
||||
or %r0, %r0, %r0
|
||||
jmp %r1
|
||||
.size ffi_cacheflush_OBSD, . - ffi_cacheflush_OBSD
|
||||
|
||||
/*
|
||||
* ffi_call_OBSD(unsigned bytes, %r2
|
||||
* extended_cif *ecif, %r3
|
||||
* unsigned flags, %r4
|
||||
* void *rvalue, %r5
|
||||
* void (*fn)()); %r6
|
||||
*/
|
||||
.align 4
|
||||
.globl ffi_call_OBSD
|
||||
.type ffi_call_OBSD,@function
|
||||
ffi_call_OBSD:
|
||||
subu %r31, %r31, 32
|
||||
st %r30, %r31, 4
|
||||
st %r1, %r31, 0
|
||||
addu %r30, %r31, 32
|
||||
|
||||
| Save the few arguments we'll need after ffi_prep_args()
|
||||
st.d %r4, %r31, 8
|
||||
st %r6, %r31, 16
|
||||
|
||||
| Allocate room for the image of r2-r9, and the stack space for
|
||||
| the args (rounded to a 16-byte boundary)
|
||||
addu %r2, %r2, (8 * 4) + 15
|
||||
clr %r2, %r2, 4<0>
|
||||
subu %r31, %r31, %r2
|
||||
|
||||
| Fill register and stack image
|
||||
or %r2, %r31, %r0
|
||||
#ifdef PIC
|
||||
bsr ffi_prep_args#plt
|
||||
#else
|
||||
bsr ffi_prep_args
|
||||
#endif
|
||||
|
||||
| Save pointer to return struct address, if any
|
||||
or %r12, %r2, %r0
|
||||
|
||||
| Get function pointer
|
||||
subu %r4, %r30, 32
|
||||
ld %r1, %r4, 16
|
||||
|
||||
| Fetch the register arguments
|
||||
ld.d %r2, %r31, (0 * 4)
|
||||
ld.d %r4, %r31, (2 * 4)
|
||||
ld.d %r6, %r31, (4 * 4)
|
||||
ld.d %r8, %r31, (6 * 4)
|
||||
addu %r31, %r31, (8 * 4)
|
||||
|
||||
| Invoke the function
|
||||
jsr %r1
|
||||
|
||||
| Restore stack now that we don't need the args anymore
|
||||
subu %r31, %r30, 32
|
||||
|
||||
| Figure out what to return as the function's return value
|
||||
ld %r5, %r31, 12 | rvalue
|
||||
ld %r4, %r31, 8 | flags
|
||||
|
||||
bcnd eq0, %r5, 9f
|
||||
|
||||
bb0 0, %r4, 1f | CIF_FLAGS_INT
|
||||
st %r2, %r5, 0
|
||||
br 9f
|
||||
|
||||
1:
|
||||
bb0 1, %r4, 1f | CIF_FLAGS_DINT
|
||||
st.d %r2, %r5, 0
|
||||
br 9f
|
||||
|
||||
1:
|
||||
9:
|
||||
ld %r1, %r31, 0
|
||||
ld %r30, %r31, 4
|
||||
jmp.n %r1
|
||||
addu %r31, %r31, 32
|
||||
.size ffi_call_OBSD, . - ffi_call_OBSD
|
||||
|
||||
/*
|
||||
* ffi_closure_OBSD(ffi_closure *closure); %r13
|
||||
*/
|
||||
.align 4
|
||||
.globl ffi_closure_OBSD
|
||||
.type ffi_closure_OBSD, @function
|
||||
ffi_closure_OBSD:
|
||||
subu %r31, %r31, 16
|
||||
st %r30, %r31, 4
|
||||
st %r1, %r31, 0
|
||||
addu %r30, %r31, 16
|
||||
|
||||
| Make room on the stack for saved register arguments and return
|
||||
| value
|
||||
subu %r31, %r31, (8 * 4) + (2 * 4)
|
||||
st.d %r2, %r31, (0 * 4)
|
||||
st.d %r4, %r31, (2 * 4)
|
||||
st.d %r6, %r31, (4 * 4)
|
||||
st.d %r8, %r31, (6 * 4)
|
||||
|
||||
| Invoke the closure function
|
||||
or %r5, %r30, 0 | calling stack
|
||||
addu %r4, %r31, 0 | saved registers
|
||||
addu %r3, %r31, (8 * 4) | return value
|
||||
or %r2, %r13, %r0 | closure
|
||||
#ifdef PIC
|
||||
bsr ffi_closure_OBSD_inner#plt
|
||||
#else
|
||||
bsr ffi_closure_OBSD_inner
|
||||
#endif
|
||||
|
||||
| Figure out what to return as the function's return value
|
||||
bb0 0, %r2, 1f | CIF_FLAGS_INT
|
||||
ld %r2, %r31, (8 * 4)
|
||||
br 9f
|
||||
|
||||
1:
|
||||
bb0 1, %r2, 1f | CIF_FLAGS_DINT
|
||||
ld.d %r2, %r31, (8 * 4)
|
||||
br 9f
|
||||
|
||||
1:
|
||||
9:
|
||||
subu %r31, %r30, 16
|
||||
ld %r1, %r31, 0
|
||||
ld %r30, %r31, 4
|
||||
jmp.n %r1
|
||||
addu %r31, %r31, 16
|
||||
.size ffi_closure_OBSD,.-ffi_closure_OBSD
|
||||
|
||||
/*
|
||||
* ffi_closure_struct_OBSD(ffi_closure *closure); %r13
|
||||
*/
|
||||
.align 4
|
||||
.globl ffi_closure_struct_OBSD
|
||||
.type ffi_closure_struct_OBSD, @function
|
||||
ffi_closure_struct_OBSD:
|
||||
subu %r31, %r31, 16
|
||||
st %r30, %r31, 4
|
||||
st %r1, %r31, 0
|
||||
addu %r30, %r31, 16
|
||||
|
||||
| Make room on the stack for saved register arguments
|
||||
subu %r31, %r31, (8 * 4)
|
||||
st.d %r2, %r31, (0 * 4)
|
||||
st.d %r4, %r31, (2 * 4)
|
||||
st.d %r6, %r31, (4 * 4)
|
||||
st.d %r8, %r31, (6 * 4)
|
||||
|
||||
| Invoke the closure function
|
||||
or %r5, %r30, 0 | calling stack
|
||||
addu %r4, %r31, 0 | saved registers
|
||||
or %r3, %r12, 0 | return value
|
||||
or %r2, %r13, %r0 | closure
|
||||
#ifdef PIC
|
||||
bsr ffi_closure_OBSD_inner#plt
|
||||
#else
|
||||
bsr ffi_closure_OBSD_inner
|
||||
#endif
|
||||
|
||||
subu %r31, %r30, 16
|
||||
ld %r1, %r31, 0
|
||||
ld %r30, %r31, 4
|
||||
jmp.n %r1
|
||||
addu %r31, %r31, 16
|
||||
.size ffi_closure_struct_OBSD,.-ffi_closure_struct_OBSD
|
330
libffi/src/metag/ffi.c
Normal file
330
libffi/src/metag/ffi.c
Normal file
|
@ -0,0 +1,330 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2013 Imagination Technologies
|
||||
|
||||
Meta 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 SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
/*
|
||||
* ffi_prep_args is called by the assembly routine once stack space has been
|
||||
* allocated for the function's arguments
|
||||
*/
|
||||
|
||||
unsigned int ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
/* Store return value */
|
||||
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
|
||||
argp -= 4;
|
||||
*(void **) argp = ecif->rvalue;
|
||||
}
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
/* point to next location */
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++, p_argv++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Move argp to address of argument */
|
||||
z = (*p_arg)->size;
|
||||
argp -= z;
|
||||
|
||||
/* Align if necessary */
|
||||
argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4);
|
||||
|
||||
if (z < sizeof(int)) {
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
} else if ( z == sizeof(int)) {
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
} else {
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
}
|
||||
|
||||
/* return the size of the arguments to be passed in registers,
|
||||
padded to an 8 byte boundary to preserve stack alignment */
|
||||
return ALIGN(MIN(stack - argp, 6*4), 8);
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
unsigned i, bytes = 0;
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) {
|
||||
if ((*ptr)->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
bytes += ALIGN((*ptr)->size, 4);
|
||||
}
|
||||
|
||||
/* Ensure arg space is aligned to an 8-byte boundary */
|
||||
bytes = ALIGN(bytes, 8);
|
||||
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT) {
|
||||
bytes += sizeof(void*);
|
||||
|
||||
/* Ensure stack is aligned to an 8-byte boundary */
|
||||
bytes = ALIGN(bytes, 8);
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type) {
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = (unsigned) FFI_TYPE_SINT64;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Meta can store return values which are <= 64 bits */
|
||||
if (cif->rtype->size <= 4)
|
||||
/* Returned to D0Re0 as 32-bit value */
|
||||
cif->flags = (unsigned)FFI_TYPE_INT;
|
||||
else if ((cif->rtype->size > 4) && (cif->rtype->size <= 8))
|
||||
/* Returned valued is stored to D1Re0|R0Re0 */
|
||||
cif->flags = (unsigned)FFI_TYPE_DOUBLE;
|
||||
else
|
||||
/* value stored in memory */
|
||||
cif->flags = (unsigned)FFI_TYPE_STRUCT;
|
||||
break;
|
||||
default:
|
||||
cif->flags = (unsigned)FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(void (*fn)(void), extended_cif *, unsigned, unsigned, double *);
|
||||
|
||||
/*
|
||||
* Exported in API. Entry point
|
||||
* cif -> ffi_cif object
|
||||
* fn -> function pointer
|
||||
* rvalue -> pointer to return value
|
||||
* avalue -> vector of void * pointers pointing to memory locations holding the
|
||||
* arguments
|
||||
*/
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
int small_struct = (((cif->flags == FFI_TYPE_INT) || (cif->flags == FFI_TYPE_DOUBLE)) && (cif->rtype->type == FFI_TYPE_STRUCT));
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
double temp;
|
||||
|
||||
/*
|
||||
* If the return value is a struct and we don't have a return value address
|
||||
* then we need to make one
|
||||
*/
|
||||
|
||||
if ((rvalue == NULL ) && (cif->flags == FFI_TYPE_STRUCT))
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
else if (small_struct)
|
||||
ecif.rvalue = &temp;
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi) {
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (small_struct)
|
||||
memcpy (rvalue, &temp, cif->rtype->size);
|
||||
}
|
||||
|
||||
/* private members */
|
||||
|
||||
static void ffi_prep_incoming_args_SYSV (char *, void **, void **,
|
||||
ffi_cif*, float *);
|
||||
|
||||
void ffi_closure_SYSV (ffi_closure *);
|
||||
|
||||
/* Do NOT change that without changing the FFI_TRAMPOLINE_SIZE */
|
||||
extern unsigned int ffi_metag_trampoline[10]; /* 10 instructions */
|
||||
|
||||
/* end of private members */
|
||||
|
||||
/*
|
||||
* __tramp: trampoline memory location
|
||||
* __fun: assembly routine
|
||||
* __ctx: memory location for wrapper
|
||||
*
|
||||
* At this point, tramp[0] == __ctx !
|
||||
*/
|
||||
void ffi_init_trampoline(unsigned char *__tramp, unsigned int __fun, unsigned int __ctx) {
|
||||
memcpy (__tramp, ffi_metag_trampoline, sizeof(ffi_metag_trampoline));
|
||||
*(unsigned int*) &__tramp[40] = __ctx;
|
||||
*(unsigned int*) &__tramp[44] = __fun;
|
||||
/* This will flush the instruction cache */
|
||||
__builtin_meta2_cachewd(&__tramp[0], 1);
|
||||
__builtin_meta2_cachewd(&__tramp[47], 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* the cif must already be prepared */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure *closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
void (*closure_func)(ffi_closure*) = NULL;
|
||||
|
||||
if (cif->abi == FFI_SYSV)
|
||||
closure_func = &ffi_closure_SYSV;
|
||||
else
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
ffi_init_trampoline(
|
||||
(unsigned char*)&closure->tramp[0],
|
||||
(unsigned int)closure_func,
|
||||
(unsigned int)codeloc);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
unsigned int ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
void *vfp_args;
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/*
|
||||
* 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, vfp_args);
|
||||
|
||||
(closure->fun) ( cif, *respp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||
void **avalue, ffi_cif *cif,
|
||||
float *vfp_stack)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
/* stack points to original arguments */
|
||||
argp = stack;
|
||||
|
||||
/* Store return value */
|
||||
if ( cif->flags == FFI_TYPE_STRUCT ) {
|
||||
argp -= 4;
|
||||
*rvalue = *(void **) argp;
|
||||
}
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) {
|
||||
size_t z;
|
||||
size_t alignment;
|
||||
|
||||
alignment = (*p_arg)->alignment;
|
||||
if (alignment < 4)
|
||||
alignment = 4;
|
||||
if ((alignment - 1) & (unsigned)argp)
|
||||
argp = (char *) ALIGN(argp, alignment);
|
||||
|
||||
z = (*p_arg)->size;
|
||||
*p_argv = (void*) argp;
|
||||
p_argv++;
|
||||
argp -= z;
|
||||
}
|
||||
return;
|
||||
}
|
53
libffi/src/metag/ffitarget.h
Normal file
53
libffi/src/metag/ffitarget.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2013 Imagination Technologies Ltd.
|
||||
Target configuration macros for Meta
|
||||
|
||||
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_DEFAULT_ABI = FFI_SYSV,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1,
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 48
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
311
libffi/src/metag/sysv.S
Normal file
311
libffi/src/metag/sysv.S
Normal file
|
@ -0,0 +1,311 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2013 Imagination Technologies Ltd.
|
||||
|
||||
Meta 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>
|
||||
#ifdef HAVE_MACHINE_ASM_H
|
||||
#include <machine/asm.h>
|
||||
#else
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a ## b
|
||||
|
||||
/* Use the right prefix for global labels. */
|
||||
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
||||
#else
|
||||
#define CNAME(x) x
|
||||
#endif
|
||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x), %function; CNAME(x):
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
#define LSYM(x) .x
|
||||
#else
|
||||
#define LSYM(x) x
|
||||
#endif
|
||||
|
||||
.macro call_reg x=
|
||||
.text
|
||||
.balign 4
|
||||
mov D1RtP, \x
|
||||
swap D1RtP, PC
|
||||
.endm
|
||||
|
||||
! Save register arguments
|
||||
.macro SAVE_ARGS
|
||||
.text
|
||||
.balign 4
|
||||
setl [A0StP++], D0Ar6, D1Ar5
|
||||
setl [A0StP++], D0Ar4, D1Ar3
|
||||
setl [A0StP++], D0Ar2, D1Ar1
|
||||
.endm
|
||||
|
||||
! Save retrun, frame pointer and other regs
|
||||
.macro SAVE_REGS regs=
|
||||
.text
|
||||
.balign 4
|
||||
setl [A0StP++], D0FrT, D1RtP
|
||||
! Needs to be a pair of regs
|
||||
.ifnc "\regs",""
|
||||
setl [A0StP++], \regs
|
||||
.endif
|
||||
.endm
|
||||
|
||||
! Declare a global function
|
||||
.macro METAG_FUNC_START name
|
||||
.text
|
||||
.balign 4
|
||||
ENTRY(\name)
|
||||
.endm
|
||||
|
||||
! Return registers from the stack. Reverse SAVE_REGS operation
|
||||
.macro RET_REGS regs=, cond=
|
||||
.ifnc "\regs", ""
|
||||
getl \regs, [--A0StP]
|
||||
.endif
|
||||
getl D0FrT, D1RtP, [--A0StP]
|
||||
.endm
|
||||
|
||||
! Return arguments
|
||||
.macro RET_ARGS
|
||||
getl D0Ar2, D1Ar1, [--A0StP]
|
||||
getl D0Ar4, D1Ar3, [--A0StP]
|
||||
getl D0Ar6, D1Ar5, [--A0StP]
|
||||
.endm
|
||||
|
||||
|
||||
! D1Ar1: fn
|
||||
! D0Ar2: &ecif
|
||||
! D1Ar3: cif->bytes
|
||||
! D0Ar4: fig->flags
|
||||
! D1Ar5: ecif.rvalue
|
||||
|
||||
! This assumes we are using GNU as
|
||||
METAG_FUNC_START ffi_call_SYSV
|
||||
! Save argument registers
|
||||
|
||||
SAVE_ARGS
|
||||
|
||||
! new frame
|
||||
mov D0FrT, A0FrP
|
||||
add A0FrP, A0StP, #0
|
||||
|
||||
! Preserve the old frame pointer
|
||||
SAVE_REGS "D1.5, D0.5"
|
||||
|
||||
! Make room for new args. cifs->bytes is the total space for input
|
||||
! and return arguments
|
||||
|
||||
add A0StP, A0StP, D1Ar3
|
||||
|
||||
! Preserve cifs->bytes & fn
|
||||
mov D0.5, D1Ar3
|
||||
mov D1.5, D1Ar1
|
||||
|
||||
! Place all of the ffi_prep_args in position
|
||||
mov D1Ar1, A0StP
|
||||
|
||||
! Call ffi_prep_args(stack, &ecif)
|
||||
#ifdef __PIC__
|
||||
callr D1RtP, CNAME(ffi_prep_args@PLT)
|
||||
#else
|
||||
callr D1RtP, CNAME(ffi_prep_args)
|
||||
#endif
|
||||
|
||||
! Restore fn pointer
|
||||
|
||||
! The foreign stack should look like this
|
||||
! XXXXX XXXXXX <--- stack pointer
|
||||
! FnArgN rvalue
|
||||
! FnArgN+2 FnArgN+1
|
||||
! FnArgN+4 FnArgN+3
|
||||
! ....
|
||||
!
|
||||
|
||||
! A0StP now points to the first (or return) argument + 4
|
||||
|
||||
! Preserve cif->bytes
|
||||
getl D0Ar2, D1Ar1, [--A0StP]
|
||||
getl D0Ar4, D1Ar3, [--A0StP]
|
||||
getl D0Ar6, D1Ar5, [--A0StP]
|
||||
|
||||
! Place A0StP to the first argument again
|
||||
add A0StP, A0StP, #24 ! That's because we loaded 6 regs x 4 byte each
|
||||
|
||||
! A0FrP points to the initial stack without the reserved space for the
|
||||
! cifs->bytes, whilst A0StP points to the stack after the space allocation
|
||||
|
||||
! fn was the first argument of ffi_call_SYSV.
|
||||
! The stack at this point looks like this:
|
||||
!
|
||||
! A0StP(on entry to _SYSV) -> Arg6 Arg5 | low
|
||||
! Arg4 Arg3 |
|
||||
! Arg2 Arg1 |
|
||||
! A0FrP ----> D0FrtP D1RtP |
|
||||
! D1.5 D0.5 |
|
||||
! A0StP(bf prep_args) -> FnArgn FnArgn-1 |
|
||||
! FnArgn-2FnArgn-3 |
|
||||
! ................ | <= cifs->bytes
|
||||
! FnArg4 FnArg3 |
|
||||
! A0StP (prv_A0StP+cifs->bytes) FnArg2 FnArg1 | high
|
||||
!
|
||||
! fn was in Arg1 so it's located in in A0FrP+#-0xC
|
||||
!
|
||||
|
||||
! D0Re0 contains the size of arguments stored in registers
|
||||
sub A0StP, A0StP, D0Re0
|
||||
|
||||
! Arg1 is the function pointer for the foreign call. This has been
|
||||
! preserved in D1.5
|
||||
|
||||
! Time to call (fn). Arguments should be like this:
|
||||
! Arg1-Arg6 are loaded to regs
|
||||
! The rest of the arguments are stored in stack pointed by A0StP
|
||||
|
||||
call_reg D1.5
|
||||
|
||||
! Reset stack.
|
||||
|
||||
mov A0StP, A0FrP
|
||||
|
||||
! Load Arg1 with the pointer to storage for the return type
|
||||
! This was stored in Arg5
|
||||
|
||||
getd D1Ar1, [A0FrP+#-20]
|
||||
|
||||
! Load D0Ar2 with the return type code. This was stored in Arg4 (flags)
|
||||
|
||||
getd D0Ar2, [A0FrP+#-16]
|
||||
|
||||
! We are ready to start processing the return value
|
||||
! D0Re0 (and D1Re0) hold the return value
|
||||
|
||||
! If the return value is NULL, assume no return value
|
||||
cmp D1Ar1, #0
|
||||
beq LSYM(Lepilogue)
|
||||
|
||||
! return INT
|
||||
cmp D0Ar2, #FFI_TYPE_INT
|
||||
! Sadly, there is no setd{cc} instruction so we need to workaround that
|
||||
bne .INT64
|
||||
setd [D1Ar1], D0Re0
|
||||
b LSYM(Lepilogue)
|
||||
|
||||
! return INT64
|
||||
.INT64:
|
||||
cmp D0Ar2, #FFI_TYPE_SINT64
|
||||
setleq [D1Ar1], D0Re0, D1Re0
|
||||
|
||||
! return DOUBLE
|
||||
cmp D0Ar2, #FFI_TYPE_DOUBLE
|
||||
setl [D1AR1++], D0Re0, D1Re0
|
||||
|
||||
LSYM(Lepilogue):
|
||||
! At this point, the stack pointer points right after the argument
|
||||
! saved area. We need to restore 4 regs, therefore we need to move
|
||||
! 16 bytes ahead.
|
||||
add A0StP, A0StP, #16
|
||||
RET_REGS "D1.5, D0.5"
|
||||
RET_ARGS
|
||||
getd D0Re0, [A0StP]
|
||||
mov A0FrP, D0FrT
|
||||
swap D1RtP, PC
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
|
||||
/*
|
||||
(called by ffi_metag_trampoline)
|
||||
void ffi_closure_SYSV (ffi_closure*)
|
||||
|
||||
(called by ffi_closure_SYSV)
|
||||
unsigned int FFI_HIDDEN
|
||||
ffi_closure_SYSV_inner (closure,respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
*/
|
||||
|
||||
METAG_FUNC_START ffi_closure_SYSV
|
||||
! We assume that D1Ar1 holds the address of the
|
||||
! ffi_closure struct. We will use that to fetch the
|
||||
! arguments. The stack pointer points to an empty space
|
||||
! and it is ready to store more data.
|
||||
|
||||
! D1Ar1 is ready
|
||||
! Allocate stack space for return value
|
||||
add A0StP, A0StP, #8
|
||||
! Store it to D0Ar2
|
||||
sub D0Ar2, A0StP, #8
|
||||
|
||||
sub D1Ar3, A0FrP, #4
|
||||
|
||||
! D1Ar3 contains the address of the original D1Ar1 argument
|
||||
! We need to subtract #4 later on
|
||||
|
||||
! Preverve D0Ar2
|
||||
mov D0.5, D0Ar2
|
||||
|
||||
#ifdef __PIC__
|
||||
callr D1RtP, CNAME(ffi_closure_SYSV_inner@PLT)
|
||||
#else
|
||||
callr D1RtP, CNAME(ffi_closure_SYSV_inner)
|
||||
#endif
|
||||
|
||||
! Check the return value and store it to D0.5
|
||||
cmp D0Re0, #FFI_TYPE_INT
|
||||
beq .Lretint
|
||||
cmp D0Re0, #FFI_TYPE_DOUBLE
|
||||
beq .Lretdouble
|
||||
.Lclosure_epilogue:
|
||||
sub A0StP, A0StP, #8
|
||||
RET_REGS "D1.5, D0.5"
|
||||
RET_ARGS
|
||||
swap D1RtP, PC
|
||||
|
||||
.Lretint:
|
||||
setd [D0.5], D0Re0
|
||||
b .Lclosure_epilogue
|
||||
.Lretdouble:
|
||||
setl [D0.5++], D0Re0, D1Re0
|
||||
b .Lclosure_epilogue
|
||||
.ffi_closure_SYSV_end:
|
||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
||||
|
||||
|
||||
ENTRY(ffi_metag_trampoline)
|
||||
SAVE_ARGS
|
||||
! New frame
|
||||
mov A0FrP, A0StP
|
||||
SAVE_REGS "D1.5, D0.5"
|
||||
mov D0.5, PC
|
||||
! Load D1Ar1 the value of ffi_metag_trampoline
|
||||
getd D1Ar1, [D0.5 + #8]
|
||||
! Jump to ffi_closure_SYSV
|
||||
getd PC, [D0.5 + #12]
|
321
libffi/src/microblaze/ffi.c
Normal file
321
libffi/src/microblaze/ffi.c
Normal file
|
@ -0,0 +1,321 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2012, 2013 Xilinx, Inc
|
||||
|
||||
MicroBlaze 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>
|
||||
|
||||
extern void ffi_call_SYSV(void (*)(void*, extended_cif*), extended_cif*,
|
||||
unsigned int, unsigned int, unsigned int*, void (*fn)(void),
|
||||
unsigned int, unsigned int);
|
||||
|
||||
extern void ffi_closure_SYSV(void);
|
||||
|
||||
#define WORD_SIZE sizeof(unsigned int)
|
||||
#define ARGS_REGISTER_SIZE (WORD_SIZE * 6)
|
||||
#define WORD_ALIGN(x) ALIGN(x, WORD_SIZE)
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
void ffi_prep_args(void* stack, extended_cif* ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
ffi_type** p_arg;
|
||||
void** p_argv;
|
||||
void* stack_args_p = stack;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
if (ecif == NULL || ecif->cif == NULL) {
|
||||
return; /* no description to prepare */
|
||||
}
|
||||
|
||||
if ((ecif->cif->rtype != NULL) &&
|
||||
(ecif->cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/* if return type is a struct which is referenced on the stack/reg5,
|
||||
* by a pointer. Stored the return value pointer in r5.
|
||||
*/
|
||||
char* addr = stack_args_p;
|
||||
memcpy(addr, &(ecif->rvalue), WORD_SIZE);
|
||||
stack_args_p += WORD_SIZE;
|
||||
}
|
||||
|
||||
if (ecif->avalue == NULL) {
|
||||
return; /* no arguments to prepare */
|
||||
}
|
||||
|
||||
for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
|
||||
i++, p_arg++)
|
||||
{
|
||||
size_t size = (*p_arg)->size;
|
||||
int type = (*p_arg)->type;
|
||||
void* value = p_argv[i];
|
||||
char* addr = stack_args_p;
|
||||
int aligned_size = WORD_ALIGN(size);
|
||||
|
||||
/* force word alignment on the stack */
|
||||
stack_args_p += aligned_size;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *)addr = (unsigned int)*(UINT8*)(value);
|
||||
break;
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *)addr = (signed int)*(SINT8*)(value);
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *)addr = (unsigned int)*(UINT16*)(value);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *)addr = (signed int)*(SINT16*)(value);
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if __BIG_ENDIAN__
|
||||
/*
|
||||
* MicroBlaze toolchain appears to emit:
|
||||
* bsrli r5, r5, 8 (caller)
|
||||
* ...
|
||||
* <branch to callee>
|
||||
* ...
|
||||
* bslli r5, r5, 8 (callee)
|
||||
*
|
||||
* For structs like "struct a { uint8_t a[3]; };", when passed
|
||||
* by value.
|
||||
*
|
||||
* Structs like "struct b { uint16_t a; };" are also expected
|
||||
* to be packed strangely in registers.
|
||||
*
|
||||
* This appears to be because the microblaze toolchain expects
|
||||
* "struct b == uint16_t", which is only any issue for big
|
||||
* endian.
|
||||
*
|
||||
* The following is a work around for big-endian only, for the
|
||||
* above mentioned case, it will re-align the contents of a
|
||||
* <= 3-byte struct value.
|
||||
*/
|
||||
if (size < WORD_SIZE)
|
||||
{
|
||||
memcpy (addr + (WORD_SIZE - size), value, size);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
default:
|
||||
memcpy(addr, value, aligned_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif* cif)
|
||||
{
|
||||
/* check ABI */
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
break;
|
||||
default:
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
void ffi_call(ffi_cif* cif, void (*fn)(void), void* rvalue, void** avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
} else {
|
||||
ecif.rvalue = rvalue;
|
||||
}
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn, cif->rtype->type, cif->rtype->size);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ffi_closure_call_SYSV(void* register_args, void* stack_args,
|
||||
ffi_closure* closure, void* rvalue,
|
||||
unsigned int* rtype, unsigned int* rsize)
|
||||
{
|
||||
/* prepare arguments for closure call */
|
||||
ffi_cif* cif = closure->cif;
|
||||
ffi_type** arg_types = cif->arg_types;
|
||||
|
||||
/* re-allocate data for the args. This needs to be done in order to keep
|
||||
* multi-word objects (e.g. structs) in contiguous memory. Callers are not
|
||||
* required to store the value of args in the lower 6 words in the stack
|
||||
* (although they are allocated in the stack).
|
||||
*/
|
||||
char* stackclone = alloca(cif->bytes);
|
||||
void** avalue = alloca(cif->nargs * sizeof(void*));
|
||||
void* struct_rvalue = NULL;
|
||||
char* ptr = stackclone;
|
||||
int i;
|
||||
|
||||
/* copy registers into stack clone */
|
||||
int registers_used = cif->bytes;
|
||||
if (registers_used > ARGS_REGISTER_SIZE) {
|
||||
registers_used = ARGS_REGISTER_SIZE;
|
||||
}
|
||||
memcpy(stackclone, register_args, registers_used);
|
||||
|
||||
/* copy stack allocated args into stack clone */
|
||||
if (cif->bytes > ARGS_REGISTER_SIZE) {
|
||||
int stack_used = cif->bytes - ARGS_REGISTER_SIZE;
|
||||
memcpy(stackclone + ARGS_REGISTER_SIZE, stack_args, stack_used);
|
||||
}
|
||||
|
||||
/* preserve struct type return pointer passing */
|
||||
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
|
||||
struct_rvalue = *((void**)ptr);
|
||||
ptr += WORD_SIZE;
|
||||
}
|
||||
|
||||
/* populate arg pointer list */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
#ifdef __BIG_ENDIAN__
|
||||
avalue[i] = ptr + 3;
|
||||
#else
|
||||
avalue[i] = ptr;
|
||||
#endif
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
#ifdef __BIG_ENDIAN__
|
||||
avalue[i] = ptr + 2;
|
||||
#else
|
||||
avalue[i] = ptr;
|
||||
#endif
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if __BIG_ENDIAN__
|
||||
/*
|
||||
* Work around strange ABI behaviour.
|
||||
* (see info in ffi_prep_args)
|
||||
*/
|
||||
if (arg_types[i]->size < WORD_SIZE)
|
||||
{
|
||||
memcpy (ptr, ptr + (WORD_SIZE - arg_types[i]->size), arg_types[i]->size);
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void*)ptr;
|
||||
break;
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
avalue[i] = ptr;
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
default:
|
||||
/* default 4-byte argument */
|
||||
avalue[i] = ptr;
|
||||
break;
|
||||
}
|
||||
ptr += WORD_ALIGN(arg_types[i]->size);
|
||||
}
|
||||
|
||||
/* set the return type info passed back to the wrapper */
|
||||
*rsize = cif->rtype->size;
|
||||
*rtype = cif->rtype->type;
|
||||
if (struct_rvalue != NULL) {
|
||||
closure->fun(cif, struct_rvalue, avalue, closure->user_data);
|
||||
/* copy struct return pointer value into function return value */
|
||||
*((void**)rvalue) = struct_rvalue;
|
||||
} else {
|
||||
closure->fun(cif, rvalue, avalue, closure->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
ffi_status ffi_prep_closure_loc(
|
||||
ffi_closure* closure, ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void* user_data, void* codeloc)
|
||||
{
|
||||
unsigned long* tramp = (unsigned long*)&(closure->tramp[0]);
|
||||
unsigned long cls = (unsigned long)codeloc;
|
||||
unsigned long fn = 0;
|
||||
unsigned long fn_closure_call_sysv = (unsigned long)ffi_closure_call_SYSV;
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
fn = (unsigned long)ffi_closure_SYSV;
|
||||
|
||||
/* load r11 (temp) with fn */
|
||||
/* imm fn(upper) */
|
||||
tramp[0] = 0xb0000000 | ((fn >> 16) & 0xffff);
|
||||
/* addik r11, r0, fn(lower) */
|
||||
tramp[1] = 0x31600000 | (fn & 0xffff);
|
||||
|
||||
/* load r12 (temp) with cls */
|
||||
/* imm cls(upper) */
|
||||
tramp[2] = 0xb0000000 | ((cls >> 16) & 0xffff);
|
||||
/* addik r12, r0, cls(lower) */
|
||||
tramp[3] = 0x31800000 | (cls & 0xffff);
|
||||
|
||||
/* load r3 (temp) with ffi_closure_call_SYSV */
|
||||
/* imm fn_closure_call_sysv(upper) */
|
||||
tramp[4] = 0xb0000000 | ((fn_closure_call_sysv >> 16) & 0xffff);
|
||||
/* addik r3, r0, fn_closure_call_sysv(lower) */
|
||||
tramp[5] = 0x30600000 | (fn_closure_call_sysv & 0xffff);
|
||||
/* branch/jump to address stored in r11 (fn) */
|
||||
tramp[6] = 0x98085800; /* bra r11 */
|
||||
|
||||
break;
|
||||
default:
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
return FFI_OK;
|
||||
}
|
53
libffi/src/microblaze/ffitarget.h
Normal file
53
libffi/src/microblaze/ffitarget.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffitarget.h - Copyright (c) 2012, 2013 Xilinx, Inc
|
||||
|
||||
Target configuration macros for MicroBlaze.
|
||||
|
||||
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
|
||||
|
||||
/* Definitions for closures */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#define FFI_TRAMPOLINE_SIZE (4*8)
|
||||
|
||||
#endif
|
302
libffi/src/microblaze/sysv.S
Normal file
302
libffi/src/microblaze/sysv.S
Normal file
|
@ -0,0 +1,302 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2012, 2013 Xilinx, Inc
|
||||
|
||||
MicroBlaze 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>
|
||||
|
||||
/*
|
||||
* arg[0] (r5) = ffi_prep_args,
|
||||
* arg[1] (r6) = &ecif,
|
||||
* arg[2] (r7) = cif->bytes,
|
||||
* arg[3] (r8) = cif->flags,
|
||||
* arg[4] (r9) = ecif.rvalue,
|
||||
* arg[5] (r10) = fn
|
||||
* arg[6] (sp[0]) = cif->rtype->type
|
||||
* arg[7] (sp[4]) = cif->rtype->size
|
||||
*/
|
||||
.text
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV, @function
|
||||
ffi_call_SYSV:
|
||||
/* push callee saves */
|
||||
addik r1, r1, -20
|
||||
swi r19, r1, 0 /* Frame Pointer */
|
||||
swi r20, r1, 4 /* PIC register */
|
||||
swi r21, r1, 8 /* PIC register */
|
||||
swi r22, r1, 12 /* save for locals */
|
||||
swi r23, r1, 16 /* save for locals */
|
||||
|
||||
/* save the r5-r10 registers in the stack */
|
||||
addik r1, r1, -24 /* increment sp to store 6x 32-bit words */
|
||||
swi r5, r1, 0
|
||||
swi r6, r1, 4
|
||||
swi r7, r1, 8
|
||||
swi r8, r1, 12
|
||||
swi r9, r1, 16
|
||||
swi r10, r1, 20
|
||||
|
||||
/* save function pointer */
|
||||
addik r3, r5, 0 /* copy ffi_prep_args into r3 */
|
||||
addik r22, r1, 0 /* save sp for unallocated args into r22 (callee-saved) */
|
||||
addik r23, r10, 0 /* save function address into r23 (callee-saved) */
|
||||
|
||||
/* prepare stack with allocation for n (bytes = r7) args */
|
||||
rsub r1, r7, r1 /* subtract bytes from sp */
|
||||
|
||||
/* prep args for ffi_prep_args call */
|
||||
addik r5, r1, 0 /* store stack pointer into arg[0] */
|
||||
/* r6 still holds ecif for arg[1] */
|
||||
|
||||
/* Call ffi_prep_args(stack, &ecif). */
|
||||
addik r1, r1, -4
|
||||
swi r15, r1, 0 /* store the link register in the frame */
|
||||
brald r15, r3
|
||||
nop /* branch has delay slot */
|
||||
lwi r15, r1, 0
|
||||
addik r1, r1, 4 /* restore the link register from the frame */
|
||||
/* returns calling stack pointer location */
|
||||
|
||||
/* prepare args for fn call, prep_args populates them onto the stack */
|
||||
lwi r5, r1, 0 /* arg[0] */
|
||||
lwi r6, r1, 4 /* arg[1] */
|
||||
lwi r7, r1, 8 /* arg[2] */
|
||||
lwi r8, r1, 12 /* arg[3] */
|
||||
lwi r9, r1, 16 /* arg[4] */
|
||||
lwi r10, r1, 20 /* arg[5] */
|
||||
|
||||
/* call (fn) (...). */
|
||||
addik r1, r1, -4
|
||||
swi r15, r1, 0 /* store the link register in the frame */
|
||||
brald r15, r23
|
||||
nop /* branch has delay slot */
|
||||
lwi r15, r1, 0
|
||||
addik r1, r1, 4 /* restore the link register from the frame */
|
||||
|
||||
/* Remove the space we pushed for the args. */
|
||||
addik r1, r22, 0 /* restore old SP */
|
||||
|
||||
/* restore this functions parameters */
|
||||
lwi r5, r1, 0 /* arg[0] */
|
||||
lwi r6, r1, 4 /* arg[1] */
|
||||
lwi r7, r1, 8 /* arg[2] */
|
||||
lwi r8, r1, 12 /* arg[3] */
|
||||
lwi r9, r1, 16 /* arg[4] */
|
||||
lwi r10, r1, 20 /* arg[5] */
|
||||
addik r1, r1, 24 /* decrement sp to de-allocate 6x 32-bit words */
|
||||
|
||||
/* If the return value pointer is NULL, assume no return value. */
|
||||
beqi r9, ffi_call_SYSV_end
|
||||
|
||||
lwi r22, r1, 48 /* get return type (20 for locals + 28 for arg[6]) */
|
||||
lwi r23, r1, 52 /* get return size (20 for locals + 32 for arg[7]) */
|
||||
|
||||
/* Check if return type is actually a struct, do nothing */
|
||||
rsubi r11, r22, FFI_TYPE_STRUCT
|
||||
beqi r11, ffi_call_SYSV_end
|
||||
|
||||
/* Return 8bit */
|
||||
rsubi r11, r23, 1
|
||||
beqi r11, ffi_call_SYSV_store8
|
||||
|
||||
/* Return 16bit */
|
||||
rsubi r11, r23, 2
|
||||
beqi r11, ffi_call_SYSV_store16
|
||||
|
||||
/* Return 32bit */
|
||||
rsubi r11, r23, 4
|
||||
beqi r11, ffi_call_SYSV_store32
|
||||
|
||||
/* Return 64bit */
|
||||
rsubi r11, r23, 8
|
||||
beqi r11, ffi_call_SYSV_store64
|
||||
|
||||
/* Didn't match anything */
|
||||
bri ffi_call_SYSV_end
|
||||
|
||||
ffi_call_SYSV_store64:
|
||||
swi r3, r9, 0 /* store word r3 into return value */
|
||||
swi r4, r9, 4 /* store word r4 into return value */
|
||||
bri ffi_call_SYSV_end
|
||||
|
||||
ffi_call_SYSV_store32:
|
||||
swi r3, r9, 0 /* store word r3 into return value */
|
||||
bri ffi_call_SYSV_end
|
||||
|
||||
ffi_call_SYSV_store16:
|
||||
#ifdef __BIG_ENDIAN__
|
||||
shi r3, r9, 2 /* store half-word r3 into return value */
|
||||
#else
|
||||
shi r3, r9, 0 /* store half-word r3 into return value */
|
||||
#endif
|
||||
bri ffi_call_SYSV_end
|
||||
|
||||
ffi_call_SYSV_store8:
|
||||
#ifdef __BIG_ENDIAN__
|
||||
sbi r3, r9, 3 /* store byte r3 into return value */
|
||||
#else
|
||||
sbi r3, r9, 0 /* store byte r3 into return value */
|
||||
#endif
|
||||
bri ffi_call_SYSV_end
|
||||
|
||||
ffi_call_SYSV_end:
|
||||
/* callee restores */
|
||||
lwi r19, r1, 0 /* frame pointer */
|
||||
lwi r20, r1, 4 /* PIC register */
|
||||
lwi r21, r1, 8 /* PIC register */
|
||||
lwi r22, r1, 12
|
||||
lwi r23, r1, 16
|
||||
addik r1, r1, 20
|
||||
|
||||
/* return from sub-routine (with delay slot) */
|
||||
rtsd r15, 8
|
||||
nop
|
||||
|
||||
.size ffi_call_SYSV, . - ffi_call_SYSV
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* args passed into this function, are passed down to the callee.
|
||||
* this function is the target of the closure trampoline, as such r12 is
|
||||
* a pointer to the closure object.
|
||||
*/
|
||||
.text
|
||||
.globl ffi_closure_SYSV
|
||||
.type ffi_closure_SYSV, @function
|
||||
ffi_closure_SYSV:
|
||||
/* push callee saves */
|
||||
addik r11, r1, 28 /* save stack args start location (excluding regs/link) */
|
||||
addik r1, r1, -12
|
||||
swi r19, r1, 0 /* Frame Pointer */
|
||||
swi r20, r1, 4 /* PIC register */
|
||||
swi r21, r1, 8 /* PIC register */
|
||||
|
||||
/* store register args on stack */
|
||||
addik r1, r1, -24
|
||||
swi r5, r1, 0
|
||||
swi r6, r1, 4
|
||||
swi r7, r1, 8
|
||||
swi r8, r1, 12
|
||||
swi r9, r1, 16
|
||||
swi r10, r1, 20
|
||||
|
||||
/* setup args */
|
||||
addik r5, r1, 0 /* register_args */
|
||||
addik r6, r11, 0 /* stack_args */
|
||||
addik r7, r12, 0 /* closure object */
|
||||
addik r1, r1, -8 /* allocate return value */
|
||||
addik r8, r1, 0 /* void* rvalue */
|
||||
addik r1, r1, -8 /* allocate for return type/size values */
|
||||
addik r9, r1, 0 /* void* rtype */
|
||||
addik r10, r1, 4 /* void* rsize */
|
||||
|
||||
/* call the wrap_call function */
|
||||
addik r1, r1, -28 /* allocate args + link reg */
|
||||
swi r15, r1, 0 /* store the link register in the frame */
|
||||
brald r15, r3
|
||||
nop /* branch has delay slot */
|
||||
lwi r15, r1, 0
|
||||
addik r1, r1, 28 /* restore the link register from the frame */
|
||||
|
||||
ffi_closure_SYSV_prepare_return:
|
||||
lwi r9, r1, 0 /* rtype */
|
||||
lwi r10, r1, 4 /* rsize */
|
||||
addik r1, r1, 8 /* de-allocate return info values */
|
||||
|
||||
/* Check if return type is actually a struct, store 4 bytes */
|
||||
rsubi r11, r9, FFI_TYPE_STRUCT
|
||||
beqi r11, ffi_closure_SYSV_store32
|
||||
|
||||
/* Return 8bit */
|
||||
rsubi r11, r10, 1
|
||||
beqi r11, ffi_closure_SYSV_store8
|
||||
|
||||
/* Return 16bit */
|
||||
rsubi r11, r10, 2
|
||||
beqi r11, ffi_closure_SYSV_store16
|
||||
|
||||
/* Return 32bit */
|
||||
rsubi r11, r10, 4
|
||||
beqi r11, ffi_closure_SYSV_store32
|
||||
|
||||
/* Return 64bit */
|
||||
rsubi r11, r10, 8
|
||||
beqi r11, ffi_closure_SYSV_store64
|
||||
|
||||
/* Didn't match anything */
|
||||
bri ffi_closure_SYSV_end
|
||||
|
||||
ffi_closure_SYSV_store64:
|
||||
lwi r3, r1, 0 /* store word r3 into return value */
|
||||
lwi r4, r1, 4 /* store word r4 into return value */
|
||||
/* 64 bits == 2 words, no sign extend occurs */
|
||||
bri ffi_closure_SYSV_end
|
||||
|
||||
ffi_closure_SYSV_store32:
|
||||
lwi r3, r1, 0 /* store word r3 into return value */
|
||||
/* 32 bits == 1 word, no sign extend occurs */
|
||||
bri ffi_closure_SYSV_end
|
||||
|
||||
ffi_closure_SYSV_store16:
|
||||
#ifdef __BIG_ENDIAN__
|
||||
lhui r3, r1, 2 /* store half-word r3 into return value */
|
||||
#else
|
||||
lhui r3, r1, 0 /* store half-word r3 into return value */
|
||||
#endif
|
||||
rsubi r11, r9, FFI_TYPE_SINT16
|
||||
bnei r11, ffi_closure_SYSV_end
|
||||
sext16 r3, r3 /* fix sign extend of sint8 */
|
||||
bri ffi_closure_SYSV_end
|
||||
|
||||
ffi_closure_SYSV_store8:
|
||||
#ifdef __BIG_ENDIAN__
|
||||
lbui r3, r1, 3 /* store byte r3 into return value */
|
||||
#else
|
||||
lbui r3, r1, 0 /* store byte r3 into return value */
|
||||
#endif
|
||||
rsubi r11, r9, FFI_TYPE_SINT8
|
||||
bnei r11, ffi_closure_SYSV_end
|
||||
sext8 r3, r3 /* fix sign extend of sint8 */
|
||||
bri ffi_closure_SYSV_end
|
||||
|
||||
ffi_closure_SYSV_end:
|
||||
addik r1, r1, 8 /* de-allocate return value */
|
||||
|
||||
/* de-allocate stored args */
|
||||
addik r1, r1, 24
|
||||
|
||||
/* callee restores */
|
||||
lwi r19, r1, 0 /* frame pointer */
|
||||
lwi r20, r1, 4 /* PIC register */
|
||||
lwi r21, r1, 8 /* PIC register */
|
||||
addik r1, r1, 12
|
||||
|
||||
/* return from sub-routine (with delay slot) */
|
||||
rtsd r15, 8
|
||||
nop
|
||||
|
||||
.size ffi_closure_SYSV, . - ffi_closure_SYSV
|
|
@ -170,7 +170,14 @@ static void ffi_prep_args(char *stack,
|
|||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
#ifdef FFI_MIPS_N32
|
||||
/* The N32 ABI requires that 32-bit integers
|
||||
be sign-extended to 64-bits, regardless of
|
||||
whether they are signed or unsigned. */
|
||||
*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
|
||||
#else
|
||||
*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* This can only happen with 64bit slots. */
|
||||
|
|
|
@ -108,10 +108,8 @@ loadregs:
|
|||
REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6.
|
||||
|
||||
and t4, t6, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg1_floatp
|
||||
REG_L a0, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
arg1_floatp:
|
||||
beqz t4, arg1_next
|
||||
bne t4, FFI_TYPE_FLOAT, arg1_doublep
|
||||
l.s $f12, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
|
@ -121,10 +119,8 @@ arg1_next:
|
|||
|
||||
SRL t4, t6, 1*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg2_floatp
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
arg2_floatp:
|
||||
beqz t4, arg2_next
|
||||
bne t4, FFI_TYPE_FLOAT, arg2_doublep
|
||||
l.s $f13, 1*FFI_SIZEOF_ARG(t9)
|
||||
b arg2_next
|
||||
|
@ -134,10 +130,8 @@ arg2_next:
|
|||
|
||||
SRL t4, t6, 2*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg3_floatp
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
arg3_floatp:
|
||||
beqz t4, arg3_next
|
||||
bne t4, FFI_TYPE_FLOAT, arg3_doublep
|
||||
l.s $f14, 2*FFI_SIZEOF_ARG(t9)
|
||||
b arg3_next
|
||||
|
@ -147,10 +141,8 @@ arg3_next:
|
|||
|
||||
SRL t4, t6, 3*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg4_floatp
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
arg4_floatp:
|
||||
beqz t4, arg4_next
|
||||
bne t4, FFI_TYPE_FLOAT, arg4_doublep
|
||||
l.s $f15, 3*FFI_SIZEOF_ARG(t9)
|
||||
b arg4_next
|
||||
|
@ -160,10 +152,8 @@ arg4_next:
|
|||
|
||||
SRL t4, t6, 4*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg5_floatp
|
||||
REG_L a4, 4*FFI_SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
arg5_floatp:
|
||||
beqz t4, arg5_next
|
||||
bne t4, FFI_TYPE_FLOAT, arg5_doublep
|
||||
l.s $f16, 4*FFI_SIZEOF_ARG(t9)
|
||||
b arg5_next
|
||||
|
@ -173,10 +163,8 @@ arg5_next:
|
|||
|
||||
SRL t4, t6, 5*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg6_floatp
|
||||
REG_L a5, 5*FFI_SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
arg6_floatp:
|
||||
beqz t4, arg6_next
|
||||
bne t4, FFI_TYPE_FLOAT, arg6_doublep
|
||||
l.s $f17, 5*FFI_SIZEOF_ARG(t9)
|
||||
b arg6_next
|
||||
|
@ -186,10 +174,8 @@ arg6_next:
|
|||
|
||||
SRL t4, t6, 6*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg7_floatp
|
||||
REG_L a6, 6*FFI_SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
arg7_floatp:
|
||||
beqz t4, arg7_next
|
||||
bne t4, FFI_TYPE_FLOAT, arg7_doublep
|
||||
l.s $f18, 6*FFI_SIZEOF_ARG(t9)
|
||||
b arg7_next
|
||||
|
@ -199,10 +185,8 @@ arg7_next:
|
|||
|
||||
SRL t4, t6, 7*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg8_floatp
|
||||
REG_L a7, 7*FFI_SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
arg8_floatp:
|
||||
beqz t4, arg8_next
|
||||
bne t4, FFI_TYPE_FLOAT, arg8_doublep
|
||||
l.s $f19, 7*FFI_SIZEOF_ARG(t9)
|
||||
b arg8_next
|
||||
|
|
101
libffi/src/moxie/eabi.S
Normal file
101
libffi/src/moxie/eabi.S
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
eabi.S - Copyright (c) 2012, 2013 Anthony Green
|
||||
|
||||
Moxie Assembly glue.
|
||||
|
||||
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 AUTHOR 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>
|
||||
|
||||
.globl ffi_prep_args_EABI
|
||||
|
||||
.text
|
||||
.p2align 4
|
||||
.globl ffi_call_EABI
|
||||
.type ffi_call_EABI, @function
|
||||
|
||||
# $r0 : ffi_prep_args
|
||||
# $r1 : &ecif
|
||||
# $r2 : cif->bytes
|
||||
# $r3 : fig->flags
|
||||
# $r4 : ecif.rvalue
|
||||
# $r5 : fn
|
||||
|
||||
ffi_call_EABI:
|
||||
push $sp, $r6
|
||||
push $sp, $r7
|
||||
push $sp, $r8
|
||||
dec $sp, 24
|
||||
|
||||
/* Store incoming args on stack. */
|
||||
sto.l 0($sp), $r0 /* ffi_prep_args */
|
||||
sto.l 4($sp), $r1 /* ecif */
|
||||
sto.l 8($sp), $r2 /* bytes */
|
||||
sto.l 12($sp), $r3 /* flags */
|
||||
sto.l 16($sp), $r4 /* &rvalue */
|
||||
sto.l 20($sp), $r5 /* fn */
|
||||
|
||||
/* Call ffi_prep_args. */
|
||||
mov $r6, $r4 /* Save result buffer */
|
||||
mov $r7, $r5 /* Save the target fn */
|
||||
mov $r8, $r3 /* Save the flags */
|
||||
sub.l $sp, $r2 /* Allocate stack space */
|
||||
mov $r0, $sp /* We can stomp over $r0 */
|
||||
/* $r1 is already set up */
|
||||
jsra ffi_prep_args
|
||||
|
||||
/* Load register arguments. */
|
||||
ldo.l $r0, 0($sp)
|
||||
ldo.l $r1, 4($sp)
|
||||
ldo.l $r2, 8($sp)
|
||||
ldo.l $r3, 12($sp)
|
||||
ldo.l $r4, 16($sp)
|
||||
ldo.l $r5, 20($sp)
|
||||
|
||||
/* Call the target function. */
|
||||
jsr $r7
|
||||
|
||||
ldi.l $r7, 0xffffffff
|
||||
cmp $r8, $r7
|
||||
beq retstruct
|
||||
|
||||
ldi.l $r7, 4
|
||||
cmp $r8, $r7
|
||||
bgt ret2reg
|
||||
|
||||
st.l ($r6), $r0
|
||||
jmpa retdone
|
||||
|
||||
ret2reg:
|
||||
st.l ($r6), $r0
|
||||
sto.l 4($r6), $r1
|
||||
|
||||
retstruct:
|
||||
retdone:
|
||||
/* Return. */
|
||||
ldo.l $r6, -4($fp)
|
||||
ldo.l $r7, -8($fp)
|
||||
ldo.l $r8, -12($fp)
|
||||
ret
|
||||
.size ffi_call_EABI, .-ffi_call_EABI
|
||||
|
272
libffi/src/moxie/ffi.c
Normal file
272
libffi/src/moxie/ffi.c
Normal file
|
@ -0,0 +1,272 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (C) 2012, 2013 Anthony Green
|
||||
|
||||
Moxie 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>
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
void *ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
register int count = 0;
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
(i != 0);
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
z = sizeof(void*);
|
||||
*(void **) argp = *p_argv;
|
||||
}
|
||||
else if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (z == sizeof(int))
|
||||
{
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
count += z;
|
||||
}
|
||||
|
||||
return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
cif->flags = -1;
|
||||
else
|
||||
cif->flags = cif->rtype->size;
|
||||
|
||||
cif->bytes = ALIGN (cif->bytes, 8);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned,
|
||||
unsigned *,
|
||||
void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_EABI:
|
||||
ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
|
||||
unsigned arg4, unsigned arg5, unsigned arg6)
|
||||
{
|
||||
/* This function is called by a trampoline. The trampoline stows a
|
||||
pointer to the ffi_closure object in $r7. We must save this
|
||||
pointer in a place that will persist while we do our work. */
|
||||
register ffi_closure *creg __asm__ ("$r12");
|
||||
ffi_closure *closure = creg;
|
||||
|
||||
/* Arguments that don't fit in registers are found on the stack
|
||||
at a fixed offset above the current frame pointer. */
|
||||
register char *frame_pointer __asm__ ("$fp");
|
||||
|
||||
/* Pointer to a struct return value. */
|
||||
void *struct_rvalue = (void *) arg1;
|
||||
|
||||
/* 6 words reserved for register args + 3 words from jsr */
|
||||
char *stack_args = frame_pointer + 9*4;
|
||||
|
||||
/* Lay the register arguments down in a continuous chunk of memory. */
|
||||
unsigned register_args[6] =
|
||||
{ arg1, arg2, arg3, arg4, arg5, arg6 };
|
||||
char *register_args_ptr = (char *) register_args;
|
||||
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
void **avalue = alloca (cif->nargs * sizeof(void *));
|
||||
char *ptr = (char *) register_args;
|
||||
int i;
|
||||
|
||||
/* preserve struct type return pointer passing */
|
||||
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
|
||||
ptr += 4;
|
||||
register_args_ptr = (char *)®ister_args[1];
|
||||
}
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = ptr + 3;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = ptr + 2;
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_POINTER:
|
||||
avalue[i] = ptr;
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = *(void**)ptr;
|
||||
break;
|
||||
default:
|
||||
/* This is an 8-byte value. */
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
break;
|
||||
}
|
||||
ptr += 4;
|
||||
|
||||
/* If we've handled more arguments than fit in registers,
|
||||
start looking at the those passed on the stack. */
|
||||
if (ptr == ®ister_args[6])
|
||||
ptr = stack_args;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
(closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate space for the return value and call the function. */
|
||||
long long rvalue;
|
||||
(closure->fun) (cif, &rvalue, avalue, closure->user_data);
|
||||
asm ("mov $r12, %0\n ld.l $r0, ($r12)\n ldo.l $r1, 4($r12)" : : "r" (&rvalue));
|
||||
}
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned short *tramp = (unsigned short *) &closure->tramp[0];
|
||||
unsigned long fn = (long) ffi_closure_eabi;
|
||||
unsigned long cls = (long) codeloc;
|
||||
|
||||
if (cif->abi != FFI_EABI)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
fn = (unsigned long) ffi_closure_eabi;
|
||||
|
||||
tramp[0] = 0x01e0; /* ldi.l $r7, .... */
|
||||
tramp[1] = cls >> 16;
|
||||
tramp[2] = cls & 0xffff;
|
||||
tramp[3] = 0x1a00; /* jmpa .... */
|
||||
tramp[4] = fn >> 16;
|
||||
tramp[5] = fn & 0xffff;
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
52
libffi/src/moxie/ffitarget.h
Normal file
52
libffi/src/moxie/ffitarget.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2012, 2013 Anthony Green
|
||||
Target configuration macros for Moxie
|
||||
|
||||
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
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_EABI,
|
||||
FFI_DEFAULT_ABI = FFI_EABI,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
/* Trampolines are 12-bytes long. See ffi_prep_closure_loc. */
|
||||
#define FFI_TRAMPOLINE_SIZE (12)
|
||||
|
||||
#endif
|
304
libffi/src/nios2/ffi.c
Normal file
304
libffi/src/nios2/ffi.c
Normal file
|
@ -0,0 +1,304 @@
|
|||
/* libffi support for Altera Nios II.
|
||||
|
||||
Copyright (c) 2013 Mentor Graphics.
|
||||
|
||||
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>
|
||||
|
||||
/* The Nios II Processor Reference Handbook defines the procedure call
|
||||
ABI as follows.
|
||||
|
||||
Arguments are passed as if a structure containing the types of
|
||||
the arguments were constructed. The first 16 bytes are passed in r4
|
||||
through r7, the remainder on the stack. The first 16 bytes of a function
|
||||
taking variable arguments are passed in r4-r7 in the same way.
|
||||
|
||||
Return values of types up to 8 bytes are returned in r2 and r3. For
|
||||
return values greater than 8 bytes, the caller must allocate memory for
|
||||
the result and pass the address as if it were argument 0.
|
||||
|
||||
While this isn't specified explicitly in the ABI documentation, GCC
|
||||
promotes integral arguments smaller than int size to 32 bits.
|
||||
|
||||
Also of note, the ABI specifies that all structure objects are
|
||||
aligned to 32 bits even if all their fields have a smaller natural
|
||||
alignment. See FFI_AGGREGATE_ALIGNMENT. */
|
||||
|
||||
|
||||
/* Declare the assembly language hooks. */
|
||||
|
||||
extern UINT64 ffi_call_sysv (void (*) (char *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned,
|
||||
void (*fn) (void));
|
||||
extern void ffi_closure_sysv (void);
|
||||
|
||||
/* Perform machine-dependent cif processing. */
|
||||
|
||||
ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
|
||||
{
|
||||
/* We always want at least 16 bytes in the parameter block since it
|
||||
simplifies the low-level call function. Also round the parameter
|
||||
block size up to a multiple of 4 bytes to preserve
|
||||
32-bit alignment of the stack pointer. */
|
||||
if (cif->bytes < 16)
|
||||
cif->bytes = 16;
|
||||
else
|
||||
cif->bytes = (cif->bytes + 3) & ~3;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine to transfer arguments
|
||||
to the stack using the pointers in the ecif array.
|
||||
Note that the stack buffer is big enough to fit all the arguments,
|
||||
but the first 16 bytes will be copied to registers for the actual
|
||||
call. */
|
||||
|
||||
void ffi_prep_args (char *stack, extended_cif *ecif)
|
||||
{
|
||||
char *argp = stack;
|
||||
unsigned int i;
|
||||
|
||||
/* The implicit return value pointer is passed as if it were a hidden
|
||||
first argument. */
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& ecif->cif->rtype->size > 8)
|
||||
{
|
||||
(*(void **) argp) = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < ecif->cif->nargs; i++)
|
||||
{
|
||||
void *avalue = ecif->avalue[i];
|
||||
ffi_type *atype = ecif->cif->arg_types[i];
|
||||
size_t size = atype->size;
|
||||
size_t alignment = atype->alignment;
|
||||
|
||||
/* Align argp as appropriate for the argument type. */
|
||||
if ((alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, alignment);
|
||||
|
||||
/* Copy the argument, promoting integral types smaller than a
|
||||
word to word size. */
|
||||
if (size < sizeof (int))
|
||||
{
|
||||
size = sizeof (int);
|
||||
switch (atype->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) avalue;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT8 *) avalue;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) avalue;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT16 *) avalue;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp, avalue, atype->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else if (size == sizeof (int))
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT32 *) avalue;
|
||||
else
|
||||
memcpy (argp, avalue, size);
|
||||
argp += size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Call FN using the prepared CIF. RVALUE points to space allocated by
|
||||
the caller for the return value, and AVALUE is an array of argument
|
||||
pointers. */
|
||||
|
||||
void ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
|
||||
{
|
||||
|
||||
extended_cif ecif;
|
||||
UINT64 result;
|
||||
|
||||
/* If bigret is true, this is the case where a return value of larger
|
||||
than 8 bytes is handled by being passed by reference as an implicit
|
||||
argument. */
|
||||
int bigret = (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& cif->rtype->size > 8);
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* Allocate space for return value if this is the pass-by-reference case
|
||||
and the caller did not provide a buffer. */
|
||||
if (rvalue == NULL && bigret)
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
result = ffi_call_sysv (ffi_prep_args, &ecif, cif->bytes, fn);
|
||||
|
||||
/* Now result contains the 64 bit contents returned from fn in
|
||||
r2 and r3. Copy the value of the appropriate size to the user-provided
|
||||
rvalue buffer. */
|
||||
if (rvalue && !bigret)
|
||||
switch (cif->rtype->size)
|
||||
{
|
||||
case 1:
|
||||
*(UINT8 *)rvalue = (UINT8) result;
|
||||
break;
|
||||
case 2:
|
||||
*(UINT16 *)rvalue = (UINT16) result;
|
||||
break;
|
||||
case 4:
|
||||
*(UINT32 *)rvalue = (UINT32) result;
|
||||
break;
|
||||
case 8:
|
||||
*(UINT64 *)rvalue = (UINT64) result;
|
||||
break;
|
||||
default:
|
||||
memcpy (rvalue, (void *)&result, cif->rtype->size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is invoked from the closure trampoline to invoke
|
||||
CLOSURE with argument block ARGS. Parse ARGS according to
|
||||
CLOSURE->cfi and invoke CLOSURE->fun. */
|
||||
|
||||
static UINT64
|
||||
ffi_closure_helper (unsigned char *args,
|
||||
ffi_closure *closure)
|
||||
{
|
||||
ffi_cif *cif = closure->cif;
|
||||
unsigned char *argp = args;
|
||||
void **parsed_args = alloca (cif->nargs * sizeof (void *));
|
||||
UINT64 result;
|
||||
void *retptr;
|
||||
unsigned int i;
|
||||
|
||||
/* First figure out what to do about the return type. If this is the
|
||||
big-structure-return case, the first arg is the hidden return buffer
|
||||
allocated by the caller. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& cif->rtype->size > 8)
|
||||
{
|
||||
retptr = *((void **) argp);
|
||||
argp += 4;
|
||||
}
|
||||
else
|
||||
retptr = (void *) &result;
|
||||
|
||||
/* Fill in the array of argument pointers. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
size_t size = cif->arg_types[i]->size;
|
||||
size_t alignment = cif->arg_types[i]->alignment;
|
||||
|
||||
/* Align argp as appropriate for the argument type. */
|
||||
if ((alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, alignment);
|
||||
|
||||
/* Arguments smaller than an int are promoted to int. */
|
||||
if (size < sizeof (int))
|
||||
size = sizeof (int);
|
||||
|
||||
/* Store the pointer. */
|
||||
parsed_args[i] = argp;
|
||||
argp += size;
|
||||
}
|
||||
|
||||
/* Call the user-supplied function. */
|
||||
(closure->fun) (cif, retptr, parsed_args, closure->user_data);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize CLOSURE with a trampoline to call FUN with
|
||||
CIF and USER_DATA. */
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun) (ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
int i;
|
||||
|
||||
if (cif->abi != FFI_SYSV)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
/* The trampoline looks like:
|
||||
movhi r8, %hi(ffi_closure_sysv)
|
||||
ori r8, r8, %lo(ffi_closure_sysv)
|
||||
movhi r9, %hi(ffi_closure_helper)
|
||||
ori r0, r9, %lo(ffi_closure_helper)
|
||||
movhi r10, %hi(closure)
|
||||
ori r10, r10, %lo(closure)
|
||||
jmp r8
|
||||
and then ffi_closure_sysv retrieves the closure pointer out of r10
|
||||
in addition to the arguments passed in the normal way for the call,
|
||||
and invokes ffi_closure_helper. We encode the pointer to
|
||||
ffi_closure_helper in the trampoline because making a PIC call
|
||||
to it in ffi_closure_sysv would be messy (it would have to indirect
|
||||
through the GOT). */
|
||||
|
||||
#define HI(x) ((((unsigned int) (x)) >> 16) & 0xffff)
|
||||
#define LO(x) (((unsigned int) (x)) & 0xffff)
|
||||
tramp[0] = (0 << 27) | (8 << 22) | (HI (ffi_closure_sysv) << 6) | 0x34;
|
||||
tramp[1] = (8 << 27) | (8 << 22) | (LO (ffi_closure_sysv) << 6) | 0x14;
|
||||
tramp[2] = (0 << 27) | (9 << 22) | (HI (ffi_closure_helper) << 6) | 0x34;
|
||||
tramp[3] = (9 << 27) | (9 << 22) | (LO (ffi_closure_helper) << 6) | 0x14;
|
||||
tramp[4] = (0 << 27) | (10 << 22) | (HI (closure) << 6) | 0x34;
|
||||
tramp[5] = (10 << 27) | (10 << 22) | (LO (closure) << 6) | 0x14;
|
||||
tramp[6] = (8 << 27) | (0x0d << 11) | 0x3a;
|
||||
#undef HI
|
||||
#undef LO
|
||||
|
||||
/* Flush the caches.
|
||||
See Example 9-4 in the Nios II Software Developer's Handbook. */
|
||||
for (i = 0; i < 7; i++)
|
||||
asm volatile ("flushd 0(%0); flushi %0" :: "r"(tramp + i) : "memory");
|
||||
asm volatile ("flushp" ::: "memory");
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
52
libffi/src/nios2/ffitarget.h
Normal file
52
libffi/src/nios2/ffitarget.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* libffi target includes for Altera Nios II.
|
||||
|
||||
Copyright (c) 2013 Mentor Graphics.
|
||||
|
||||
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
|
||||
|
||||
/* Structures have a 4-byte alignment even if all the fields have lesser
|
||||
alignment requirements. */
|
||||
#define FFI_AGGREGATE_ALIGNMENT 4
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 28 /* 7 instructions */
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
136
libffi/src/nios2/sysv.S
Normal file
136
libffi/src/nios2/sysv.S
Normal file
|
@ -0,0 +1,136 @@
|
|||
/* Low-level libffi support for Altera Nios II.
|
||||
|
||||
Copyright (c) 2013 Mentor Graphics.
|
||||
|
||||
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. */
|
||||
|
||||
/* This function is declared on the C side as
|
||||
|
||||
extern UINT64 ffi_call_sysv (void (*arghook) (char *, extended_cif *),
|
||||
extended_cif *ecif,
|
||||
unsigned nbytes,
|
||||
void (*fn) (void));
|
||||
|
||||
On input, the arguments appear as
|
||||
r4 = arghook
|
||||
r5 = ecif
|
||||
r6 = nbytes
|
||||
r7 = fn
|
||||
*/
|
||||
|
||||
.section .text
|
||||
.align 2
|
||||
.global ffi_call_sysv
|
||||
.type ffi_call_sysv, @function
|
||||
|
||||
ffi_call_sysv:
|
||||
.cfi_startproc
|
||||
|
||||
/* Create the stack frame, saving r16 so we can use it locally. */
|
||||
addi sp, sp, -12
|
||||
.cfi_def_cfa_offset 12
|
||||
stw ra, 8(sp)
|
||||
stw fp, 4(sp)
|
||||
stw r16, 0(sp)
|
||||
.cfi_offset 31, -4
|
||||
.cfi_offset 28, -8
|
||||
.cfi_offset 16, -12
|
||||
mov fp, sp
|
||||
.cfi_def_cfa_register 28
|
||||
mov r16, r7
|
||||
|
||||
/* Adjust the stack pointer to create the argument buffer
|
||||
nbytes long. */
|
||||
sub sp, sp, r6
|
||||
|
||||
/* Call the arghook function. */
|
||||
mov r2, r4 /* fn */
|
||||
mov r4, sp /* argbuffer */
|
||||
callr r2 /* r5 already contains ecif */
|
||||
|
||||
/* Pop off the first 16 bytes of the argument buffer on the stack,
|
||||
transferring the contents to the argument registers. */
|
||||
ldw r4, 0(sp)
|
||||
ldw r5, 4(sp)
|
||||
ldw r6, 8(sp)
|
||||
ldw r7, 12(sp)
|
||||
addi sp, sp, 16
|
||||
|
||||
/* Call the user function, which leaves its result in r2 and r3. */
|
||||
callr r16
|
||||
|
||||
/* Pop off the stack frame. */
|
||||
mov sp, fp
|
||||
ldw ra, 8(sp)
|
||||
ldw fp, 4(sp)
|
||||
ldw r16, 0(sp)
|
||||
addi sp, sp, 12
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size ffi_call_sysv, .-ffi_call_sysv
|
||||
|
||||
|
||||
/* Closure trampolines jump here after putting the C helper address
|
||||
in r9 and the closure pointer in r10. The user-supplied arguments
|
||||
to the closure are in the normal places, in r4-r7 and on the
|
||||
stack. Push the register arguments on the stack too and then call the
|
||||
C helper function to deal with them. */
|
||||
|
||||
.section .text
|
||||
.align 2
|
||||
.global ffi_closure_sysv
|
||||
.type ffi_closure_sysv, @function
|
||||
|
||||
ffi_closure_sysv:
|
||||
.cfi_startproc
|
||||
|
||||
/* Create the stack frame, pushing the register args on the stack
|
||||
just below the stack args. This is the same trick illustrated
|
||||
in Figure 7-3 in the Nios II Processor Reference Handbook, used
|
||||
for variable arguments and structures passed by value. */
|
||||
addi sp, sp, -20
|
||||
.cfi_def_cfa_offset 20
|
||||
stw ra, 0(sp)
|
||||
.cfi_offset 31, -20
|
||||
stw r4, 4(sp)
|
||||
.cfi_offset 4, -16
|
||||
stw r5, 8(sp)
|
||||
.cfi_offset 5, -12
|
||||
stw r6, 12(sp)
|
||||
.cfi_offset 6, -8
|
||||
stw r7, 16(sp)
|
||||
.cfi_offset 7, -4
|
||||
|
||||
/* Call the helper.
|
||||
r4 = pointer to arguments on stack
|
||||
r5 = closure pointer (loaded in r10 by the trampoline)
|
||||
r9 = address of helper function (loaded by trampoline) */
|
||||
addi r4, sp, 4
|
||||
mov r5, r10
|
||||
callr r9
|
||||
|
||||
/* Pop the stack and return. */
|
||||
ldw ra, 0(sp)
|
||||
addi sp, sp, 20
|
||||
.cfi_def_cfa_offset -20
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size ffi_closure_sysv, .-ffi_closure_sysv
|
||||
|
328
libffi/src/or1k/ffi.c
Normal file
328
libffi/src/or1k/ffi.c
Normal file
|
@ -0,0 +1,328 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
|
||||
|
||||
OpenRISC 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"
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
void* ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
{
|
||||
char *stacktemp = stack;
|
||||
int i, s;
|
||||
ffi_type **arg;
|
||||
int count = 0;
|
||||
int nfixedargs;
|
||||
|
||||
nfixedargs = ecif->cif->nfixedargs;
|
||||
arg = ecif->cif->arg_types;
|
||||
void **argv = ecif->avalue;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*(void **) stack = ecif->rvalue;
|
||||
stack += 4;
|
||||
count = 4;
|
||||
}
|
||||
for(i=0; i<ecif->cif->nargs; i++)
|
||||
{
|
||||
|
||||
/* variadic args are saved on stack */
|
||||
if ((nfixedargs == 0) && (count < 24))
|
||||
{
|
||||
count = 24;
|
||||
stack = stacktemp + 24;
|
||||
}
|
||||
nfixedargs--;
|
||||
|
||||
s = 4;
|
||||
switch((*arg)->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(void **)stack = *argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) stack = (signed int)*(SINT8 *)(* argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) stack = (unsigned int)*(UINT8 *)(* argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) stack = (signed int)*(SINT16 *)(* argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) stack = (unsigned int)*(UINT16 *)(* argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(int *)stack = *(int*)(*argv);
|
||||
break;
|
||||
|
||||
default: /* 8 byte types */
|
||||
if (count == 20) /* never split arguments */
|
||||
{
|
||||
stack += 4;
|
||||
count += 4;
|
||||
}
|
||||
s = (*arg)->size;
|
||||
memcpy(stack, *argv, s);
|
||||
break;
|
||||
}
|
||||
|
||||
stack += s;
|
||||
count += s;
|
||||
argv++;
|
||||
arg++;
|
||||
}
|
||||
return stacktemp + ((count>24)?24:0);
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV(unsigned,
|
||||
extended_cif *,
|
||||
void *(*)(int *, extended_cif *),
|
||||
unsigned *,
|
||||
void (*fn)(void),
|
||||
unsigned);
|
||||
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
ffi_type **arg;
|
||||
|
||||
/* Calculate size to allocate on stack */
|
||||
|
||||
for(i = 0, arg = cif->arg_types, size=0; i < cif->nargs; i++, arg++)
|
||||
{
|
||||
if ((*arg)->type == FFI_TYPE_STRUCT)
|
||||
size += 4;
|
||||
else
|
||||
if ((*arg)->size <= 4)
|
||||
size += 4;
|
||||
else
|
||||
size += 8;
|
||||
}
|
||||
|
||||
/* for variadic functions more space is needed on the stack */
|
||||
if (cif->nargs != cif->nfixedargs)
|
||||
size += 24;
|
||||
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
size += 4;
|
||||
|
||||
|
||||
extended_cif ecif;
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(size, &ecif, ffi_prep_args, rvalue, fn, cif->flags);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5,
|
||||
unsigned long r6, unsigned long r7, unsigned long r8)
|
||||
{
|
||||
register int *sp __asm__ ("r17");
|
||||
register int *r13 __asm__ ("r13");
|
||||
|
||||
ffi_closure* closure = (ffi_closure*) r13;
|
||||
char *stack_args = sp;
|
||||
|
||||
/* Lay the register arguments down in a continuous chunk of memory. */
|
||||
unsigned register_args[6] =
|
||||
{ r3, r4, r5, r6, r7, r8 };
|
||||
|
||||
/* Pointer to a struct return value. */
|
||||
void *struct_rvalue = (void *) r3;
|
||||
|
||||
ffi_cif *cif = closure->cif;
|
||||
ffi_type **arg_types = cif->arg_types;
|
||||
void **avalue = alloca (cif->nargs * sizeof(void *));
|
||||
char *ptr = (char *) register_args;
|
||||
int count = 0;
|
||||
int nfixedargs = cif->nfixedargs;
|
||||
int i;
|
||||
|
||||
/* preserve struct type return pointer passing */
|
||||
|
||||
if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ptr += 4;
|
||||
count = 4;
|
||||
}
|
||||
|
||||
/* Find the address of each argument. */
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
{
|
||||
|
||||
/* variadic args are saved on stack */
|
||||
if ((nfixedargs == 0) && (count < 24))
|
||||
{
|
||||
ptr = stack_args;
|
||||
count = 24;
|
||||
}
|
||||
nfixedargs--;
|
||||
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT8:
|
||||
avalue[i] = ptr + 3;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT16:
|
||||
avalue[i] = ptr + 2;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_POINTER:
|
||||
avalue[i] = ptr;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
avalue[i] = *(void**)ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* 8-byte values */
|
||||
|
||||
/* arguments are never splitted */
|
||||
if (ptr == ®ister_args[5])
|
||||
ptr = stack_args;
|
||||
avalue[i] = ptr;
|
||||
ptr += 4;
|
||||
count += 4;
|
||||
break;
|
||||
}
|
||||
ptr += 4;
|
||||
count += 4;
|
||||
|
||||
/* If we've handled more arguments than fit in registers,
|
||||
start looking at the those passed on the stack. */
|
||||
|
||||
if (count == 24)
|
||||
ptr = stack_args;
|
||||
}
|
||||
|
||||
if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
(closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
|
||||
} else
|
||||
{
|
||||
long long rvalue;
|
||||
(closure->fun) (cif, &rvalue, avalue, closure->user_data);
|
||||
if (cif->rtype)
|
||||
asm ("l.ori r12, %0, 0x0\n l.lwz r11, 0(r12)\n l.lwz r12, 4(r12)" : : "r" (&rvalue));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned short *tramp = (unsigned short *) closure->tramp;
|
||||
unsigned long fn = (unsigned long) ffi_closure_SYSV;
|
||||
unsigned long cls = (unsigned long) codeloc;
|
||||
|
||||
if (cif->abi != FFI_SYSV)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
/* write pointers to temporary registers */
|
||||
tramp[0] = (0x6 << 10) | (13 << 5); /* l.movhi r13, ... */
|
||||
tramp[1] = cls >> 16;
|
||||
tramp[2] = (0x2a << 10) | (13 << 5) | 13; /* l.ori r13, r13, ... */
|
||||
tramp[3] = cls & 0xFFFF;
|
||||
|
||||
tramp[4] = (0x6 << 10) | (15 << 5); /* l.movhi r15, ... */
|
||||
tramp[5] = fn >> 16;
|
||||
tramp[6] = (0x2a << 10) | (15 << 5) | 15; /* l.ori r15, r15 ... */
|
||||
tramp[7] = fn & 0xFFFF;
|
||||
|
||||
tramp[8] = (0x11 << 10); /* l.jr r15 */
|
||||
tramp[9] = 15 << 11;
|
||||
|
||||
tramp[10] = (0x2a << 10) | (17 << 5) | 1; /* l.ori r17, r1, ... */
|
||||
tramp[11] = 0x0;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
|
||||
{
|
||||
cif->flags = 0;
|
||||
|
||||
/* structures are returned as pointers */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
else
|
||||
if (cif->rtype->size > 4)
|
||||
cif->flags = FFI_TYPE_UINT64;
|
||||
|
||||
cif->nfixedargs = cif->nargs;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
|
||||
unsigned int nfixedargs, unsigned int ntotalargs)
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_cif_machdep (cif);
|
||||
cif->nfixedargs = nfixedargs;
|
||||
return status;
|
||||
}
|
58
libffi/src/or1k/ffitarget.h
Normal file
58
libffi/src/or1k/ffitarget.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffitarget.h - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
|
||||
|
||||
OpenRISC Target configuration macros
|
||||
|
||||
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
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#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
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
#define FFI_TRAMPOLINE_SIZE (24)
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_VARIADIC 1
|
||||
#define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs;
|
||||
|
||||
#endif
|
||||
|
107
libffi/src/or1k/sysv.S
Normal file
107
libffi/src/or1k/sysv.S
Normal file
|
@ -0,0 +1,107 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
|
||||
|
||||
OpenRISC 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>
|
||||
|
||||
.text
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV, @function
|
||||
/*
|
||||
r3: size to allocate on stack
|
||||
r4: extended cif structure
|
||||
r5: function pointer ffi_prep_args
|
||||
r6: ret address
|
||||
r7: function to call
|
||||
r8: flag for return type
|
||||
*/
|
||||
|
||||
ffi_call_SYSV:
|
||||
/* Store registers used on stack */
|
||||
l.sw -4(r1), r9 /* return address */
|
||||
l.sw -8(r1), r1 /* stack address */
|
||||
l.sw -12(r1), r14 /* callee saved registers */
|
||||
l.sw -16(r1), r16
|
||||
l.sw -20(r1), r18
|
||||
l.sw -24(r1), r20
|
||||
|
||||
l.ori r14, r1, 0x0 /* save stack pointer */
|
||||
l.addi r1, r1, -24
|
||||
|
||||
l.ori r16, r7, 0x0 /* save function address */
|
||||
l.ori r18, r6, 0x0 /* save ret address */
|
||||
l.ori r20, r8, 0x0 /* save flag */
|
||||
|
||||
l.sub r1, r1, r3 /* reserve space on stack */
|
||||
|
||||
/* Call ffi_prep_args */
|
||||
l.ori r3, r1, 0x0 /* first argument stack address, second already ecif */
|
||||
l.jalr r5
|
||||
l.nop
|
||||
|
||||
/* Load register arguments and call*/
|
||||
|
||||
l.lwz r3, 0(r1)
|
||||
l.lwz r4, 4(r1)
|
||||
l.lwz r5, 8(r1)
|
||||
l.lwz r6, 12(r1)
|
||||
l.lwz r7, 16(r1)
|
||||
l.lwz r8, 20(r1)
|
||||
l.ori r1, r11, 0x0 /* new stack pointer */
|
||||
l.jalr r16
|
||||
l.nop
|
||||
|
||||
/* handle return values */
|
||||
|
||||
l.sfeqi r20, FFI_TYPE_STRUCT
|
||||
l.bf ret /* structs don't return an rvalue */
|
||||
l.nop
|
||||
|
||||
/* copy ret address */
|
||||
|
||||
l.sfeqi r20, FFI_TYPE_UINT64
|
||||
l.bnf four_byte_ret /* 8 byte value is returned */
|
||||
l.nop
|
||||
|
||||
l.sw 4(r18), r12
|
||||
|
||||
four_byte_ret:
|
||||
l.sw 0(r18), r11
|
||||
|
||||
ret:
|
||||
/* return */
|
||||
l.ori r1, r14, 0x0 /* reset stack pointer */
|
||||
l.lwz r9, -4(r1)
|
||||
l.lwz r1, -8(r1)
|
||||
l.lwz r14, -12(r1)
|
||||
l.lwz r16, -16(r1)
|
||||
l.lwz r18, -20(r1)
|
||||
l.lwz r20, -24(r1)
|
||||
l.jr r9
|
||||
l.nop
|
||||
|
||||
.size ffi_call_SYSV, .-ffi_call_SYSV
|
|
@ -62,6 +62,8 @@ typedef enum ffi_abi {
|
|||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
|
|
|
@ -137,7 +137,7 @@ ffi_call_AIX:
|
|||
mtcrf 0x40, r31
|
||||
mtctr r0
|
||||
/* Load all those argument registers. */
|
||||
// We have set up a nice stack frame, just load it into registers.
|
||||
/* We have set up a nice stack frame, just load it into registers. */
|
||||
ld r3, 40+(1*8)(r1)
|
||||
ld r4, 40+(2*8)(r1)
|
||||
ld r5, 40+(3*8)(r1)
|
||||
|
@ -150,7 +150,7 @@ ffi_call_AIX:
|
|||
|
||||
L1:
|
||||
/* Load all the FP registers. */
|
||||
bf 6,L2 // 2f + 0x18
|
||||
bf 6,L2 /* 2f + 0x18 */
|
||||
lfd f1,-32-(13*8)(r28)
|
||||
lfd f2,-32-(12*8)(r28)
|
||||
lfd f3,-32-(11*8)(r28)
|
||||
|
@ -239,7 +239,7 @@ L(float_return_value):
|
|||
mtcrf 0x40, r31
|
||||
mtctr r0
|
||||
/* Load all those argument registers. */
|
||||
// We have set up a nice stack frame, just load it into registers.
|
||||
/* We have set up a nice stack frame, just load it into registers. */
|
||||
lwz r3, 20+(1*4)(r1)
|
||||
lwz r4, 20+(2*4)(r1)
|
||||
lwz r5, 20+(3*4)(r1)
|
||||
|
@ -252,7 +252,7 @@ L(float_return_value):
|
|||
|
||||
L1:
|
||||
/* Load all the FP registers. */
|
||||
bf 6,L2 // 2f + 0x18
|
||||
bf 6,L2 /* 2f + 0x18 */
|
||||
lfd f1,-16-(13*8)(r28)
|
||||
lfd f2,-16-(12*8)(r28)
|
||||
lfd f3,-16-(11*8)(r28)
|
||||
|
@ -307,7 +307,7 @@ L(float_return_value):
|
|||
#endif
|
||||
.long 0
|
||||
.byte 0,0,0,1,128,4,0,0
|
||||
//END(ffi_call_AIX)
|
||||
/* END(ffi_call_AIX) */
|
||||
|
||||
.csect .text[PR]
|
||||
.align 2
|
||||
|
@ -325,4 +325,4 @@ ffi_call_DARWIN:
|
|||
blr
|
||||
.long 0
|
||||
.byte 0,0,0,0,0,0,0,0
|
||||
//END(ffi_call_DARWIN)
|
||||
/* END(ffi_call_DARWIN) */
|
||||
|
|
|
@ -318,11 +318,6 @@ _ffi_call_AIX:
|
|||
|
||||
#define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
|
||||
|
||||
.static_data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB0$non_lazy_ptr:
|
||||
.g_long Lstartcode
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
|
@ -335,7 +330,7 @@ LSCIE1:
|
|||
.byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x10 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0x10 ; FDE Encoding (pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
|
@ -349,7 +344,7 @@ LSFDE1:
|
|||
.long L$set$1 ; FDE Length
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB0$non_lazy_ptr-. ; FDE initial location
|
||||
.g_long Lstartcode-. ; FDE initial location
|
||||
.set L$set$3,LFE1-Lstartcode
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
|
|
|
@ -192,7 +192,7 @@ LCFI1:
|
|||
lg r0,0(r3) ; size => r0
|
||||
lhz r3,FFI_TYPE_TYPE(r3) ; type => r3
|
||||
|
||||
/* The helper will have intercepted struture returns and inserted
|
||||
/* The helper will have intercepted structure returns and inserted
|
||||
the caller`s destination address for structs returned by ref. */
|
||||
|
||||
/* r3 contains the return type so use it to look up in a table
|
||||
|
@ -467,11 +467,6 @@ Lendcode:
|
|||
#define EH_FRAME_OFFSETA MODE_CHOICE(176,0x90)
|
||||
#define EH_FRAME_OFFSETB MODE_CHOICE(1,3)
|
||||
|
||||
.static_data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB1$non_lazy_ptr:
|
||||
.g_long Lstartcode
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
|
@ -484,7 +479,7 @@ LSCIE1:
|
|||
.byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x10 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0x10 ; FDE Encoding (pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
|
@ -498,7 +493,7 @@ LSFDE1:
|
|||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
||||
.g_long Lstartcode-. ; FDE initial location
|
||||
.set L$set$3,LFE1-Lstartcode
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
|
@ -523,12 +518,12 @@ LEFDE1:
|
|||
L_ffi_closure_helper_DARWIN$stub:
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
mflr r0
|
||||
bcl 20,31,"L00000000001$spb"
|
||||
"L00000000001$spb":
|
||||
bcl 20,31,"L1$spb"
|
||||
"L1$spb":
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L00000000001$spb")
|
||||
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")
|
||||
mtlr r0
|
||||
lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L00000000001$spb")(r11)
|
||||
lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
|
@ -542,12 +537,12 @@ L_ffi_closure_helper_DARWIN$lazy_ptr:
|
|||
L_darwin64_struct_ret_by_value_p$stub:
|
||||
.indirect_symbol _darwin64_struct_ret_by_value_p
|
||||
mflr r0
|
||||
bcl 20,31,"L00000000002$spb"
|
||||
"L00000000002$spb":
|
||||
bcl 20,31,"L2$spb"
|
||||
"L2$spb":
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L00000000002$spb")
|
||||
addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")
|
||||
mtlr r0
|
||||
lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L00000000002$spb")(r11)
|
||||
lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
|
@ -560,12 +555,12 @@ L_darwin64_struct_ret_by_value_p$lazy_ptr:
|
|||
L_darwin64_pass_struct_floats$stub:
|
||||
.indirect_symbol _darwin64_pass_struct_floats
|
||||
mflr r0
|
||||
bcl 20,31,"L00000000003$spb"
|
||||
"L00000000003$spb":
|
||||
bcl 20,31,"L3$spb"
|
||||
"L3$spb":
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L00000000003$spb")
|
||||
addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")
|
||||
mtlr r0
|
||||
lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L00000000003$spb")(r11)
|
||||
lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
|
|
|
@ -70,8 +70,12 @@ ffi_prep_cif_machdep_var (ffi_cif *cif,
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
static void
|
||||
ffi_call_int (ffi_cif *cif,
|
||||
void (*fn) (void),
|
||||
void *rvalue,
|
||||
void **avalue,
|
||||
void *closure)
|
||||
{
|
||||
/* The final SYSV ABI says that structures smaller or equal 8 bytes
|
||||
are returned in r3/r4. A draft ABI used by linux instead returns
|
||||
|
@ -97,9 +101,10 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
|
||||
#ifdef POWERPC64
|
||||
ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
|
||||
ffi_call_LINUX64 (&ecif, fn, ecif.rvalue, cif->flags, closure,
|
||||
-(long) cif->bytes);
|
||||
#else
|
||||
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
|
||||
ffi_call_SYSV (&ecif, fn, ecif.rvalue, cif->flags, closure, -cif->bytes);
|
||||
#endif
|
||||
|
||||
/* Check for a bounce-buffered return value */
|
||||
|
@ -125,6 +130,18 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
|
||||
{
|
||||
ffi_call_int (cif, fn, rvalue, avalue, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
|
||||
void *closure)
|
||||
{
|
||||
ffi_call_int (cif, fn, rvalue, avalue, closure);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure *closure,
|
||||
|
@ -139,3 +156,18 @@ ffi_prep_closure_loc (ffi_closure *closure,
|
|||
return ffi_prep_closure_loc_sysv (closure, cif, fun, user_data, codeloc);
|
||||
#endif
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_go_closure (ffi_go_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *))
|
||||
{
|
||||
#ifdef POWERPC64
|
||||
closure->tramp = ffi_go_closure_linux64;
|
||||
#else
|
||||
closure->tramp = ffi_go_closure_sysv;
|
||||
#endif
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
return FFI_OK;
|
||||
}
|
||||
|
|
|
@ -302,10 +302,10 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
|||
}
|
||||
|
||||
/* Check that we didn't overrun the stack... */
|
||||
//FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
|
||||
//FFI_ASSERT((unsigned *)fpr_base
|
||||
// <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
||||
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||
/* FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
|
||||
FFI_ASSERT((unsigned *)fpr_base
|
||||
<= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
||||
FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); */
|
||||
}
|
||||
|
||||
#if defined(POWERPC_DARWIN64)
|
||||
|
@ -593,7 +593,7 @@ darwin_adjust_aggregate_sizes (ffi_type *s)
|
|||
/* Natural alignment for all items. */
|
||||
align = p->alignment;
|
||||
#else
|
||||
/* Natrual alignment for the first item... */
|
||||
/* Natural alignment for the first item... */
|
||||
if (i == 0)
|
||||
align = p->alignment;
|
||||
else if (p->alignment == 16 || p->alignment < 4)
|
||||
|
|
|
@ -667,7 +667,8 @@ flush_icache (char *wraddr, char *xaddr, int size)
|
|||
}
|
||||
#endif
|
||||
|
||||
ffi_status
|
||||
|
||||
ffi_status FFI_HIDDEN
|
||||
ffi_prep_closure_loc_linux64 (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
|
@ -688,16 +689,17 @@ ffi_prep_closure_loc_linux64 (ffi_closure *closure,
|
|||
/* 2: .quad context */
|
||||
*(void **) &tramp[4] = (void *) ffi_closure_LINUX64;
|
||||
*(void **) &tramp[6] = codeloc;
|
||||
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
|
||||
flush_icache ((char *) tramp, (char *) codeloc, 4 * 4);
|
||||
#else
|
||||
void **tramp = (void **) &closure->tramp[0];
|
||||
|
||||
if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
/* Copy function address and TOC from ffi_closure_LINUX64. */
|
||||
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
|
||||
tramp[2] = codeloc;
|
||||
/* Copy function address and TOC from ffi_closure_LINUX64 OPD. */
|
||||
memcpy (&tramp[0], (void **) ffi_closure_LINUX64, sizeof (void *));
|
||||
tramp[1] = codeloc;
|
||||
memcpy (&tramp[2], (void **) ffi_closure_LINUX64 + 1, sizeof (void *));
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
|
@ -709,8 +711,12 @@ ffi_prep_closure_loc_linux64 (ffi_closure *closure,
|
|||
|
||||
|
||||
int FFI_HIDDEN
|
||||
ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
|
||||
unsigned long *pst, ffi_dblfl *pfr)
|
||||
ffi_closure_helper_LINUX64 (ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data,
|
||||
void *rvalue,
|
||||
unsigned long *pst,
|
||||
ffi_dblfl *pfr)
|
||||
{
|
||||
/* rvalue is the pointer to space for return value in closure assembly */
|
||||
/* pst is the pointer to parameter save area
|
||||
|
@ -720,11 +726,9 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
|
|||
void **avalue;
|
||||
ffi_type **arg_types;
|
||||
unsigned long i, avn, nfixedargs;
|
||||
ffi_cif *cif;
|
||||
ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
|
||||
unsigned long align;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
/* Copy the caller's structure return value address so that the
|
||||
|
@ -924,8 +928,7 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
|
|||
i++;
|
||||
}
|
||||
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
(*fun) (cif, rvalue, avalue, user_data);
|
||||
|
||||
/* Tell ffi_closure_LINUX64 how to perform return type promotions. */
|
||||
if ((cif->flags & FLAG_RETURNS_SMST) != 0)
|
||||
|
|
|
@ -56,22 +56,39 @@ typedef union
|
|||
} ffi_dblfl;
|
||||
|
||||
void FFI_HIDDEN ffi_closure_SYSV (void);
|
||||
void FFI_HIDDEN ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*)(void));
|
||||
void FFI_HIDDEN ffi_go_closure_sysv (void);
|
||||
void FFI_HIDDEN ffi_call_SYSV(extended_cif *, void (*)(void), void *,
|
||||
unsigned, void *, int);
|
||||
|
||||
void FFI_HIDDEN ffi_prep_types_sysv (ffi_abi);
|
||||
ffi_status FFI_HIDDEN ffi_prep_cif_sysv (ffi_cif *);
|
||||
int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
|
||||
ffi_status FFI_HIDDEN ffi_prep_closure_loc_sysv (ffi_closure *,
|
||||
ffi_cif *,
|
||||
void (*) (ffi_cif *, void *,
|
||||
void **, void *),
|
||||
void *, void *);
|
||||
int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_cif *,
|
||||
void (*) (ffi_cif *, void *,
|
||||
void **, void *),
|
||||
void *, void *, unsigned long *,
|
||||
ffi_dblfl *, unsigned long *);
|
||||
|
||||
void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long, unsigned long,
|
||||
unsigned long *, void (*)(void));
|
||||
void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, void (*) (void), void *,
|
||||
unsigned long, void *, long);
|
||||
void FFI_HIDDEN ffi_closure_LINUX64 (void);
|
||||
void FFI_HIDDEN ffi_go_closure_linux64 (void);
|
||||
|
||||
void FFI_HIDDEN ffi_prep_types_linux64 (ffi_abi);
|
||||
ffi_status FFI_HIDDEN ffi_prep_cif_linux64 (ffi_cif *);
|
||||
ffi_status FFI_HIDDEN ffi_prep_cif_linux64_var (ffi_cif *, unsigned int,
|
||||
unsigned int);
|
||||
void FFI_HIDDEN ffi_prep_args64 (extended_cif *, unsigned long *const);
|
||||
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
|
||||
ffi_status FFI_HIDDEN ffi_prep_closure_loc_linux64 (ffi_closure *, ffi_cif *,
|
||||
void (*) (ffi_cif *, void *,
|
||||
void **, void *),
|
||||
void *, void *);
|
||||
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_cif *,
|
||||
void (*) (ffi_cif *, void *,
|
||||
void **, void *),
|
||||
void *, void *,
|
||||
unsigned long *, ffi_dblfl *);
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
|
||||
/* About the SYSV ABI. */
|
||||
#define ASM_NEEDS_REGISTERS 4
|
||||
#define ASM_NEEDS_REGISTERS 6
|
||||
#define NUM_GPR_ARG_REGISTERS 8
|
||||
#define NUM_FPR_ARG_REGISTERS 8
|
||||
|
||||
|
@ -654,18 +654,18 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
|
|||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
||||
tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
|
||||
tramp[4] = 0x7d6802a6; /* mflr r11 */
|
||||
tramp[5] = 0x7c0803a6; /* mtlr r0 */
|
||||
tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
|
||||
tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
|
||||
tramp[8] = 0x7c0903a6; /* mtctr r0 */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
*(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
|
||||
*(void **) &tramp[3] = codeloc; /* context */
|
||||
tramp[1] = 0x429f0005; /* bcl 20,31,.+4 */
|
||||
tramp[2] = 0x7d6802a6; /* mflr r11 */
|
||||
tramp[3] = 0x7c0803a6; /* mtlr r0 */
|
||||
tramp[4] = 0x800b0018; /* lwz r0,24(r11) */
|
||||
tramp[5] = 0x816b001c; /* lwz r11,28(r11) */
|
||||
tramp[6] = 0x7c0903a6; /* mtctr r0 */
|
||||
tramp[7] = 0x4e800420; /* bctr */
|
||||
*(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */
|
||||
*(void **) &tramp[9] = codeloc; /* context */
|
||||
|
||||
/* Flush the icache. */
|
||||
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
|
||||
flush_icache ((char *)tramp, (char *)codeloc, 8 * 4);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
|
@ -682,8 +682,12 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
|
|||
following helper function to do most of the work. */
|
||||
|
||||
int
|
||||
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
||||
unsigned long *pgr, ffi_dblfl *pfr,
|
||||
ffi_closure_helper_SYSV (ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data,
|
||||
void *rvalue,
|
||||
unsigned long *pgr,
|
||||
ffi_dblfl *pfr,
|
||||
unsigned long *pst)
|
||||
{
|
||||
/* rvalue is the pointer to space for return value in closure assembly */
|
||||
|
@ -699,7 +703,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
#endif
|
||||
long ng = 0; /* number of general registers already used */
|
||||
|
||||
ffi_cif *cif = closure->cif;
|
||||
unsigned size = cif->rtype->size;
|
||||
unsigned short rtypenum = cif->rtype->type;
|
||||
|
||||
|
@ -915,7 +918,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
i++;
|
||||
}
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
(*fun) (cif, rvalue, avalue, user_data);
|
||||
|
||||
/* Tell ffi_closure_SYSV how to perform return type promotions.
|
||||
Because the FFI_SYSV ABI returns the structures <= 8 bytes in
|
||||
|
|
|
@ -138,23 +138,35 @@ typedef enum ffi_abi {
|
|||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
#if defined (POWERPC) || defined (POWERPC_FREEBSD)
|
||||
# define FFI_GO_CLOSURES 1
|
||||
# define FFI_TARGET_SPECIFIC_VARIADIC 1
|
||||
# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs
|
||||
#endif
|
||||
|
||||
/* For additional types like the below, take care about the order in
|
||||
ppc_closures.S. They must follow after the FFI_TYPE_LAST. */
|
||||
/* ppc_closure.S and linux64_closure.S expect this. */
|
||||
#define FFI_PPC_TYPE_LAST FFI_TYPE_POINTER
|
||||
|
||||
/* We define additional types below. If generic types are added that
|
||||
must be supported by powerpc libffi then it is likely that
|
||||
FFI_PPC_TYPE_LAST needs increasing *and* the jump tables in
|
||||
ppc_closure.S and linux64_closure.S be extended. */
|
||||
|
||||
#if !(FFI_TYPE_LAST == FFI_PPC_TYPE_LAST \
|
||||
|| (FFI_TYPE_LAST == FFI_TYPE_COMPLEX \
|
||||
&& !defined FFI_TARGET_HAS_COMPLEX_TYPE))
|
||||
# error "You likely have a broken powerpc libffi"
|
||||
#endif
|
||||
|
||||
/* Needed for soft-float long-double-128 support. */
|
||||
#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
|
||||
#define FFI_TYPE_UINT128 (FFI_PPC_TYPE_LAST + 1)
|
||||
|
||||
/* Needed for FFI_SYSV small structure returns. */
|
||||
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
|
||||
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 2)
|
||||
|
||||
/* Used by ELFv2 for homogenous structure returns. */
|
||||
#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_TYPE_LAST + 1)
|
||||
#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_TYPE_LAST + 2)
|
||||
#define FFI_V2_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 3)
|
||||
#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_PPC_TYPE_LAST + 1)
|
||||
#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_PPC_TYPE_LAST + 2)
|
||||
#define FFI_V2_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 3)
|
||||
|
||||
#if _CALL_ELF == 2
|
||||
# define FFI_TRAMPOLINE_SIZE 32
|
||||
|
|
|
@ -32,8 +32,9 @@
|
|||
#ifdef POWERPC64
|
||||
.hidden ffi_call_LINUX64
|
||||
.globl ffi_call_LINUX64
|
||||
# if _CALL_ELF == 2
|
||||
.text
|
||||
.cfi_startproc
|
||||
# if _CALL_ELF == 2
|
||||
ffi_call_LINUX64:
|
||||
addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha
|
||||
addi %r2, %r2, .TOC.-ffi_call_LINUX64@l
|
||||
|
@ -57,20 +58,26 @@ ffi_call_LINUX64:
|
|||
.ffi_call_LINUX64:
|
||||
# endif
|
||||
# endif
|
||||
.LFB1:
|
||||
mflr %r0
|
||||
std %r28, -32(%r1)
|
||||
std %r29, -24(%r1)
|
||||
std %r30, -16(%r1)
|
||||
std %r31, -8(%r1)
|
||||
std %r7, 8(%r1) /* closure, saved in cr field. */
|
||||
std %r0, 16(%r1)
|
||||
|
||||
mr %r28, %r1 /* our AP. */
|
||||
.LCFI0:
|
||||
stdux %r1, %r1, %r4
|
||||
mr %r31, %r5 /* flags, */
|
||||
mr %r30, %r6 /* rvalue, */
|
||||
mr %r29, %r7 /* function address. */
|
||||
.cfi_def_cfa_register 28
|
||||
.cfi_offset 65, 16
|
||||
.cfi_offset 31, -8
|
||||
.cfi_offset 30, -16
|
||||
.cfi_offset 29, -24
|
||||
.cfi_offset 28, -32
|
||||
|
||||
stdux %r1, %r1, %r8
|
||||
mr %r31, %r6 /* flags, */
|
||||
mr %r30, %r5 /* rvalue, */
|
||||
mr %r29, %r4 /* function address. */
|
||||
/* Save toc pointer, not for the ffi_prep_args64 call, but for the later
|
||||
bctrl function call. */
|
||||
# if _CALL_ELF == 2
|
||||
|
@ -92,7 +99,6 @@ ffi_call_LINUX64:
|
|||
# else
|
||||
ld %r12, 0(%r29)
|
||||
ld %r2, 8(%r29)
|
||||
ld %r11, 16(%r29)
|
||||
# endif
|
||||
/* Now do the call. */
|
||||
/* Set up cr1 with bits 4-7 of the flags. */
|
||||
|
@ -130,6 +136,7 @@ ffi_call_LINUX64:
|
|||
2:
|
||||
|
||||
/* Make the call. */
|
||||
ld %r11, 8(%r28)
|
||||
bctrl
|
||||
|
||||
/* This must follow the call immediately, the unwinder
|
||||
|
@ -151,6 +158,7 @@ ffi_call_LINUX64:
|
|||
.Ldone_return_value:
|
||||
/* Restore the registers we used and return. */
|
||||
mr %r1, %r28
|
||||
.cfi_def_cfa_register 1
|
||||
ld %r0, 16(%r28)
|
||||
ld %r28, -32(%r28)
|
||||
mtlr %r0
|
||||
|
@ -160,6 +168,7 @@ ffi_call_LINUX64:
|
|||
blr
|
||||
|
||||
.Lfp_return_value:
|
||||
.cfi_def_cfa_register 28
|
||||
bf 28, .Lfloat_return_value
|
||||
stfd %f1, 0(%r30)
|
||||
mtcrf 0x02, %r31 /* cr6 */
|
||||
|
@ -199,61 +208,19 @@ ffi_call_LINUX64:
|
|||
std %r4, 8(%r30)
|
||||
b .Ldone_return_value
|
||||
|
||||
.LFE1:
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,4,0,0
|
||||
.cfi_endproc
|
||||
# if _CALL_ELF == 2
|
||||
.size ffi_call_LINUX64,.-ffi_call_LINUX64
|
||||
# else
|
||||
# ifdef _CALL_LINUX
|
||||
.size ffi_call_LINUX64,.-.L.ffi_call_LINUX64
|
||||
# else
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,4,0,0
|
||||
.size .ffi_call_LINUX64,.-.ffi_call_LINUX64
|
||||
# endif
|
||||
# endif
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -8 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x14 # FDE Encoding (pcrel udata8)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 3
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.8byte .LFB1-. # FDE initial location
|
||||
.8byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x2 # DW_CFA_advance_loc1
|
||||
.byte .LCFI0-.LFB1
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0x1c
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -2
|
||||
.byte 0x9f # DW_CFA_offset, column 0x1f
|
||||
.uleb128 0x1
|
||||
.byte 0x9e # DW_CFA_offset, column 0x1e
|
||||
.uleb128 0x2
|
||||
.byte 0x9d # DW_CFA_offset, column 0x1d
|
||||
.uleb128 0x3
|
||||
.byte 0x9c # DW_CFA_offset, column 0x1c
|
||||
.uleb128 0x4
|
||||
.align 3
|
||||
.LEFDE1:
|
||||
|
||||
#endif
|
||||
|
||||
#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
|
||||
|
|
|
@ -33,8 +33,9 @@
|
|||
#ifdef POWERPC64
|
||||
FFI_HIDDEN (ffi_closure_LINUX64)
|
||||
.globl ffi_closure_LINUX64
|
||||
# if _CALL_ELF == 2
|
||||
.text
|
||||
.cfi_startproc
|
||||
# if _CALL_ELF == 2
|
||||
ffi_closure_LINUX64:
|
||||
addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
|
||||
addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
|
||||
|
@ -73,20 +74,18 @@ ffi_closure_LINUX64:
|
|||
# define RETVAL PARMSAVE+64
|
||||
# endif
|
||||
|
||||
.LFB1:
|
||||
# if _CALL_ELF == 2
|
||||
ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
|
||||
mflr %r0
|
||||
lwz %r12, 28(%r12) # cif->flags
|
||||
mtcrf 0x40, %r12
|
||||
addi %r12, %r1, PARMSAVE
|
||||
bt 7, .Lparmsave
|
||||
bt 7, 0f
|
||||
# Our caller has not allocated a parameter save area.
|
||||
# We need to allocate one here and use it to pass gprs to
|
||||
# ffi_closure_helper_LINUX64.
|
||||
addi %r12, %r1, -STACKFRAME+PARMSAVE
|
||||
.Lparmsave:
|
||||
std %r0, 16(%r1)
|
||||
0:
|
||||
# Save general regs into parm save area
|
||||
std %r3, 0(%r12)
|
||||
std %r4, 8(%r12)
|
||||
|
@ -98,8 +97,12 @@ ffi_closure_LINUX64:
|
|||
std %r10, 56(%r12)
|
||||
|
||||
# load up the pointer to the parm save area
|
||||
mr %r5, %r12
|
||||
mr %r7, %r12
|
||||
# else
|
||||
# copy r2 to r11 and load TOC into r2
|
||||
mr %r11, %r2
|
||||
ld %r2, 16(%r2)
|
||||
|
||||
mflr %r0
|
||||
# Save general regs into parm save area
|
||||
# This is the parameter save area set up by our caller.
|
||||
|
@ -112,12 +115,19 @@ ffi_closure_LINUX64:
|
|||
std %r9, PARMSAVE+48(%r1)
|
||||
std %r10, PARMSAVE+56(%r1)
|
||||
|
||||
# load up the pointer to the parm save area
|
||||
addi %r7, %r1, PARMSAVE
|
||||
# endif
|
||||
std %r0, 16(%r1)
|
||||
|
||||
# load up the pointer to the parm save area
|
||||
addi %r5, %r1, PARMSAVE
|
||||
# endif
|
||||
# closure->cif
|
||||
ld %r3, FFI_TRAMPOLINE_SIZE(%r11)
|
||||
# closure->fun
|
||||
ld %r4, FFI_TRAMPOLINE_SIZE+8(%r11)
|
||||
# closure->user_data
|
||||
ld %r5, FFI_TRAMPOLINE_SIZE+16(%r11)
|
||||
|
||||
.Ldoclosure:
|
||||
# next save fpr 1 to fpr 13
|
||||
stfd %f1, -104+(0*8)(%r1)
|
||||
stfd %f2, -104+(1*8)(%r1)
|
||||
|
@ -134,16 +144,14 @@ ffi_closure_LINUX64:
|
|||
stfd %f13, -104+(12*8)(%r1)
|
||||
|
||||
# load up the pointer to the saved fpr registers */
|
||||
addi %r6, %r1, -104
|
||||
addi %r8, %r1, -104
|
||||
|
||||
# load up the pointer to the result storage
|
||||
addi %r4, %r1, -STACKFRAME+RETVAL
|
||||
addi %r6, %r1, -STACKFRAME+RETVAL
|
||||
|
||||
stdu %r1, -STACKFRAME(%r1)
|
||||
.LCFI0:
|
||||
|
||||
# get the context pointer from the trampoline
|
||||
mr %r3, %r11
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
.cfi_offset 65, 16
|
||||
|
||||
# make the call
|
||||
# if defined _CALL_LINUX || _CALL_ELF == 2
|
||||
|
@ -178,7 +186,9 @@ ffi_closure_LINUX64:
|
|||
# case FFI_TYPE_VOID
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
nop
|
||||
# case FFI_TYPE_INT
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
|
@ -188,17 +198,23 @@ ffi_closure_LINUX64:
|
|||
# endif
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_FLOAT
|
||||
lfs %f1, RETVAL+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_DOUBLE
|
||||
lfd %f1, RETVAL+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
lfd %f1, RETVAL+0(%r1)
|
||||
mtlr %r0
|
||||
|
@ -212,7 +228,9 @@ ffi_closure_LINUX64:
|
|||
# endif
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_SINT8
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
lbz %r3, RETVAL+0(%r1)
|
||||
|
@ -231,7 +249,9 @@ ffi_closure_LINUX64:
|
|||
mtlr %r0
|
||||
.Lfinish:
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_SINT16
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
lha %r3, RETVAL+0(%r1)
|
||||
|
@ -240,7 +260,9 @@ ffi_closure_LINUX64:
|
|||
# endif
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_UINT32
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
lwz %r3, RETVAL+0(%r1)
|
||||
|
@ -249,7 +271,9 @@ ffi_closure_LINUX64:
|
|||
# endif
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_SINT32
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
lwa %r3, RETVAL+0(%r1)
|
||||
|
@ -258,27 +282,37 @@ ffi_closure_LINUX64:
|
|||
# endif
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_UINT64
|
||||
ld %r3, RETVAL+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_SINT64
|
||||
ld %r3, RETVAL+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_TYPE_STRUCT
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
nop
|
||||
# case FFI_TYPE_POINTER
|
||||
ld %r3, RETVAL+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
# case FFI_V2_TYPE_FLOAT_HOMOG
|
||||
lfs %f1, RETVAL+0(%r1)
|
||||
lfs %f2, RETVAL+4(%r1)
|
||||
|
@ -295,7 +329,9 @@ ffi_closure_LINUX64:
|
|||
lfd %f7, RETVAL+48(%r1)
|
||||
lfd %f8, RETVAL+56(%r1)
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
.Lmorefloat:
|
||||
lfs %f4, RETVAL+12(%r1)
|
||||
mtlr %r0
|
||||
|
@ -304,13 +340,16 @@ ffi_closure_LINUX64:
|
|||
lfs %f7, RETVAL+24(%r1)
|
||||
lfs %f8, RETVAL+28(%r1)
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
.Lsmall:
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
ld %r3,RETVAL+0(%r1)
|
||||
mtlr %r0
|
||||
ld %r4,RETVAL+8(%r1)
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
# else
|
||||
# A struct smaller than a dword is returned in the low bits of r3
|
||||
|
@ -324,63 +363,124 @@ ffi_closure_LINUX64:
|
|||
mtlr %r0
|
||||
ld %r4,RETVAL+8(%r1)
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset STACKFRAME
|
||||
.Lsmalldown:
|
||||
addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
|
||||
mtlr %r0
|
||||
sldi %r5, %r5, 3
|
||||
addi %r1, %r1, STACKFRAME
|
||||
.cfi_def_cfa_offset 0
|
||||
srd %r3, %r3, %r5
|
||||
blr
|
||||
# endif
|
||||
|
||||
.LFE1:
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,0,0,0
|
||||
.cfi_endproc
|
||||
# if _CALL_ELF == 2
|
||||
.size ffi_closure_LINUX64,.-ffi_closure_LINUX64
|
||||
# else
|
||||
# ifdef _CALL_LINUX
|
||||
.size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
|
||||
# else
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,0,0,0
|
||||
.size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
|
||||
# endif
|
||||
# endif
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -8 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x14 # FDE Encoding (pcrel udata8)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 3
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.8byte .LFB1-. # FDE initial location
|
||||
.8byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x2 # DW_CFA_advance_loc1
|
||||
.byte .LCFI0-.LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 STACKFRAME
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -2
|
||||
.align 3
|
||||
.LEFDE1:
|
||||
|
||||
FFI_HIDDEN (ffi_go_closure_linux64)
|
||||
.globl ffi_go_closure_linux64
|
||||
.text
|
||||
.cfi_startproc
|
||||
# if _CALL_ELF == 2
|
||||
ffi_go_closure_linux64:
|
||||
addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha
|
||||
addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l
|
||||
.localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
|
||||
# else
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
ffi_go_closure_linux64:
|
||||
# ifdef _CALL_LINUX
|
||||
.quad .L.ffi_go_closure_linux64,.TOC.@tocbase,0
|
||||
.type ffi_go_closure_linux64,@function
|
||||
.text
|
||||
.L.ffi_go_closure_linux64:
|
||||
# else
|
||||
FFI_HIDDEN (.ffi_go_closure_linux64)
|
||||
.globl .ffi_go_closure_linux64
|
||||
.quad .ffi_go_closure_linux64,.TOC.@tocbase,0
|
||||
.size ffi_go_closure_linux64,24
|
||||
.type .ffi_go_closure_linux64,@function
|
||||
.text
|
||||
.ffi_go_closure_linux64:
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if _CALL_ELF == 2
|
||||
ld %r12, 8(%r11) # closure->cif
|
||||
mflr %r0
|
||||
lwz %r12, 28(%r12) # cif->flags
|
||||
mtcrf 0x40, %r12
|
||||
addi %r12, %r1, PARMSAVE
|
||||
bt 7, 0f
|
||||
# Our caller has not allocated a parameter save area.
|
||||
# We need to allocate one here and use it to pass gprs to
|
||||
# ffi_closure_helper_LINUX64.
|
||||
addi %r12, %r1, -STACKFRAME+PARMSAVE
|
||||
0:
|
||||
# Save general regs into parm save area
|
||||
std %r3, 0(%r12)
|
||||
std %r4, 8(%r12)
|
||||
std %r5, 16(%r12)
|
||||
std %r6, 24(%r12)
|
||||
std %r7, 32(%r12)
|
||||
std %r8, 40(%r12)
|
||||
std %r9, 48(%r12)
|
||||
std %r10, 56(%r12)
|
||||
|
||||
# load up the pointer to the parm save area
|
||||
mr %r7, %r12
|
||||
# else
|
||||
mflr %r0
|
||||
# Save general regs into parm save area
|
||||
# This is the parameter save area set up by our caller.
|
||||
std %r3, PARMSAVE+0(%r1)
|
||||
std %r4, PARMSAVE+8(%r1)
|
||||
std %r5, PARMSAVE+16(%r1)
|
||||
std %r6, PARMSAVE+24(%r1)
|
||||
std %r7, PARMSAVE+32(%r1)
|
||||
std %r8, PARMSAVE+40(%r1)
|
||||
std %r9, PARMSAVE+48(%r1)
|
||||
std %r10, PARMSAVE+56(%r1)
|
||||
|
||||
# load up the pointer to the parm save area
|
||||
addi %r7, %r1, PARMSAVE
|
||||
# endif
|
||||
std %r0, 16(%r1)
|
||||
|
||||
# closure->cif
|
||||
ld %r3, 8(%r11)
|
||||
# closure->fun
|
||||
ld %r4, 16(%r11)
|
||||
# user_data
|
||||
mr %r5, %r11
|
||||
b .Ldoclosure
|
||||
|
||||
.cfi_endproc
|
||||
# if _CALL_ELF == 2
|
||||
.size ffi_go_closure_linux64,.-ffi_go_closure_linux64
|
||||
# else
|
||||
# ifdef _CALL_LINUX
|
||||
.size ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
|
||||
# else
|
||||
.long 0
|
||||
.byte 0,12,0,1,128,0,0,0
|
||||
.size .ffi_go_closure_linux64,.-.ffi_go_closure_linux64
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
|
||||
|
|
|
@ -33,13 +33,14 @@
|
|||
|
||||
#ifndef POWERPC64
|
||||
|
||||
FFI_HIDDEN(ffi_closure_SYSV)
|
||||
ENTRY(ffi_closure_SYSV)
|
||||
.LFB1:
|
||||
.cfi_startproc
|
||||
stwu %r1,-144(%r1)
|
||||
.LCFI0:
|
||||
.cfi_def_cfa_offset 144
|
||||
mflr %r0
|
||||
.LCFI1:
|
||||
stw %r0,148(%r1)
|
||||
.cfi_offset 65, 4
|
||||
|
||||
# we want to build up an areas for the parameters passed
|
||||
# in registers (both floating point and integer)
|
||||
|
@ -48,6 +49,17 @@ ENTRY(ffi_closure_SYSV)
|
|||
stw %r3, 16(%r1)
|
||||
stw %r4, 20(%r1)
|
||||
stw %r5, 24(%r1)
|
||||
|
||||
# set up registers for the routine that does the work
|
||||
|
||||
# closure->cif
|
||||
lwz %r3,FFI_TRAMPOLINE_SIZE(%r11)
|
||||
# closure->fun
|
||||
lwz %r4,FFI_TRAMPOLINE_SIZE+4(%r11)
|
||||
# closure->user_data
|
||||
lwz %r5,FFI_TRAMPOLINE_SIZE+8(%r11)
|
||||
|
||||
.Ldoclosure:
|
||||
stw %r6, 28(%r1)
|
||||
stw %r7, 32(%r1)
|
||||
stw %r8, 36(%r1)
|
||||
|
@ -66,23 +78,18 @@ ENTRY(ffi_closure_SYSV)
|
|||
stfd %f8, 104(%r1)
|
||||
#endif
|
||||
|
||||
# set up registers for the routine that actually does the work
|
||||
# get the context pointer from the trampoline
|
||||
mr %r3,%r11
|
||||
# pointer to the result storage
|
||||
addi %r6,%r1,112
|
||||
|
||||
# now load up the pointer to the result storage
|
||||
addi %r4,%r1,112
|
||||
# pointer to the saved gpr registers
|
||||
addi %r7,%r1,16
|
||||
|
||||
# now load up the pointer to the saved gpr registers
|
||||
addi %r5,%r1,16
|
||||
# pointer to the saved fpr registers
|
||||
addi %r8,%r1,48
|
||||
|
||||
# now load up the pointer to the saved fpr registers */
|
||||
addi %r6,%r1,48
|
||||
|
||||
# now load up the pointer to the outgoing parameter
|
||||
# stack in the previous frame
|
||||
# pointer to the outgoing parameter save area in the previous frame
|
||||
# i.e. the previous frame pointer + 8
|
||||
addi %r7,%r1,152
|
||||
addi %r9,%r1,152
|
||||
|
||||
# make the call
|
||||
bl ffi_closure_helper_SYSV@local
|
||||
|
@ -101,7 +108,6 @@ ENTRY(ffi_closure_SYSV)
|
|||
add %r3,%r3,%r4 # add contents of table to table address
|
||||
mtctr %r3
|
||||
bctr # jump to it
|
||||
.LFE1:
|
||||
|
||||
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
|
||||
|
@ -111,7 +117,9 @@ ENTRY(ffi_closure_SYSV)
|
|||
.Lret_type0:
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_INT
|
||||
|
@ -119,31 +127,33 @@ ENTRY(ffi_closure_SYSV)
|
|||
mtlr %r0
|
||||
.Lfinish:
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_FLOAT
|
||||
#ifndef __NO_FPRS__
|
||||
lfs %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
#else
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
#endif
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_DOUBLE
|
||||
#ifndef __NO_FPRS__
|
||||
lfd %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
#else
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
#endif
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
#ifndef __NO_FPRS__
|
||||
|
@ -152,10 +162,12 @@ ENTRY(ffi_closure_SYSV)
|
|||
mtlr %r0
|
||||
b .Lfinish
|
||||
#else
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
nop
|
||||
#endif
|
||||
|
||||
# case FFI_TYPE_UINT8
|
||||
|
@ -166,7 +178,9 @@ ENTRY(ffi_closure_SYSV)
|
|||
#endif
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_SINT8
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
|
@ -186,7 +200,9 @@ ENTRY(ffi_closure_SYSV)
|
|||
#endif
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_SINT16
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
|
@ -196,19 +212,25 @@ ENTRY(ffi_closure_SYSV)
|
|||
#endif
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_UINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_SINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_UINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
|
@ -225,14 +247,18 @@ ENTRY(ffi_closure_SYSV)
|
|||
# case FFI_TYPE_STRUCT
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_POINTER
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_TYPE_UINT128
|
||||
lwz %r3,112+0(%r1)
|
||||
|
@ -245,20 +271,26 @@ ENTRY(ffi_closure_SYSV)
|
|||
lbz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||
lhz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
#else
|
||||
srwi %r3,%r3,8
|
||||
mtlr %r0
|
||||
|
@ -269,7 +301,9 @@ ENTRY(ffi_closure_SYSV)
|
|||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
|
@ -319,64 +353,43 @@ ENTRY(ffi_closure_SYSV)
|
|||
or %r4,%r6,%r4
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
.cfi_def_cfa_offset 144
|
||||
#endif
|
||||
|
||||
.Luint128:
|
||||
lwz %r6,112+12(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
.cfi_def_cfa_offset 0
|
||||
blr
|
||||
|
||||
.cfi_endproc
|
||||
END(ffi_closure_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
#else
|
||||
.ascii "\0" # CIE Augmentation
|
||||
#endif
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -4 # CIE Data Alignment Factor
|
||||
.byte 0x41 # CIE RA Column
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
#endif
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.4byte .LFB1-. # FDE initial location
|
||||
#else
|
||||
.4byte .LFB1 # FDE initial location
|
||||
#endif
|
||||
.4byte .LFE1-.LFB1 # FDE address range
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x0 # Augmentation size
|
||||
#endif
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 144
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0x11 # DW_CFA_offset_extended_sf
|
||||
.uleb128 0x41
|
||||
.sleb128 -1
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
|
||||
FFI_HIDDEN(ffi_go_closure_sysv)
|
||||
ENTRY(ffi_go_closure_sysv)
|
||||
.cfi_startproc
|
||||
stwu %r1,-144(%r1)
|
||||
.cfi_def_cfa_offset 144
|
||||
mflr %r0
|
||||
stw %r0,148(%r1)
|
||||
.cfi_offset 65, 4
|
||||
|
||||
stw %r3, 16(%r1)
|
||||
stw %r4, 20(%r1)
|
||||
stw %r5, 24(%r1)
|
||||
|
||||
# closure->cif
|
||||
lwz %r3,4(%r11)
|
||||
# closure->fun
|
||||
lwz %r4,8(%r11)
|
||||
# user_data
|
||||
mr %r5,%r11
|
||||
b .Ldoclosure
|
||||
.cfi_endproc
|
||||
END(ffi_go_closure_sysv)
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
|
|
|
@ -31,34 +31,35 @@
|
|||
#include <powerpc/asm.h>
|
||||
|
||||
#ifndef POWERPC64
|
||||
.globl ffi_prep_args_SYSV
|
||||
FFI_HIDDEN(ffi_call_SYSV)
|
||||
ENTRY(ffi_call_SYSV)
|
||||
.LFB1:
|
||||
.cfi_startproc
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr %r8,%r1
|
||||
mr %r10,%r1
|
||||
.cfi_def_cfa_register 10
|
||||
|
||||
.LCFI0:
|
||||
/* Allocate the stack space we need. */
|
||||
stwux %r1,%r1,%r4
|
||||
stwux %r1,%r1,%r8
|
||||
/* Save registers we use. */
|
||||
mflr %r9
|
||||
stw %r28,-16(%r8)
|
||||
.LCFI1:
|
||||
stw %r29,-12(%r8)
|
||||
.LCFI2:
|
||||
stw %r30, -8(%r8)
|
||||
.LCFI3:
|
||||
stw %r31, -4(%r8)
|
||||
.LCFI4:
|
||||
stw %r9, 4(%r8)
|
||||
.LCFI5:
|
||||
stw %r28,-16(%r10)
|
||||
stw %r29,-12(%r10)
|
||||
stw %r30, -8(%r10)
|
||||
stw %r31, -4(%r10)
|
||||
stw %r9, 4(%r10)
|
||||
.cfi_offset 65, 4
|
||||
.cfi_offset 31, -4
|
||||
.cfi_offset 30, -8
|
||||
.cfi_offset 29, -12
|
||||
.cfi_offset 28, -16
|
||||
|
||||
/* Save arguments over call... */
|
||||
mr %r31,%r5 /* flags, */
|
||||
mr %r30,%r6 /* rvalue, */
|
||||
mr %r29,%r7 /* function address, */
|
||||
mr %r28,%r8 /* our AP. */
|
||||
.LCFI6:
|
||||
stw %r7, -20(%r10) /* closure, */
|
||||
mr %r31,%r6 /* flags, */
|
||||
mr %r30,%r5 /* rvalue, */
|
||||
mr %r29,%r4 /* function address, */
|
||||
mr %r28,%r10 /* our AP. */
|
||||
.cfi_def_cfa_register 28
|
||||
|
||||
/* Call ffi_prep_args_SYSV. */
|
||||
mr %r4,%r1
|
||||
|
@ -70,35 +71,36 @@ ENTRY(ffi_call_SYSV)
|
|||
/* Get the address to call into CTR. */
|
||||
mtctr %r29
|
||||
/* Load all those argument registers. */
|
||||
lwz %r3,-16-(8*4)(%r28)
|
||||
lwz %r4,-16-(7*4)(%r28)
|
||||
lwz %r5,-16-(6*4)(%r28)
|
||||
lwz %r6,-16-(5*4)(%r28)
|
||||
lwz %r3,-24-(8*4)(%r28)
|
||||
lwz %r4,-24-(7*4)(%r28)
|
||||
lwz %r5,-24-(6*4)(%r28)
|
||||
lwz %r6,-24-(5*4)(%r28)
|
||||
bf- 5,1f
|
||||
nop
|
||||
lwz %r7,-16-(4*4)(%r28)
|
||||
lwz %r8,-16-(3*4)(%r28)
|
||||
lwz %r9,-16-(2*4)(%r28)
|
||||
lwz %r10,-16-(1*4)(%r28)
|
||||
lwz %r7,-24-(4*4)(%r28)
|
||||
lwz %r8,-24-(3*4)(%r28)
|
||||
lwz %r9,-24-(2*4)(%r28)
|
||||
lwz %r10,-24-(1*4)(%r28)
|
||||
nop
|
||||
1:
|
||||
|
||||
#ifndef __NO_FPRS__
|
||||
/* Load all the FP registers. */
|
||||
bf- 6,2f
|
||||
lfd %f1,-16-(8*4)-(8*8)(%r28)
|
||||
lfd %f2,-16-(8*4)-(7*8)(%r28)
|
||||
lfd %f3,-16-(8*4)-(6*8)(%r28)
|
||||
lfd %f4,-16-(8*4)-(5*8)(%r28)
|
||||
lfd %f1,-24-(8*4)-(8*8)(%r28)
|
||||
lfd %f2,-24-(8*4)-(7*8)(%r28)
|
||||
lfd %f3,-24-(8*4)-(6*8)(%r28)
|
||||
lfd %f4,-24-(8*4)-(5*8)(%r28)
|
||||
nop
|
||||
lfd %f5,-16-(8*4)-(4*8)(%r28)
|
||||
lfd %f6,-16-(8*4)-(3*8)(%r28)
|
||||
lfd %f7,-16-(8*4)-(2*8)(%r28)
|
||||
lfd %f8,-16-(8*4)-(1*8)(%r28)
|
||||
lfd %f5,-24-(8*4)-(4*8)(%r28)
|
||||
lfd %f6,-24-(8*4)-(3*8)(%r28)
|
||||
lfd %f7,-24-(8*4)-(2*8)(%r28)
|
||||
lfd %f8,-24-(8*4)-(1*8)(%r28)
|
||||
#endif
|
||||
2:
|
||||
|
||||
/* Make the call. */
|
||||
lwz %r11, -20(%r28)
|
||||
bctrl
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
|
@ -125,11 +127,24 @@ L(done_return_value):
|
|||
lwz %r30, -8(%r28)
|
||||
lwz %r29,-12(%r28)
|
||||
lwz %r28,-16(%r28)
|
||||
.cfi_remember_state
|
||||
/* At this point we don't have a cfa register. Say all our
|
||||
saved regs have been restored. */
|
||||
.cfi_same_value 65
|
||||
.cfi_same_value 31
|
||||
.cfi_same_value 30
|
||||
.cfi_same_value 29
|
||||
.cfi_same_value 28
|
||||
/* Hopefully this works.. */
|
||||
.cfi_def_cfa_register 1
|
||||
.cfi_offset 1, 0
|
||||
lwz %r1,0(%r1)
|
||||
.cfi_same_value 1
|
||||
blr
|
||||
|
||||
#ifndef __NO_FPRS__
|
||||
L(fp_return_value):
|
||||
.cfi_restore_state
|
||||
bf 28,L(float_return_value)
|
||||
stfd %f1,0(%r30)
|
||||
mtcrf 0x02,%r31 /* cr6 */
|
||||
|
@ -150,70 +165,10 @@ L(small_struct_return_value):
|
|||
stw %r3, 0(%r30)
|
||||
stw %r4, 4(%r30)
|
||||
b L(done_return_value)
|
||||
.cfi_endproc
|
||||
|
||||
.LFE1:
|
||||
END(ffi_call_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||
.LSCIE1:
|
||||
.4byte 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
#else
|
||||
.ascii "\0" /* CIE Augmentation */
|
||||
#endif
|
||||
.uleb128 0x1 /* CIE Code Alignment Factor */
|
||||
.sleb128 -4 /* CIE Data Alignment Factor */
|
||||
.byte 0x41 /* CIE RA Column */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x1 /* Augmentation size */
|
||||
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
|
||||
#endif
|
||||
.byte 0xc /* DW_CFA_def_cfa */
|
||||
.uleb128 0x1
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 /* FDE Length */
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 /* FDE CIE offset */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.4byte .LFB1-. /* FDE initial location */
|
||||
#else
|
||||
.4byte .LFB1 /* FDE initial location */
|
||||
#endif
|
||||
.4byte .LFE1-.LFB1 /* FDE address range */
|
||||
#if defined _RELOCATABLE || defined __PIC__
|
||||
.uleb128 0x0 /* Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0x08
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI5-.LCFI0
|
||||
.byte 0x11 /* DW_CFA_offset_extended_sf */
|
||||
.uleb128 0x41
|
||||
.sleb128 -1
|
||||
.byte 0x9f /* DW_CFA_offset, column 0x1f */
|
||||
.uleb128 0x1
|
||||
.byte 0x9e /* DW_CFA_offset, column 0x1e */
|
||||
.uleb128 0x2
|
||||
.byte 0x9d /* DW_CFA_offset, column 0x1d */
|
||||
.uleb128 0x3
|
||||
.byte 0x9c /* DW_CFA_offset, column 0x1c */
|
||||
.uleb128 0x4
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFI6-.LCFI5
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.uleb128 0x1c
|
||||
.align 2
|
||||
.LEFDE1:
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -76,6 +76,13 @@ static ffi_status initialize_aggregate(ffi_type *arg)
|
|||
total size of 3*sizeof(long). */
|
||||
arg->size = ALIGN (arg->size, arg->alignment);
|
||||
|
||||
/* On some targets, the ABI defines that structures have an additional
|
||||
alignment beyond the "natural" one based on their elements. */
|
||||
#ifdef FFI_AGGREGATE_ALIGNMENT
|
||||
if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
|
||||
arg->alignment = FFI_AGGREGATE_ALIGNMENT;
|
||||
#endif
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
|
@ -111,13 +118,8 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
|
|||
FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
|
||||
FFI_ASSERT(nfixedargs <= ntotalargs);
|
||||
|
||||
#ifndef X86_WIN32
|
||||
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
|
||||
return FFI_BAD_ABI;
|
||||
#else
|
||||
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL))
|
||||
return FFI_BAD_ABI;
|
||||
#endif
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
|
@ -134,18 +136,25 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
|
|||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
if (rtype->type == FFI_TYPE_COMPLEX)
|
||||
abort();
|
||||
#endif
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT_VALID_TYPE(cif->rtype);
|
||||
|
||||
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
||||
#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
|
||||
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
#ifdef SPARC
|
||||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
#ifdef TILE
|
||||
&& (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
|
||||
#endif
|
||||
#ifdef XTENSA
|
||||
&& (cif->rtype->size > 16)
|
||||
#endif
|
||||
#ifdef NIOS2
|
||||
&& (cif->rtype->size > 8)
|
||||
#endif
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
|
@ -158,23 +167,19 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
|
|||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
if ((*ptr)->type == FFI_TYPE_COMPLEX)
|
||||
abort();
|
||||
#endif
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#if !defined X86_ANY && !defined S390 && !defined PA
|
||||
#ifdef SPARC
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
||||
&& cif->abi != FFI_V9))
|
||||
bytes += sizeof(void*);
|
||||
else
|
||||
#endif
|
||||
#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
{
|
||||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
#ifdef TILE
|
||||
if (bytes < 10 * FFI_SIZEOF_ARG &&
|
||||
|
@ -185,6 +190,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);
|
||||
}
|
||||
|
|
|
@ -88,6 +88,10 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
|||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
*args = (raw++)->ptr;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
@ -112,6 +116,11 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
if ((*tp)->type == FFI_TYPE_COMPLEX)
|
||||
{
|
||||
*args = (raw++)->ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
*args = (void*) raw;
|
||||
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
||||
|
@ -167,6 +176,10 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
|||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
(raw++)->ptr = *args;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2000, 2007 Software AG
|
||||
Copyright (c) 2008 Red Hat, Inc
|
||||
|
||||
|
||||
S390 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
|
||||
|
@ -11,10 +11,10 @@
|
|||
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.
|
||||
|
@ -27,24 +27,23 @@
|
|||
/* Includes */
|
||||
/* -------- */
|
||||
/*====================================================================*/
|
||||
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include "internal.h"
|
||||
|
||||
/*====================== End of Includes =============================*/
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
/* Defines */
|
||||
/* ------- */
|
||||
/*====================================================================*/
|
||||
|
||||
/* Maximum number of GPRs available for argument passing. */
|
||||
/* Maximum number of GPRs available for argument passing. */
|
||||
#define MAX_GPRARGS 5
|
||||
|
||||
/* Maximum number of FPRs available for argument passing. */
|
||||
/* Maximum number of FPRs available for argument passing. */
|
||||
#ifdef __s390x__
|
||||
#define MAX_FPRARGS 4
|
||||
#else
|
||||
|
@ -54,47 +53,30 @@
|
|||
/* Round to multiple of 16. */
|
||||
#define ROUND_SIZE(size) (((size) + 15) & ~15)
|
||||
|
||||
/* If these values change, sysv.S must be adapted! */
|
||||
#define FFI390_RET_VOID 0
|
||||
#define FFI390_RET_STRUCT 1
|
||||
#define FFI390_RET_FLOAT 2
|
||||
#define FFI390_RET_DOUBLE 3
|
||||
#define FFI390_RET_INT32 4
|
||||
#define FFI390_RET_INT64 5
|
||||
|
||||
/*===================== End of Defines ===============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Prototypes */
|
||||
/* ---------- */
|
||||
/*====================================================================*/
|
||||
|
||||
static void ffi_prep_args (unsigned char *, extended_cif *);
|
||||
void
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
|
||||
__attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
ffi_closure_helper_SYSV (ffi_closure *, unsigned long *,
|
||||
unsigned long long *, unsigned long *);
|
||||
|
||||
/*====================== End of Prototypes ===========================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* Externals */
|
||||
/* --------- */
|
||||
/*====================================================================*/
|
||||
|
||||
extern void ffi_call_SYSV(unsigned,
|
||||
extended_cif *,
|
||||
void (*)(unsigned char *, extended_cif *),
|
||||
unsigned,
|
||||
void *,
|
||||
void (*fn)(void));
|
||||
|
||||
struct call_frame
|
||||
{
|
||||
void *back_chain;
|
||||
void *eos;
|
||||
unsigned long gpr_args[5];
|
||||
unsigned long gpr_save[9];
|
||||
unsigned long long fpr_args[4];
|
||||
};
|
||||
|
||||
extern void FFI_HIDDEN ffi_call_SYSV(struct call_frame *, unsigned, void *,
|
||||
void (*fn)(void), void *);
|
||||
|
||||
extern void ffi_closure_SYSV(void);
|
||||
|
||||
extern void ffi_go_closure_SYSV(void);
|
||||
|
||||
/*====================== End of Externals ============================*/
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_check_struct_type. */
|
||||
|
@ -103,7 +85,7 @@ extern void ffi_closure_SYSV(void);
|
|||
/* general purpose or floating point register. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
|
||||
static int
|
||||
ffi_check_struct_type (ffi_type *arg)
|
||||
{
|
||||
|
@ -111,7 +93,7 @@ ffi_check_struct_type (ffi_type *arg)
|
|||
|
||||
/* If the struct has just one element, look at that element
|
||||
to find out whether to consider the struct as floating point. */
|
||||
while (arg->type == FFI_TYPE_STRUCT
|
||||
while (arg->type == FFI_TYPE_STRUCT
|
||||
&& arg->elements[0] && !arg->elements[1])
|
||||
arg = arg->elements[0];
|
||||
|
||||
|
@ -144,190 +126,9 @@ ffi_check_struct_type (ffi_type *arg)
|
|||
/* Other structs are passed via a pointer to the data. */
|
||||
return FFI_TYPE_POINTER;
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_args. */
|
||||
/* */
|
||||
/* Function - Prepare parameters for call to function. */
|
||||
/* */
|
||||
/* ffi_prep_args is called by the assembly routine once stack space */
|
||||
/* has been allocated for the function's arguments. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
static void
|
||||
ffi_prep_args (unsigned char *stack, extended_cif *ecif)
|
||||
{
|
||||
/* The stack space will be filled with those areas:
|
||||
|
||||
FPR argument register save area (highest addresses)
|
||||
GPR argument register save area
|
||||
temporary struct copies
|
||||
overflow argument area (lowest addresses)
|
||||
|
||||
We set up the following pointers:
|
||||
|
||||
p_fpr: bottom of the FPR area (growing upwards)
|
||||
p_gpr: bottom of the GPR area (growing upwards)
|
||||
p_ov: bottom of the overflow area (growing upwards)
|
||||
p_struct: top of the struct copy area (growing downwards)
|
||||
|
||||
All areas are kept aligned to twice the word size. */
|
||||
|
||||
int gpr_off = ecif->cif->bytes;
|
||||
int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
|
||||
|
||||
unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
|
||||
unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
|
||||
unsigned char *p_struct = (unsigned char *)p_gpr;
|
||||
unsigned long *p_ov = (unsigned long *)stack;
|
||||
|
||||
int n_fpr = 0;
|
||||
int n_gpr = 0;
|
||||
int n_ov = 0;
|
||||
|
||||
ffi_type **ptr;
|
||||
void **p_argv = ecif->avalue;
|
||||
int i;
|
||||
|
||||
/* If we returning a structure then we set the first parameter register
|
||||
to the address of where we are returning this structure. */
|
||||
|
||||
if (ecif->cif->flags == FFI390_RET_STRUCT)
|
||||
p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
|
||||
|
||||
/* Now for the arguments. */
|
||||
|
||||
for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
|
||||
i > 0;
|
||||
i--, ptr++, p_argv++)
|
||||
{
|
||||
void *arg = *p_argv;
|
||||
int type = (*ptr)->type;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
/* 16-byte long double is passed like a struct. */
|
||||
if (type == FFI_TYPE_LONGDOUBLE)
|
||||
type = FFI_TYPE_STRUCT;
|
||||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, copy the data. */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
{
|
||||
p_struct -= ROUND_SIZE ((*ptr)->size);
|
||||
memcpy (p_struct, (char *)arg, (*ptr)->size);
|
||||
arg = &p_struct;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now handle all primitive int/pointer/float data types. */
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
p_fpr[n_fpr++] = *(unsigned long long *) arg;
|
||||
else
|
||||
#ifdef __s390x__
|
||||
p_ov[n_ov++] = *(unsigned long *) arg;
|
||||
#else
|
||||
p_ov[n_ov++] = ((unsigned long *) arg)[0],
|
||||
p_ov[n_ov++] = ((unsigned long *) arg)[1];
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned int *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
|
||||
else
|
||||
p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
#ifdef __s390x__
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(unsigned long *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned long *) arg;
|
||||
#else
|
||||
if (n_gpr == MAX_GPRARGS-1)
|
||||
n_gpr = MAX_GPRARGS;
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
|
||||
p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
|
||||
else
|
||||
p_ov[n_ov++] = ((unsigned long *) arg)[0],
|
||||
p_ov[n_ov++] = ((unsigned long *) arg)[1];
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(unsigned int *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned int *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(signed int *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(signed int *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(unsigned short *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned short *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(signed short *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(signed short *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(unsigned char *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(unsigned char *) arg;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = *(signed char *) arg;
|
||||
else
|
||||
p_ov[n_ov++] = *(signed char *) arg;
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_cif_machdep. */
|
||||
|
@ -335,8 +136,8 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif)
|
|||
/* Function - Perform machine dependent CIF processing. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
ffi_status
|
||||
|
||||
ffi_status FFI_HIDDEN
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
size_t struct_size = 0;
|
||||
|
@ -347,7 +148,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
ffi_type **ptr;
|
||||
int i;
|
||||
|
||||
/* Determine return value handling. */
|
||||
/* Determine return value handling. */
|
||||
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
|
@ -356,11 +157,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
cif->flags = FFI390_RET_VOID;
|
||||
break;
|
||||
|
||||
/* Structures are returned via a hidden pointer. */
|
||||
/* Structures and complex are returned via a hidden pointer. */
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_COMPLEX:
|
||||
cif->flags = FFI390_RET_STRUCT;
|
||||
n_gpr++; /* We need one GPR to pass the pointer. */
|
||||
break;
|
||||
break;
|
||||
|
||||
/* Floating point values are returned in fpr 0. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
|
@ -399,14 +201,14 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
cif->flags = FFI390_RET_INT32;
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now for the arguments. */
|
||||
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs;
|
||||
i > 0;
|
||||
i--, ptr++)
|
||||
|
@ -420,9 +222,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
if (type == FFI_TYPE_COMPLEX)
|
||||
type = FFI_TYPE_POINTER;
|
||||
else
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, we must reserve space
|
||||
to copy its data for proper call-by-value semantics. */
|
||||
|
@ -431,7 +236,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
}
|
||||
|
||||
/* Now handle all primitive int/float data types. */
|
||||
switch (type)
|
||||
switch (type)
|
||||
{
|
||||
/* The first MAX_FPRARGS floating point arguments
|
||||
go in FPRs, the rest overflow to the stack. */
|
||||
|
@ -442,7 +247,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
else
|
||||
n_ov += sizeof (double) / sizeof (long);
|
||||
break;
|
||||
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
n_fpr++;
|
||||
|
@ -452,9 +257,9 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
|
||||
/* On 31-bit machines, 64-bit integers are passed in GPR pairs,
|
||||
if one is still available, or else on the stack. If only one
|
||||
register is free, skip the register (it won't be used for any
|
||||
register is free, skip the register (it won't be used for any
|
||||
subsequent argument either). */
|
||||
|
||||
|
||||
#ifndef __s390x__
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
|
@ -470,7 +275,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
/* Everything else is passed in GPRs (until MAX_GPRARGS
|
||||
have been used) or overflows to the stack. */
|
||||
|
||||
default:
|
||||
default:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
n_gpr++;
|
||||
else
|
||||
|
@ -483,12 +288,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
and temporary structure copies. */
|
||||
|
||||
cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
|
||||
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_call. */
|
||||
|
@ -496,42 +301,195 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
/* Function - Call the FFI routine. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
void **avalue)
|
||||
|
||||
static void
|
||||
ffi_call_int(ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
void **avalue,
|
||||
void *closure)
|
||||
{
|
||||
int ret_type = cif->flags;
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
ecif.rvalue = rvalue;
|
||||
size_t rsize = 0, bytes = cif->bytes;
|
||||
unsigned char *stack, *p_struct;
|
||||
struct call_frame *frame;
|
||||
unsigned long *p_ov, *p_gpr;
|
||||
unsigned long long *p_fpr;
|
||||
int n_fpr, n_gpr, n_ov, i, n;
|
||||
ffi_type **arg_types;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
/* If we don't have a return value, we need to fake one. */
|
||||
if (rvalue == NULL)
|
||||
{
|
||||
if (ret_type == FFI390_RET_STRUCT)
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
if (ret_type & FFI390_RET_IN_MEM)
|
||||
rsize = cif->rtype->size;
|
||||
else
|
||||
ret_type = FFI390_RET_VOID;
|
||||
}
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
|
||||
ret_type, ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* The stack space will be filled with those areas:
|
||||
|
||||
dummy structure return (highest addresses)
|
||||
FPR argument register save area
|
||||
GPR argument register save area
|
||||
stack frame for ffi_call_SYSV
|
||||
temporary struct copies
|
||||
overflow argument area (lowest addresses)
|
||||
|
||||
We set up the following pointers:
|
||||
|
||||
p_fpr: bottom of the FPR area (growing upwards)
|
||||
p_gpr: bottom of the GPR area (growing upwards)
|
||||
p_ov: bottom of the overflow area (growing upwards)
|
||||
p_struct: top of the struct copy area (growing downwards)
|
||||
|
||||
All areas are kept aligned to twice the word size.
|
||||
|
||||
Note that we're going to create the stack frame for both
|
||||
ffi_call_SYSV _and_ the target function right here. This
|
||||
works because we don't make any function calls with more
|
||||
than 5 arguments (indeed only memcpy and ffi_call_SYSV),
|
||||
and thus we don't have any stacked outgoing parameters. */
|
||||
|
||||
stack = alloca (bytes + sizeof(struct call_frame) + rsize);
|
||||
frame = (struct call_frame *)(stack + bytes);
|
||||
if (rsize)
|
||||
rvalue = frame + 1;
|
||||
|
||||
/* Link the new frame back to the one from this function. */
|
||||
frame->back_chain = __builtin_frame_address (0);
|
||||
|
||||
/* Fill in all of the argument stuff. */
|
||||
p_ov = (unsigned long *)stack;
|
||||
p_struct = (unsigned char *)frame;
|
||||
p_gpr = frame->gpr_args;
|
||||
p_fpr = frame->fpr_args;
|
||||
n_fpr = n_gpr = n_ov = 0;
|
||||
|
||||
/* If we returning a structure then we set the first parameter register
|
||||
to the address of where we are returning this structure. */
|
||||
if (cif->flags & FFI390_RET_IN_MEM)
|
||||
p_gpr[n_gpr++] = (uintptr_t) rvalue;
|
||||
|
||||
/* Now for the arguments. */
|
||||
arg_types = cif->arg_types;
|
||||
for (i = 0, n = cif->nargs; i < n; ++i)
|
||||
{
|
||||
ffi_type *ty = arg_types[i];
|
||||
void *arg = avalue[i];
|
||||
int type = ty->type;
|
||||
ffi_arg val;
|
||||
|
||||
restart:
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
val = *(SINT8 *)arg;
|
||||
goto do_int;
|
||||
case FFI_TYPE_UINT8:
|
||||
val = *(UINT8 *)arg;
|
||||
goto do_int;
|
||||
case FFI_TYPE_SINT16:
|
||||
val = *(SINT16 *)arg;
|
||||
goto do_int;
|
||||
case FFI_TYPE_UINT16:
|
||||
val = *(UINT16 *)arg;
|
||||
goto do_int;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
val = *(SINT32 *)arg;
|
||||
goto do_int;
|
||||
case FFI_TYPE_UINT32:
|
||||
val = *(UINT32 *)arg;
|
||||
goto do_int;
|
||||
case FFI_TYPE_POINTER:
|
||||
val = *(uintptr_t *)arg;
|
||||
do_int:
|
||||
*(n_gpr < MAX_GPRARGS ? p_gpr + n_gpr++ : p_ov + n_ov++) = val;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
#ifdef __s390x__
|
||||
val = *(UINT64 *)arg;
|
||||
goto do_int;
|
||||
#else
|
||||
if (n_gpr == MAX_GPRARGS-1)
|
||||
n_gpr = MAX_GPRARGS;
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
p_gpr[n_gpr++] = ((UINT32 *) arg)[0],
|
||||
p_gpr[n_gpr++] = ((UINT32 *) arg)[1];
|
||||
else
|
||||
p_ov[n_ov++] = ((UINT32 *) arg)[0],
|
||||
p_ov[n_ov++] = ((UINT32 *) arg)[1];
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
p_fpr[n_fpr++] = *(UINT64 *) arg;
|
||||
else
|
||||
{
|
||||
#ifdef __s390x__
|
||||
p_ov[n_ov++] = *(UINT64 *) arg;
|
||||
#else
|
||||
p_ov[n_ov++] = ((UINT32 *) arg)[0],
|
||||
p_ov[n_ov++] = ((UINT32 *) arg)[1];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
val = *(UINT32 *)arg;
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
p_fpr[n_fpr++] = (UINT64)val << 32;
|
||||
else
|
||||
p_ov[n_ov++] = val;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Check how a structure type is passed. */
|
||||
type = ffi_check_struct_type (ty);
|
||||
/* Some structures are passed via a type they contain. */
|
||||
if (type != FFI_TYPE_POINTER)
|
||||
goto restart;
|
||||
/* ... otherwise, passed by reference. fallthru. */
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* 16-byte long double is passed via reference. */
|
||||
#endif
|
||||
case FFI_TYPE_COMPLEX:
|
||||
/* Complex types are passed via reference. */
|
||||
p_struct -= ROUND_SIZE (ty->size);
|
||||
memcpy (p_struct, arg, ty->size);
|
||||
val = (uintptr_t)p_struct;
|
||||
goto do_int;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ffi_call_SYSV (frame, ret_type & FFI360_RET_MASK, rvalue, fn, closure);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
ffi_call_int(cif, fn, rvalue, avalue, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, void *closure)
|
||||
{
|
||||
ffi_call_int(cif, fn, rvalue, avalue, closure);
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
|
@ -541,9 +499,11 @@ ffi_call(ffi_cif *cif,
|
|||
/* Function - Call a FFI closure target function. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
void
|
||||
ffi_closure_helper_SYSV (ffi_closure *closure,
|
||||
|
||||
void FFI_HIDDEN
|
||||
ffi_closure_helper_SYSV (ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
unsigned long *p_gpr,
|
||||
unsigned long long *p_fpr,
|
||||
unsigned long *p_ov)
|
||||
|
@ -562,21 +522,16 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
int i;
|
||||
|
||||
/* Allocate buffer for argument list pointers. */
|
||||
p_arg = avalue = alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
|
||||
|
||||
/* If we returning a structure, pass the structure address
|
||||
directly to the target function. Otherwise, have the target
|
||||
/* If we returning a structure, pass the structure address
|
||||
directly to the target function. Otherwise, have the target
|
||||
function store the return value to the GPR save area. */
|
||||
|
||||
if (closure->cif->flags == FFI390_RET_STRUCT)
|
||||
if (cif->flags & FFI390_RET_IN_MEM)
|
||||
rvalue = (void *) p_gpr[n_gpr++];
|
||||
|
||||
/* Now for the arguments. */
|
||||
|
||||
for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
|
||||
i > 0;
|
||||
i--, p_arg++, ptr++)
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, p_arg++, ptr++)
|
||||
{
|
||||
int deref_struct_pointer = 0;
|
||||
int type = (*ptr)->type;
|
||||
|
@ -588,11 +543,14 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
|
||||
{
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
if (type == FFI_TYPE_COMPLEX)
|
||||
type = FFI_TYPE_POINTER;
|
||||
else
|
||||
type = ffi_check_struct_type (*ptr);
|
||||
|
||||
/* If we pass the struct via pointer, remember to
|
||||
/* If we pass the struct via pointer, remember to
|
||||
retrieve the pointer later. */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
deref_struct_pointer = 1;
|
||||
|
@ -600,30 +558,32 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
|
||||
/* Pointers are passed like UINTs of the same size. */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
{
|
||||
#ifdef __s390x__
|
||||
type = FFI_TYPE_UINT64;
|
||||
type = FFI_TYPE_UINT64;
|
||||
#else
|
||||
type = FFI_TYPE_UINT32;
|
||||
type = FFI_TYPE_UINT32;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Now handle all primitive int/float data types. */
|
||||
switch (type)
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
*p_arg = &p_fpr[n_fpr++];
|
||||
else
|
||||
*p_arg = &p_ov[n_ov],
|
||||
*p_arg = &p_ov[n_ov],
|
||||
n_ov += sizeof (double) / sizeof (long);
|
||||
break;
|
||||
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (n_fpr < MAX_FPRARGS)
|
||||
*p_arg = &p_fpr[n_fpr++];
|
||||
else
|
||||
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
|
||||
break;
|
||||
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
#ifdef __s390x__
|
||||
|
@ -640,7 +600,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
*p_arg = &p_ov[n_ov], n_ov += 2;
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
|
@ -649,7 +609,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
else
|
||||
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
|
||||
break;
|
||||
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
if (n_gpr < MAX_GPRARGS)
|
||||
|
@ -665,7 +625,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
else
|
||||
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
break;
|
||||
|
@ -679,14 +639,15 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
|
||||
|
||||
/* Call the target function. */
|
||||
(closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
|
||||
(fun) (cif, rvalue, avalue, user_data);
|
||||
|
||||
/* Convert the return value. */
|
||||
switch (closure->cif->rtype->type)
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
/* Void is easy, and so is struct. */
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_COMPLEX:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
|
@ -732,7 +693,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
/*====================================================================*/
|
||||
|
@ -742,7 +703,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
/* Function - Prepare a FFI closure. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
|
@ -750,32 +711,46 @@ ffi_prep_closure_loc (ffi_closure *closure,
|
|||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
static unsigned short const template[] = {
|
||||
0x0d10, /* basr %r1,0 */
|
||||
#ifndef __s390x__
|
||||
0x9801, 0x1006, /* lm %r0,%r1,6(%r1) */
|
||||
#else
|
||||
0xeb01, 0x100e, 0x0004, /* lmg %r0,%r1,14(%r1) */
|
||||
#endif
|
||||
0x07f1 /* br %r1 */
|
||||
};
|
||||
|
||||
unsigned long *tramp = (unsigned long *)&closure->tramp;
|
||||
|
||||
if (cif->abi != FFI_SYSV)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
#ifndef __s390x__
|
||||
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
|
||||
*(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
|
||||
*(short *)&closure->tramp [4] = 0x1006;
|
||||
*(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
|
||||
*(long *)&closure->tramp [8] = (long)codeloc;
|
||||
*(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
|
||||
#else
|
||||
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
|
||||
*(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
|
||||
*(short *)&closure->tramp [4] = 0x100e;
|
||||
*(short *)&closure->tramp [6] = 0x0004;
|
||||
*(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
|
||||
*(long *)&closure->tramp[16] = (long)codeloc;
|
||||
*(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
|
||||
#endif
|
||||
|
||||
memcpy (tramp, template, sizeof(template));
|
||||
tramp[2] = (unsigned long)codeloc;
|
||||
tramp[3] = (unsigned long)&ffi_closure_SYSV;
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
closure->user_data = user_data;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*======================== End of Routine ============================*/
|
||||
|
||||
|
||||
/* Build a Go language closure. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*))
|
||||
{
|
||||
if (cif->abi != FFI_SYSV)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
closure->tramp = ffi_go_closure_SYSV;
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
|
|
@ -52,10 +52,13 @@ typedef enum ffi_abi {
|
|||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
|
||||
#define FFI_TARGET_HAS_COMPLEX_TYPE
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_GO_CLOSURES 1
|
||||
#ifdef S390X
|
||||
#define FFI_TRAMPOLINE_SIZE 32
|
||||
#else
|
||||
|
|
11
libffi/src/s390/internal.h
Normal file
11
libffi/src/s390/internal.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* If these values change, sysv.S must be adapted! */
|
||||
#define FFI390_RET_DOUBLE 0
|
||||
#define FFI390_RET_FLOAT 1
|
||||
#define FFI390_RET_INT64 2
|
||||
#define FFI390_RET_INT32 3
|
||||
#define FFI390_RET_VOID 4
|
||||
|
||||
#define FFI360_RET_MASK 7
|
||||
#define FFI390_RET_IN_MEM 8
|
||||
|
||||
#define FFI390_RET_STRUCT (FFI390_RET_VOID | FFI390_RET_IN_MEM)
|
|
@ -1,9 +1,9 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2000 Software AG
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
|
||||
S390 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
|
||||
|
@ -11,10 +11,10 @@
|
|||
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
|
||||
|
@ -29,405 +29,296 @@
|
|||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifndef __s390x__
|
||||
|
||||
.text
|
||||
.text
|
||||
|
||||
#ifndef __s390x__
|
||||
|
||||
# r2: frame
|
||||
# r3: ret_type
|
||||
# r4: ret_addr
|
||||
# r5: fun
|
||||
# r6: closure
|
||||
|
||||
# r2: cif->bytes
|
||||
# r3: &ecif
|
||||
# r4: ffi_prep_args
|
||||
# r5: ret_type
|
||||
# r6: ecif.rvalue
|
||||
# ov: fn
|
||||
|
||||
# This assumes we are using gas.
|
||||
.balign 8
|
||||
.globl ffi_call_SYSV
|
||||
FFI_HIDDEN(ffi_call_SYSV)
|
||||
.type ffi_call_SYSV,%function
|
||||
ffi_call_SYSV:
|
||||
.LFB1:
|
||||
stm %r6,%r15,24(%r15) # Save registers
|
||||
.LCFI0:
|
||||
basr %r13,0 # Set up base register
|
||||
.Lbase:
|
||||
lr %r11,%r15 # Set up frame pointer
|
||||
.LCFI1:
|
||||
sr %r15,%r2
|
||||
ahi %r15,-96-48 # Allocate stack
|
||||
lr %r8,%r6 # Save ecif.rvalue
|
||||
sr %r9,%r9
|
||||
ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address
|
||||
l %r7,96(%r11) # Load function address
|
||||
st %r11,0(%r15) # Set up back chain
|
||||
ahi %r11,-48 # Register save area
|
||||
.LCFI2:
|
||||
.cfi_startproc
|
||||
st %r6,44(%r2) # Save registers
|
||||
stm %r12,%r14,48(%r2)
|
||||
lr %r13,%r2 # Install frame pointer
|
||||
.cfi_rel_offset r6, 44
|
||||
.cfi_rel_offset r12, 48
|
||||
.cfi_rel_offset r13, 52
|
||||
.cfi_rel_offset r14, 56
|
||||
.cfi_def_cfa_register r13
|
||||
st %r2,0(%r15) # Set up back chain
|
||||
sla %r3,3 # ret_type *= 8
|
||||
lr %r12,%r4 # Save ret_addr
|
||||
lr %r1,%r5 # Save fun
|
||||
lr %r0,%r6 # Install static chain
|
||||
|
||||
la %r2,96(%r15) # Save area
|
||||
# r3 already holds &ecif
|
||||
basr %r14,%r4 # Call ffi_prep_args
|
||||
# Set return address, so that there is only one indirect jump.
|
||||
#ifdef HAVE_AS_S390_ZARCH
|
||||
larl %r14,.Ltable
|
||||
ar %r14,%r3
|
||||
#else
|
||||
basr %r14,0
|
||||
0: la %r14,.Ltable-0b(%r14,%r3)
|
||||
#endif
|
||||
|
||||
lm %r2,%r6,0(%r11) # Load arguments
|
||||
ld %f0,32(%r11)
|
||||
ld %f2,40(%r11)
|
||||
la %r14,0(%r13,%r9) # Set return address
|
||||
br %r7 # ... and call function
|
||||
lm %r2,%r6,8(%r13) # Load arguments
|
||||
ld %f0,64(%r13)
|
||||
ld %f2,72(%r13)
|
||||
br %r1 # ... and call function
|
||||
|
||||
.LretNone: # Return void
|
||||
l %r4,48+56(%r11)
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.LretFloat:
|
||||
l %r4,48+56(%r11)
|
||||
ste %f0,0(%r8) # Return float
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.LretDouble:
|
||||
l %r4,48+56(%r11)
|
||||
std %f0,0(%r8) # Return double
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.LretInt32:
|
||||
l %r4,48+56(%r11)
|
||||
st %r2,0(%r8) # Return int
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.LretInt64:
|
||||
l %r4,48+56(%r11)
|
||||
stm %r2,%r3,0(%r8) # Return long long
|
||||
lm %r6,%r15,48+24(%r11)
|
||||
br %r4
|
||||
|
||||
.balign 8
|
||||
.Ltable:
|
||||
.byte .LretNone-.Lbase # FFI390_RET_VOID
|
||||
.byte .LretNone-.Lbase # FFI390_RET_STRUCT
|
||||
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT
|
||||
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
|
||||
.byte .LretInt32-.Lbase # FFI390_RET_INT32
|
||||
.byte .LretInt64-.Lbase # FFI390_RET_INT64
|
||||
# FFI390_RET_DOUBLE
|
||||
std %f0,0(%r12)
|
||||
j .Ldone
|
||||
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
.balign 8
|
||||
# FFI390_RET_FLOAT
|
||||
ste %f0,0(%r12)
|
||||
j .Ldone
|
||||
|
||||
.balign 8
|
||||
# FFI390_RET_INT64
|
||||
st %r3,4(%r12)
|
||||
nop
|
||||
# fallthru
|
||||
|
||||
.balign 8
|
||||
# FFI390_RET_INT32
|
||||
st %r2,0(%r12)
|
||||
nop
|
||||
# fallthru
|
||||
|
||||
.balign 8
|
||||
# FFI390_RET_VOID
|
||||
.Ldone:
|
||||
l %r14,56(%r13)
|
||||
l %r12,48(%r13)
|
||||
l %r6,44(%r13)
|
||||
l %r13,52(%r13)
|
||||
.cfi_restore 14
|
||||
.cfi_restore 13
|
||||
.cfi_restore 12
|
||||
.cfi_restore 6
|
||||
.cfi_def_cfa r15, 96
|
||||
br %r14
|
||||
.cfi_endproc
|
||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
||||
|
||||
|
||||
.balign 8
|
||||
.globl ffi_go_closure_SYSV
|
||||
FFI_HIDDEN(ffi_go_closure_SYSV)
|
||||
.type ffi_go_closure_SYSV,%function
|
||||
ffi_go_closure_SYSV:
|
||||
.cfi_startproc
|
||||
stm %r2,%r6,8(%r15) # Save arguments
|
||||
lr %r4,%r0 # Load closure -> user_data
|
||||
l %r2,4(%r4) # ->cif
|
||||
l %r3,8(%r4) # ->fun
|
||||
j .Ldoclosure
|
||||
.cfi_endproc
|
||||
|
||||
.balign 8
|
||||
.globl ffi_closure_SYSV
|
||||
FFI_HIDDEN(ffi_closure_SYSV)
|
||||
.type ffi_closure_SYSV,%function
|
||||
ffi_closure_SYSV:
|
||||
.LFB2:
|
||||
.cfi_startproc
|
||||
stm %r2,%r6,8(%r15) # Save arguments
|
||||
lr %r4,%r0 # Closure
|
||||
l %r2,16(%r4) # ->cif
|
||||
l %r3,20(%r4) # ->fun
|
||||
l %r4,24(%r4) # ->user_data
|
||||
.Ldoclosure:
|
||||
stm %r12,%r15,48(%r15) # Save registers
|
||||
.LCFI10:
|
||||
lr %r12,%r15
|
||||
.cfi_def_cfa_register r12
|
||||
.cfi_rel_offset r6, 24
|
||||
.cfi_rel_offset r12, 48
|
||||
.cfi_rel_offset r13, 52
|
||||
.cfi_rel_offset r14, 56
|
||||
.cfi_rel_offset r15, 60
|
||||
#ifndef HAVE_AS_S390_ZARCH
|
||||
basr %r13,0 # Set up base register
|
||||
.Lcbase:
|
||||
stm %r2,%r6,8(%r15) # Save arguments
|
||||
std %f0,64(%r15)
|
||||
std %f2,72(%r15)
|
||||
lr %r1,%r15 # Set up stack frame
|
||||
ahi %r15,-96
|
||||
.LCFI11:
|
||||
l %r12,.Lchelper-.Lcbase(%r13) # Get helper function
|
||||
lr %r2,%r0 # Closure
|
||||
la %r3,8(%r1) # GPRs
|
||||
la %r4,64(%r1) # FPRs
|
||||
la %r5,96(%r1) # Overflow
|
||||
st %r1,0(%r15) # Set up back chain
|
||||
l %r1,.Lchelper-.Lcbase(%r13) # Get helper function
|
||||
#endif
|
||||
ahi %r15,-96-8 # Set up stack frame
|
||||
st %r12,0(%r15) # Set up back chain
|
||||
|
||||
bas %r14,0(%r12,%r13) # Call helper
|
||||
std %f0,64(%r12) # Save fp arguments
|
||||
std %f2,72(%r12)
|
||||
|
||||
l %r4,96+56(%r15)
|
||||
ld %f0,96+64(%r15) # Load return registers
|
||||
lm %r2,%r3,96+8(%r15)
|
||||
lm %r12,%r15,96+48(%r15)
|
||||
br %r4
|
||||
la %r5,96(%r12) # Overflow
|
||||
st %r5,96(%r15)
|
||||
la %r6,64(%r12) # FPRs
|
||||
la %r5,8(%r12) # GPRs
|
||||
#ifdef HAVE_AS_S390_ZARCH
|
||||
brasl %r14,ffi_closure_helper_SYSV
|
||||
#else
|
||||
bas %r14,0(%r1,%r13) # Call helper
|
||||
#endif
|
||||
|
||||
lr %r15,%r12
|
||||
.cfi_def_cfa_register r15
|
||||
lm %r12,%r14,48(%r12) # Restore saved registers
|
||||
l %r6,24(%r15)
|
||||
ld %f0,64(%r15) # Load return registers
|
||||
lm %r2,%r3,8(%r15)
|
||||
br %r14
|
||||
.cfi_endproc
|
||||
|
||||
#ifndef HAVE_AS_S390_ZARCH
|
||||
.align 4
|
||||
.Lchelper:
|
||||
.long ffi_closure_helper_SYSV-.Lcbase
|
||||
#endif
|
||||
|
||||
.LFE2:
|
||||
|
||||
.ffi_closure_SYSV_end:
|
||||
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
|
||||
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -4 # CIE Data Alignment Factor
|
||||
.byte 0xe # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0xf
|
||||
.uleb128 0x60
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.4byte .LFB1-. # FDE initial location
|
||||
.4byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.uleb128 0x9
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.uleb128 0xa
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.uleb128 0xb
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.uleb128 0xc
|
||||
.byte 0x8b # DW_CFA_offset, column 0xb
|
||||
.uleb128 0xd
|
||||
.byte 0x8a # DW_CFA_offset, column 0xa
|
||||
.uleb128 0xe
|
||||
.byte 0x89 # DW_CFA_offset, column 0x9
|
||||
.uleb128 0xf
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.uleb128 0x10
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.uleb128 0x11
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.uleb128 0x12
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0xb
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI2-.LCFI1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x90
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
.LSFDE2:
|
||||
.4byte .LEFDE2-.LASFDE2 # FDE Length
|
||||
.LASFDE2:
|
||||
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
|
||||
.4byte .LFB2-. # FDE initial location
|
||||
.4byte .LFE2-.LFB2 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI10-.LFB2
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.uleb128 0x9
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.uleb128 0xa
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.uleb128 0xb
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.uleb128 0xc
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI11-.LCFI10
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0xc0
|
||||
.align 4
|
||||
.LEFDE2:
|
||||
.size ffi_closure_SYSV,.-ffi_closure_SYSV
|
||||
|
||||
#else
|
||||
|
||||
.text
|
||||
|
||||
# r2: cif->bytes
|
||||
# r3: &ecif
|
||||
# r4: ffi_prep_args
|
||||
# r5: ret_type
|
||||
# r6: ecif.rvalue
|
||||
# ov: fn
|
||||
|
||||
|
||||
# r2: frame
|
||||
# r3: ret_type
|
||||
# r4: ret_addr
|
||||
# r5: fun
|
||||
# r6: closure
|
||||
|
||||
# This assumes we are using gas.
|
||||
.balign 8
|
||||
.globl ffi_call_SYSV
|
||||
FFI_HIDDEN(ffi_call_SYSV)
|
||||
.type ffi_call_SYSV,%function
|
||||
ffi_call_SYSV:
|
||||
.LFB1:
|
||||
stmg %r6,%r15,48(%r15) # Save registers
|
||||
.LCFI0:
|
||||
larl %r13,.Lbase # Set up base register
|
||||
lgr %r11,%r15 # Set up frame pointer
|
||||
.LCFI1:
|
||||
sgr %r15,%r2
|
||||
aghi %r15,-160-80 # Allocate stack
|
||||
lgr %r8,%r6 # Save ecif.rvalue
|
||||
llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address
|
||||
lg %r7,160(%r11) # Load function address
|
||||
stg %r11,0(%r15) # Set up back chain
|
||||
aghi %r11,-80 # Register save area
|
||||
.LCFI2:
|
||||
.cfi_startproc
|
||||
stg %r6,88(%r2) # Save registers
|
||||
stmg %r12,%r14,96(%r2)
|
||||
lgr %r13,%r2 # Install frame pointer
|
||||
.cfi_rel_offset r6, 88
|
||||
.cfi_rel_offset r12, 96
|
||||
.cfi_rel_offset r13, 104
|
||||
.cfi_rel_offset r14, 112
|
||||
.cfi_def_cfa_register r13
|
||||
stg %r2,0(%r15) # Set up back chain
|
||||
larl %r14,.Ltable # Set up return address
|
||||
slag %r3,%r3,3 # ret_type *= 8
|
||||
lgr %r12,%r4 # Save ret_addr
|
||||
lgr %r1,%r5 # Save fun
|
||||
lgr %r0,%r6 # Install static chain
|
||||
agr %r14,%r3
|
||||
lmg %r2,%r6,16(%r13) # Load arguments
|
||||
ld %f0,128(%r13)
|
||||
ld %f2,136(%r13)
|
||||
ld %f4,144(%r13)
|
||||
ld %f6,152(%r13)
|
||||
br %r1 # ... and call function
|
||||
|
||||
la %r2,160(%r15) # Save area
|
||||
# r3 already holds &ecif
|
||||
basr %r14,%r4 # Call ffi_prep_args
|
||||
|
||||
lmg %r2,%r6,0(%r11) # Load arguments
|
||||
ld %f0,48(%r11)
|
||||
ld %f2,56(%r11)
|
||||
ld %f4,64(%r11)
|
||||
ld %f6,72(%r11)
|
||||
la %r14,0(%r13,%r9) # Set return address
|
||||
br %r7 # ... and call function
|
||||
|
||||
.Lbase:
|
||||
.LretNone: # Return void
|
||||
lg %r4,80+112(%r11)
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.LretFloat:
|
||||
lg %r4,80+112(%r11)
|
||||
ste %f0,0(%r8) # Return float
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.LretDouble:
|
||||
lg %r4,80+112(%r11)
|
||||
std %f0,0(%r8) # Return double
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.LretInt32:
|
||||
lg %r4,80+112(%r11)
|
||||
st %r2,0(%r8) # Return int
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.LretInt64:
|
||||
lg %r4,80+112(%r11)
|
||||
stg %r2,0(%r8) # Return long
|
||||
lmg %r6,%r15,80+48(%r11)
|
||||
br %r4
|
||||
|
||||
.balign 8
|
||||
.Ltable:
|
||||
.byte .LretNone-.Lbase # FFI390_RET_VOID
|
||||
.byte .LretNone-.Lbase # FFI390_RET_STRUCT
|
||||
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT
|
||||
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
|
||||
.byte .LretInt32-.Lbase # FFI390_RET_INT32
|
||||
.byte .LretInt64-.Lbase # FFI390_RET_INT64
|
||||
# FFI390_RET_DOUBLE
|
||||
std %f0,0(%r12)
|
||||
j .Ldone
|
||||
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
.balign 8
|
||||
# FFI390_RET_DOUBLE
|
||||
ste %f0,0(%r12)
|
||||
j .Ldone
|
||||
|
||||
.balign 8
|
||||
# FFI390_RET_INT64
|
||||
stg %r2,0(%r12)
|
||||
|
||||
.balign 8
|
||||
# FFI390_RET_INT32
|
||||
# Never used, as we always store type ffi_arg.
|
||||
# But the stg above is 6 bytes and we cannot
|
||||
# jump around this case, so fall through.
|
||||
nop
|
||||
nop
|
||||
|
||||
.balign 8
|
||||
# FFI390_RET_VOID
|
||||
.Ldone:
|
||||
lg %r14,112(%r13)
|
||||
lg %r12,96(%r13)
|
||||
lg %r6,88(%r13)
|
||||
lg %r13,104(%r13)
|
||||
.cfi_restore r14
|
||||
.cfi_restore r13
|
||||
.cfi_restore r12
|
||||
.cfi_restore r6
|
||||
.cfi_def_cfa r15, 160
|
||||
br %r14
|
||||
.cfi_endproc
|
||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
||||
|
||||
|
||||
.balign 8
|
||||
.globl ffi_go_closure_SYSV
|
||||
FFI_HIDDEN(ffi_go_closure_SYSV)
|
||||
.type ffi_go_closure_SYSV,%function
|
||||
ffi_go_closure_SYSV:
|
||||
.cfi_startproc
|
||||
stmg %r2,%r6,16(%r15) # Save arguments
|
||||
lgr %r4,%r0 # Load closure -> user_data
|
||||
lg %r2,8(%r4) # ->cif
|
||||
lg %r3,16(%r4) # ->fun
|
||||
j .Ldoclosure
|
||||
.cfi_endproc
|
||||
.size ffi_go_closure_SYSV,.-ffi_go_closure_SYSV
|
||||
|
||||
|
||||
.balign 8
|
||||
.globl ffi_closure_SYSV
|
||||
FFI_HIDDEN(ffi_closure_SYSV)
|
||||
.type ffi_closure_SYSV,%function
|
||||
ffi_closure_SYSV:
|
||||
.LFB2:
|
||||
stmg %r14,%r15,112(%r15) # Save registers
|
||||
.LCFI10:
|
||||
.cfi_startproc
|
||||
stmg %r2,%r6,16(%r15) # Save arguments
|
||||
std %f0,128(%r15)
|
||||
std %f2,136(%r15)
|
||||
std %f4,144(%r15)
|
||||
std %f6,152(%r15)
|
||||
lgr %r1,%r15 # Set up stack frame
|
||||
aghi %r15,-160
|
||||
.LCFI11:
|
||||
lgr %r2,%r0 # Closure
|
||||
la %r3,16(%r1) # GPRs
|
||||
la %r4,128(%r1) # FPRs
|
||||
la %r5,160(%r1) # Overflow
|
||||
stg %r1,0(%r15) # Set up back chain
|
||||
lgr %r4,%r0 # Load closure
|
||||
lg %r2,32(%r4) # ->cif
|
||||
lg %r3,40(%r4) # ->fun
|
||||
lg %r4,48(%r4) # ->user_data
|
||||
.Ldoclosure:
|
||||
stmg %r13,%r15,104(%r15) # Save registers
|
||||
lgr %r13,%r15
|
||||
.cfi_def_cfa_register r13
|
||||
.cfi_rel_offset r6, 48
|
||||
.cfi_rel_offset r13, 104
|
||||
.cfi_rel_offset r14, 112
|
||||
.cfi_rel_offset r15, 120
|
||||
aghi %r15,-160-16 # Set up stack frame
|
||||
stg %r13,0(%r15) # Set up back chain
|
||||
|
||||
std %f0,128(%r13) # Save fp arguments
|
||||
std %f2,136(%r13)
|
||||
std %f4,144(%r13)
|
||||
std %f6,152(%r13)
|
||||
la %r5,160(%r13) # Overflow
|
||||
stg %r5,160(%r15)
|
||||
la %r6,128(%r13) # FPRs
|
||||
la %r5,16(%r13) # GPRs
|
||||
brasl %r14,ffi_closure_helper_SYSV # Call helper
|
||||
|
||||
lg %r14,160+112(%r15)
|
||||
ld %f0,160+128(%r15) # Load return registers
|
||||
lg %r2,160+16(%r15)
|
||||
la %r15,160(%r15)
|
||||
lgr %r15,%r13
|
||||
.cfi_def_cfa_register r15
|
||||
lmg %r13,%r14,104(%r13) # Restore saved registers
|
||||
lg %r6,48(%r15)
|
||||
ld %f0,128(%r15) # Load return registers
|
||||
lg %r2,16(%r15)
|
||||
br %r14
|
||||
.LFE2:
|
||||
|
||||
.ffi_closure_SYSV_end:
|
||||
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
|
||||
|
||||
|
||||
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 -8 # CIE Data Alignment Factor
|
||||
.byte 0xe # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0xf
|
||||
.uleb128 0xa0
|
||||
.align 8
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # FDE Length
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
|
||||
.4byte .LFB1-. # FDE initial location
|
||||
.4byte .LFE1-.LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.uleb128 0x5
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.uleb128 0x6
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.uleb128 0x7
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.uleb128 0x8
|
||||
.byte 0x8b # DW_CFA_offset, column 0xb
|
||||
.uleb128 0x9
|
||||
.byte 0x8a # DW_CFA_offset, column 0xa
|
||||
.uleb128 0xa
|
||||
.byte 0x89 # DW_CFA_offset, column 0x9
|
||||
.uleb128 0xb
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.uleb128 0xc
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.uleb128 0xd
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.uleb128 0xe
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0xb
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI2-.LCFI1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0xf0
|
||||
.align 8
|
||||
.LEFDE1:
|
||||
.LSFDE2:
|
||||
.4byte .LEFDE2-.LASFDE2 # FDE Length
|
||||
.LASFDE2:
|
||||
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
|
||||
.4byte .LFB2-. # FDE initial location
|
||||
.4byte .LFE2-.LFB2 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI10-.LFB2
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.uleb128 0x5
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.uleb128 0x6
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI11-.LCFI10
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x140
|
||||
.align 8
|
||||
.LEFDE2:
|
||||
|
||||
#endif
|
||||
.cfi_endproc
|
||||
.size ffi_closure_SYSV,.-ffi_closure_SYSV
|
||||
#endif /* !s390x */
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
|
||||
#endif
|
||||
|
||||
/* If the structure has essentialy an unique element, return its type. */
|
||||
/* If the structure has essentially an unique element, return its type. */
|
||||
static int
|
||||
simple_type (ffi_type *arg)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
608
libffi/src/sparc/ffi64.c
Normal file
608
libffi/src/sparc/ffi64.c
Normal file
|
@ -0,0 +1,608 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2011, 2013 Anthony Green
|
||||
Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
|
||||
|
||||
SPARC 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 "internal.h"
|
||||
|
||||
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
|
||||
all further uses in this file will refer to the 128-bit type. */
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
# if FFI_TYPE_LONGDOUBLE != 4
|
||||
# error FFI_TYPE_LONGDOUBLE out of date
|
||||
# endif
|
||||
#else
|
||||
# undef FFI_TYPE_LONGDOUBLE
|
||||
# define FFI_TYPE_LONGDOUBLE 4
|
||||
#endif
|
||||
|
||||
#ifdef SPARC64
|
||||
|
||||
/* Flatten the contents of a structure to the parts that are passed in
|
||||
floating point registers. The return is a bit mask wherein bit N
|
||||
set means bytes [4*n, 4*n+3] are passed in %fN.
|
||||
|
||||
We encode both the (running) size (maximum 32) and mask (maxumum 255)
|
||||
into one integer. The size is placed in the low byte, so that align
|
||||
and addition work correctly. The mask is placed in the second byte. */
|
||||
|
||||
static int
|
||||
ffi_struct_float_mask (ffi_type *outer_type, int size_mask)
|
||||
{
|
||||
ffi_type **elts;
|
||||
ffi_type *t;
|
||||
|
||||
if (outer_type->type == FFI_TYPE_COMPLEX)
|
||||
{
|
||||
int m = 0, tt = outer_type->elements[0]->type;
|
||||
size_t z = outer_type->size;
|
||||
|
||||
if (tt == FFI_TYPE_FLOAT
|
||||
|| tt == FFI_TYPE_DOUBLE
|
||||
|| tt == FFI_TYPE_LONGDOUBLE)
|
||||
m = (1 << (z / 4)) - 1;
|
||||
return (m << 8) | z;
|
||||
}
|
||||
FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT);
|
||||
|
||||
for (elts = outer_type->elements; (t = *elts) != NULL; elts++)
|
||||
{
|
||||
size_t z = t->size;
|
||||
int o, m, tt;
|
||||
|
||||
size_mask = ALIGN(size_mask, t->alignment);
|
||||
switch (t->type)
|
||||
{
|
||||
case FFI_TYPE_STRUCT:
|
||||
size_mask = ffi_struct_float_mask (t, size_mask);
|
||||
continue;
|
||||
case FFI_TYPE_COMPLEX:
|
||||
tt = t->elements[0]->type;
|
||||
if (tt != FFI_TYPE_FLOAT
|
||||
&& tt != FFI_TYPE_DOUBLE
|
||||
&& tt != FFI_TYPE_LONGDOUBLE)
|
||||
break;
|
||||
/* FALLTHRU */
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
m = (1 << (z / 4)) - 1; /* compute mask for type */
|
||||
o = (size_mask >> 2) & 0x3f; /* extract word offset */
|
||||
size_mask |= m << (o + 8); /* insert mask into place */
|
||||
break;
|
||||
}
|
||||
size_mask += z;
|
||||
}
|
||||
|
||||
size_mask = ALIGN(size_mask, outer_type->alignment);
|
||||
FFI_ASSERT ((size_mask & 0xff) == outer_type->size);
|
||||
|
||||
return size_mask;
|
||||
}
|
||||
|
||||
/* Merge floating point data into integer data. If the structure is
|
||||
entirely floating point, simply return a pointer to the fp data. */
|
||||
|
||||
static void *
|
||||
ffi_struct_float_merge (int size_mask, void *vi, void *vf)
|
||||
{
|
||||
int size = size_mask & 0xff;
|
||||
int mask = size_mask >> 8;
|
||||
int n = size >> 2;
|
||||
|
||||
if (mask == 0)
|
||||
return vi;
|
||||
else if (mask == (1 << n) - 1)
|
||||
return vf;
|
||||
else
|
||||
{
|
||||
unsigned int *wi = vi, *wf = vf;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
if ((mask >> i) & 1)
|
||||
wi[i] = wf[i];
|
||||
|
||||
return vi;
|
||||
}
|
||||
}
|
||||
|
||||
/* Similar, but place the data into VD in the end. */
|
||||
|
||||
void FFI_HIDDEN
|
||||
ffi_struct_float_copy (int size_mask, void *vd, void *vi, void *vf)
|
||||
{
|
||||
int size = size_mask & 0xff;
|
||||
int mask = size_mask >> 8;
|
||||
int n = size >> 2;
|
||||
|
||||
if (mask == 0)
|
||||
;
|
||||
else if (mask == (1 << n) - 1)
|
||||
vi = vf;
|
||||
else
|
||||
{
|
||||
unsigned int *wd = vd, *wi = vi, *wf = vf;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
wd[i] = ((mask >> i) & 1 ? wf : wi)[i];
|
||||
return;
|
||||
}
|
||||
memcpy (vd, vi, size);
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
|
||||
static ffi_status
|
||||
ffi_prep_cif_machdep_core(ffi_cif *cif)
|
||||
{
|
||||
ffi_type *rtype = cif->rtype;
|
||||
int rtt = rtype->type;
|
||||
size_t bytes = 0;
|
||||
int i, n, flags;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (rtt)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
flags = SPARC_RET_VOID;
|
||||
break;
|
||||
case FFI_TYPE_FLOAT:
|
||||
flags = SPARC_RET_F_1;
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
flags = SPARC_RET_F_2;
|
||||
break;
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
flags = SPARC_RET_F_4;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_COMPLEX:
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (rtype->size > 32)
|
||||
{
|
||||
flags = SPARC_RET_VOID | SPARC_FLAG_RET_IN_MEM;
|
||||
bytes = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
int size_mask = ffi_struct_float_mask (rtype, 0);
|
||||
int word_size = (size_mask >> 2) & 0x3f;
|
||||
int all_mask = (1 << word_size) - 1;
|
||||
int fp_mask = size_mask >> 8;
|
||||
|
||||
flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT;
|
||||
|
||||
/* For special cases of all-int or all-fp, we can return
|
||||
the value directly without popping through a struct copy. */
|
||||
if (fp_mask == 0)
|
||||
{
|
||||
if (rtype->alignment >= 8)
|
||||
{
|
||||
if (rtype->size == 8)
|
||||
flags = SPARC_RET_INT64;
|
||||
else if (rtype->size == 16)
|
||||
flags = SPARC_RET_INT128;
|
||||
}
|
||||
}
|
||||
else if (fp_mask == all_mask)
|
||||
switch (word_size)
|
||||
{
|
||||
case 1: flags = SPARC_RET_F_1; break;
|
||||
case 2: flags = SPARC_RET_F_2; break;
|
||||
case 3: flags = SP_V9_RET_F_3; break;
|
||||
case 4: flags = SPARC_RET_F_4; break;
|
||||
/* 5 word structures skipped; handled via RET_STRUCT. */
|
||||
case 6: flags = SPARC_RET_F_6; break;
|
||||
/* 7 word structures skipped; handled via RET_STRUCT. */
|
||||
case 8: flags = SPARC_RET_F_8; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
flags = SPARC_RET_SINT8;
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
flags = SPARC_RET_UINT8;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
flags = SPARC_RET_SINT16;
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
flags = SPARC_RET_UINT16;
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
flags = SP_V9_RET_SINT32;
|
||||
break;
|
||||
case FFI_TYPE_UINT32:
|
||||
flags = SPARC_RET_UINT32;
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
flags = SPARC_RET_INT64;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
bytes = 0;
|
||||
for (i = 0, n = cif->nargs; i < n; ++i)
|
||||
{
|
||||
ffi_type *ty = cif->arg_types[i];
|
||||
size_t z = ty->size;
|
||||
size_t a = ty->alignment;
|
||||
|
||||
switch (ty->type)
|
||||
{
|
||||
case FFI_TYPE_COMPLEX:
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Large structs passed by reference. */
|
||||
if (z > 16)
|
||||
{
|
||||
a = z = 8;
|
||||
break;
|
||||
}
|
||||
/* Small structs may be passed in integer or fp regs or both. */
|
||||
if (bytes >= 16*8)
|
||||
break;
|
||||
if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0)
|
||||
break;
|
||||
/* FALLTHRU */
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
flags |= SPARC_FLAG_FP_ARGS;
|
||||
break;
|
||||
}
|
||||
bytes = ALIGN(bytes, a);
|
||||
bytes += ALIGN(z, 8);
|
||||
}
|
||||
|
||||
/* Sparc call frames require that space is allocated for 6 args,
|
||||
even if they aren't used. Make that space if necessary. */
|
||||
if (bytes < 6 * 8)
|
||||
bytes = 6 * 8;
|
||||
|
||||
/* The stack must be 2 word aligned, so round bytes up appropriately. */
|
||||
bytes = ALIGN(bytes, 16);
|
||||
|
||||
/* Include the call frame to prep_args. */
|
||||
bytes += 8*16 + 8*8;
|
||||
|
||||
cif->bytes = bytes;
|
||||
cif->flags = flags;
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
ffi_status FFI_HIDDEN
|
||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
cif->nfixedargs = cif->nargs;
|
||||
return ffi_prep_cif_machdep_core(cif);
|
||||
}
|
||||
|
||||
ffi_status FFI_HIDDEN
|
||||
ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs)
|
||||
{
|
||||
cif->nfixedargs = nfixedargs;
|
||||
return ffi_prep_cif_machdep_core(cif);
|
||||
}
|
||||
|
||||
extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
int FFI_HIDDEN
|
||||
ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
|
||||
{
|
||||
ffi_type **p_arg;
|
||||
int flags = cif->flags;
|
||||
int i, nargs;
|
||||
|
||||
if (rvalue == NULL)
|
||||
{
|
||||
if (flags & SPARC_FLAG_RET_IN_MEM)
|
||||
{
|
||||
/* Since we pass the pointer to the callee, we need a value.
|
||||
We allowed for this space in ffi_call, before ffi_call_v8
|
||||
alloca'd the space. */
|
||||
rvalue = (char *)argp + cif->bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we can ignore the return value. */
|
||||
flags = SPARC_RET_VOID;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USING_PURIFY
|
||||
/* Purify will probably complain in our assembly routine,
|
||||
unless we zero out this memory. */
|
||||
memset(argp, 0, 6*8);
|
||||
#endif
|
||||
|
||||
if (flags & SPARC_FLAG_RET_IN_MEM)
|
||||
*argp++ = (unsigned long)rvalue;
|
||||
|
||||
p_arg = cif->arg_types;
|
||||
for (i = 0, nargs = cif->nargs; i < nargs; i++)
|
||||
{
|
||||
ffi_type *ty = p_arg[i];
|
||||
void *a = avalue[i];
|
||||
size_t z;
|
||||
|
||||
switch (ty->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*argp++ = *(SINT8 *)a;
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
*argp++ = *(UINT8 *)a;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
*argp++ = *(SINT16 *)a;
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
*argp++ = *(UINT16 *)a;
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_SINT32:
|
||||
*argp++ = *(SINT32 *)a;
|
||||
break;
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_FLOAT:
|
||||
*argp++ = *(UINT32 *)a;
|
||||
break;
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
*argp++ = *(UINT64 *)a;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
case FFI_TYPE_COMPLEX:
|
||||
case FFI_TYPE_STRUCT:
|
||||
z = ty->size;
|
||||
if (z > 16)
|
||||
{
|
||||
/* For structures larger than 16 bytes we pass reference. */
|
||||
*argp++ = (unsigned long)a;
|
||||
break;
|
||||
}
|
||||
if (((unsigned long)argp & 15) && ty->alignment > 8)
|
||||
argp++;
|
||||
memcpy(argp, a, z);
|
||||
argp += ALIGN(z, 8) / 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, void *closure)
|
||||
{
|
||||
size_t bytes = cif->bytes;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_V9);
|
||||
|
||||
if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
|
||||
bytes += ALIGN (cif->rtype->size, 16);
|
||||
|
||||
ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
ffi_call_int(cif, fn, rvalue, avalue, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, void *closure)
|
||||
{
|
||||
ffi_call_int(cif, fn, rvalue, avalue, closure);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
static inline void
|
||||
ffi_flush_icache (void *p)
|
||||
{
|
||||
asm volatile ("flush %0; flush %0+8" : : "r" (p) : "memory");
|
||||
}
|
||||
#else
|
||||
extern void ffi_flush_icache (void *) FFI_HIDDEN;
|
||||
#endif
|
||||
|
||||
extern void ffi_closure_v9(void) FFI_HIDDEN;
|
||||
extern void ffi_go_closure_v9(void) 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)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned long fn;
|
||||
|
||||
if (cif->abi != FFI_V9)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
/* Trampoline address is equal to the closure address. We take advantage
|
||||
of that to reduce the trampoline size by 8 bytes. */
|
||||
fn = (unsigned long) ffi_closure_v9;
|
||||
tramp[0] = 0x83414000; /* rd %pc, %g1 */
|
||||
tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
|
||||
tramp[2] = 0x81c14000; /* jmp %g5 */
|
||||
tramp[3] = 0x01000000; /* nop */
|
||||
*((unsigned long *) &tramp[4]) = fn;
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
ffi_flush_icache (closure);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*))
|
||||
{
|
||||
if (cif->abi != FFI_V9)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
closure->tramp = ffi_go_closure_v9;
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int FFI_HIDDEN
|
||||
ffi_closure_sparc_inner_v9(ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data, void *rvalue,
|
||||
unsigned long *gpr, unsigned long *fpr)
|
||||
{
|
||||
ffi_type **arg_types;
|
||||
void **avalue;
|
||||
int i, argn, argx, nargs, flags, nfixedargs;
|
||||
|
||||
arg_types = cif->arg_types;
|
||||
nargs = cif->nargs;
|
||||
flags = cif->flags;
|
||||
nfixedargs = cif->nfixedargs;
|
||||
|
||||
avalue = alloca(nargs * sizeof(void *));
|
||||
|
||||
/* Copy the caller's structure return address so that the closure
|
||||
returns the data directly to the caller. */
|
||||
if (flags & SPARC_FLAG_RET_IN_MEM)
|
||||
{
|
||||
rvalue = (void *) gpr[0];
|
||||
/* Skip the structure return address. */
|
||||
argn = 1;
|
||||
}
|
||||
else
|
||||
argn = 0;
|
||||
|
||||
/* Grab the addresses of the arguments from the stack frame. */
|
||||
for (i = 0; i < nargs; i++, argn = argx)
|
||||
{
|
||||
int named = i < nfixedargs;
|
||||
ffi_type *ty = arg_types[i];
|
||||
void *a = &gpr[argn];
|
||||
size_t z;
|
||||
|
||||
argx = argn + 1;
|
||||
switch (ty->type)
|
||||
{
|
||||
case FFI_TYPE_COMPLEX:
|
||||
case FFI_TYPE_STRUCT:
|
||||
z = ty->size;
|
||||
if (z > 16)
|
||||
a = *(void **)a;
|
||||
else
|
||||
{
|
||||
argx = argn + ALIGN (z, 8) / 8;
|
||||
if (named && argn < 16)
|
||||
{
|
||||
int size_mask = ffi_struct_float_mask (ty, 0);
|
||||
int argn_mask = (0xffff00 >> argn) & 0xff00;
|
||||
|
||||
/* Eliminate fp registers off the end. */
|
||||
size_mask = (size_mask & 0xff) | (size_mask & argn_mask);
|
||||
a = ffi_struct_float_merge (size_mask, gpr+argn, fpr+argn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
argn = ALIGN (argn, 2);
|
||||
a = (named && argn < 16 ? fpr : gpr) + argn;
|
||||
argx = argn + 2;
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
if (named && argn < 16)
|
||||
a = fpr + argn;
|
||||
break;
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (named && argn < 16)
|
||||
a = fpr + argn;
|
||||
a += 4;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
a += 4;
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
a += 6;
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
a += 7;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
avalue[i] = a;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
fun (cif, rvalue, avalue, user_data);
|
||||
|
||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||
return flags;
|
||||
}
|
||||
#endif /* SPARC64 */
|
|
@ -46,42 +46,36 @@ typedef signed long ffi_sarg;
|
|||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_V8,
|
||||
FFI_V8PLUS,
|
||||
/* See below for the COMPAT_V9 rationale. */
|
||||
FFI_COMPAT_V9,
|
||||
FFI_V9,
|
||||
FFI_LAST_ABI,
|
||||
#ifdef SPARC64
|
||||
FFI_DEFAULT_ABI = FFI_V9
|
||||
FFI_V9,
|
||||
FFI_DEFAULT_ABI = FFI_V9,
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_V8
|
||||
FFI_V8,
|
||||
FFI_DEFAULT_ABI = FFI_V8,
|
||||
#endif
|
||||
FFI_LAST_ABI
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
#define V8_ABI_P(abi) ((abi) == FFI_V8 || (abi) == FFI_V8PLUS)
|
||||
#define V9_ABI_P(abi) ((abi) == FFI_COMPAT_V9 || (abi) == FFI_V9)
|
||||
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION 1
|
||||
#define FFI_TARGET_HAS_COMPLEX_TYPE 1
|
||||
|
||||
#define FFI_TARGET_SPECIFIC_VARIADIC 1
|
||||
|
||||
/* The support of variadic functions was broken in the original implementation
|
||||
of the FFI_V9 ABI. This has been fixed by adding one extra field to the
|
||||
CIF structure (nfixedargs field), which means that the ABI of libffi itself
|
||||
has changed. In order to support applications using the original ABI, we
|
||||
have renamed FFI_V9 into FFI_COMPAT_V9 and defined a new FFI_V9 value. */
|
||||
#ifdef SPARC64
|
||||
#define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
|
||||
# define FFI_TARGET_SPECIFIC_VARIADIC 1
|
||||
# define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_GO_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef SPARC64
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 16
|
||||
#endif
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
|
|
26
libffi/src/sparc/internal.h
Normal file
26
libffi/src/sparc/internal.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#define SPARC_RET_VOID 0
|
||||
#define SPARC_RET_STRUCT 1
|
||||
#define SPARC_RET_UINT8 2
|
||||
#define SPARC_RET_SINT8 3
|
||||
#define SPARC_RET_UINT16 4
|
||||
#define SPARC_RET_SINT16 5
|
||||
#define SPARC_RET_UINT32 6
|
||||
#define SP_V9_RET_SINT32 7 /* v9 only */
|
||||
#define SP_V8_RET_CPLX16 7 /* v8 only */
|
||||
#define SPARC_RET_INT64 8
|
||||
#define SPARC_RET_INT128 9
|
||||
|
||||
/* Note that F_7 is missing, and is handled by SPARC_RET_STRUCT. */
|
||||
#define SPARC_RET_F_8 10
|
||||
#define SPARC_RET_F_6 11
|
||||
#define SPARC_RET_F_4 12
|
||||
#define SPARC_RET_F_2 13
|
||||
#define SP_V9_RET_F_3 14 /* v9 only */
|
||||
#define SP_V8_RET_CPLX8 14 /* v8 only */
|
||||
#define SPARC_RET_F_1 15
|
||||
|
||||
#define SPARC_FLAG_RET_MASK 15
|
||||
#define SPARC_FLAG_RET_IN_MEM 32
|
||||
#define SPARC_FLAG_FP_ARGS 64
|
||||
|
||||
#define SPARC_SIZEMASK_SHIFT 8
|
|
@ -1,7 +1,8 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
|
||||
v8.S - Copyright (c) 2013 The Written Word, Inc.
|
||||
Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
|
||||
|
||||
SPARC Foreign Function Interface
|
||||
SPARC Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -24,153 +25,243 @@
|
|||
DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <ffi_cfi.h>
|
||||
#include "internal.h"
|
||||
|
||||
#ifndef SPARC64
|
||||
|
||||
#define STACKFRAME 96 /* Minimum stack framesize for SPARC */
|
||||
#define ARGS (64+4) /* Offset of register area in frame */
|
||||
#define C2(X, Y) X ## Y
|
||||
#define C1(X, Y) C2(X, Y)
|
||||
|
||||
.text
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
# define C(Y) C1(__USER_LABEL_PREFIX__, Y)
|
||||
#else
|
||||
# define C(Y) Y
|
||||
#endif
|
||||
#define L(Y) C1(.L, Y)
|
||||
|
||||
.text
|
||||
|
||||
#ifndef __GNUC__
|
||||
.align 8
|
||||
.globl ffi_call_v8
|
||||
.globl _ffi_call_v8
|
||||
.globl C(ffi_flush_icache)
|
||||
.type C(ffi_flush_icache),@function
|
||||
FFI_HIDDEN(C(ffi_flush_icache))
|
||||
|
||||
ffi_call_v8:
|
||||
_ffi_call_v8:
|
||||
.LLFB1:
|
||||
save %sp, -STACKFRAME, %sp
|
||||
.LLCFI0:
|
||||
|
||||
sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
|
||||
add %sp, STACKFRAME, %l0 ! %l0 has start of
|
||||
! frame to set up
|
||||
|
||||
mov %l0, %o0 ! call routine to set up frame
|
||||
call %i0
|
||||
mov %i1, %o1 ! (delay)
|
||||
|
||||
ld [%l0+ARGS], %o0 ! call foreign function
|
||||
ld [%l0+ARGS+4], %o1
|
||||
ld [%l0+ARGS+8], %o2
|
||||
ld [%l0+ARGS+12], %o3
|
||||
ld [%l0+ARGS+16], %o4
|
||||
ld [%l0+ARGS+20], %o5
|
||||
call %i5
|
||||
mov %l0, %sp ! (delay) switch to frame
|
||||
nop ! STRUCT returning functions skip 12 instead of 8 bytes
|
||||
|
||||
! If the return value pointer is NULL, assume no return value.
|
||||
tst %i4
|
||||
bz done
|
||||
C(ffi_flush_icache):
|
||||
cfi_startproc
|
||||
1: iflush %o0
|
||||
iflush %o+8
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
retl
|
||||
nop
|
||||
cfi_endproc
|
||||
.size C(ffi_flush_icache), . - C(ffi_flush_icache)
|
||||
#endif
|
||||
|
||||
cmp %i3, FFI_TYPE_INT
|
||||
be,a done
|
||||
st %o0, [%i4] ! (delay)
|
||||
.macro E index
|
||||
.align 16
|
||||
.org 2b + \index * 16
|
||||
.endm
|
||||
|
||||
cmp %i3, FFI_TYPE_FLOAT
|
||||
be,a done
|
||||
st %f0, [%i4+0] ! (delay)
|
||||
.align 8
|
||||
.globl C(ffi_call_v8)
|
||||
.type C(ffi_call_v8),@function
|
||||
FFI_HIDDEN(C(ffi_call_v8))
|
||||
|
||||
cmp %i3, FFI_TYPE_DOUBLE
|
||||
be,a double
|
||||
st %f0, [%i4+0] ! (delay)
|
||||
C(ffi_call_v8):
|
||||
cfi_startproc
|
||||
! Allocate a stack frame sized by ffi_call.
|
||||
save %sp, %o4, %sp
|
||||
cfi_def_cfa_register(%fp)
|
||||
cfi_window_save
|
||||
|
||||
cmp %i3, FFI_TYPE_SINT8
|
||||
be,a sint8
|
||||
sll %o0, 24, %o0 ! (delay)
|
||||
mov %i0, %o0 ! copy cif
|
||||
add %sp, 64+32, %o1 ! load args area
|
||||
mov %i2, %o2 ! copy rvalue
|
||||
call C(ffi_prep_args_v8)
|
||||
mov %i3, %o3 ! copy avalue
|
||||
|
||||
cmp %i3, FFI_TYPE_UINT8
|
||||
be,a uint8
|
||||
sll %o0, 24, %o0 ! (delay)
|
||||
add %sp, 32, %sp ! deallocate prep frame
|
||||
and %o0, SPARC_FLAG_RET_MASK, %l0 ! save return type
|
||||
srl %o0, SPARC_SIZEMASK_SHIFT, %l1 ! save return size
|
||||
ld [%sp+64+4], %o0 ! load all argument registers
|
||||
ld [%sp+64+8], %o1
|
||||
ld [%sp+64+12], %o2
|
||||
ld [%sp+64+16], %o3
|
||||
cmp %l0, SPARC_RET_STRUCT ! struct return needs an unimp 4
|
||||
ld [%sp+64+20], %o4
|
||||
be 8f
|
||||
ld [%sp+64+24], %o5
|
||||
|
||||
cmp %i3, FFI_TYPE_SINT16
|
||||
be,a sint16
|
||||
sll %o0, 16, %o0 ! (delay)
|
||||
! Call foreign function
|
||||
call %i1
|
||||
mov %i5, %g2 ! load static chain
|
||||
|
||||
cmp %i3, FFI_TYPE_UINT16
|
||||
be,a uint16
|
||||
sll %o0, 16, %o0 ! (delay)
|
||||
0: call 1f ! load pc in %o7
|
||||
sll %l0, 4, %l0
|
||||
1: add %o7, %l0, %o7 ! o7 = 0b + ret_type*16
|
||||
jmp %o7+(2f-0b)
|
||||
nop
|
||||
|
||||
cmp %i3, FFI_TYPE_SINT64
|
||||
be,a longlong
|
||||
st %o0, [%i4+0] ! (delay)
|
||||
done:
|
||||
! Note that each entry is 4 insns, enforced by the E macro.
|
||||
.align 16
|
||||
2:
|
||||
E SPARC_RET_VOID
|
||||
ret
|
||||
restore
|
||||
|
||||
double:
|
||||
st %f1, [%i4+4]
|
||||
restore
|
||||
E SPARC_RET_STRUCT
|
||||
unimp
|
||||
E SPARC_RET_UINT8
|
||||
and %o0, 0xff, %o0
|
||||
st %o0, [%i2]
|
||||
ret
|
||||
restore
|
||||
|
||||
sint8:
|
||||
sra %o0, 24, %o0
|
||||
st %o0, [%i4+0]
|
||||
restore
|
||||
E SPARC_RET_SINT8
|
||||
sll %o0, 24, %o0
|
||||
b 7f
|
||||
sra %o0, 24, %o0
|
||||
E SPARC_RET_UINT16
|
||||
sll %o0, 16, %o0
|
||||
b 7f
|
||||
srl %o0, 16, %o0
|
||||
E SPARC_RET_SINT16
|
||||
sll %o0, 16, %o0
|
||||
b 7f
|
||||
sra %o0, 16, %o0
|
||||
E SPARC_RET_UINT32
|
||||
7: st %o0, [%i2]
|
||||
ret
|
||||
restore
|
||||
|
||||
uint8:
|
||||
srl %o0, 24, %o0
|
||||
st %o0, [%i4+0]
|
||||
restore
|
||||
E SP_V8_RET_CPLX16
|
||||
sth %o0, [%i2+2]
|
||||
b 9f
|
||||
srl %o0, 16, %o0
|
||||
E SPARC_RET_INT64
|
||||
st %o0, [%i2]
|
||||
st %o1, [%i2+4]
|
||||
ret
|
||||
restore
|
||||
|
||||
sint16:
|
||||
sra %o0, 16, %o0
|
||||
st %o0, [%i4+0]
|
||||
restore
|
||||
E SPARC_RET_INT128
|
||||
std %o0, [%i2]
|
||||
std %o2, [%i2+8]
|
||||
ret
|
||||
restore
|
||||
|
||||
uint16:
|
||||
srl %o0, 16, %o0
|
||||
st %o0, [%i4+0]
|
||||
restore
|
||||
E SPARC_RET_F_8
|
||||
st %f7, [%i2+7*4]
|
||||
nop
|
||||
st %f6, [%i2+6*4]
|
||||
nop
|
||||
E SPARC_RET_F_6
|
||||
st %f5, [%i2+5*4]
|
||||
nop
|
||||
st %f4, [%i2+4*4]
|
||||
nop
|
||||
E SPARC_RET_F_4
|
||||
st %f3, [%i2+3*4]
|
||||
nop
|
||||
st %f2, [%i2+2*4]
|
||||
nop
|
||||
E SPARC_RET_F_2
|
||||
st %f1, [%i2+4]
|
||||
st %f0, [%i2]
|
||||
ret
|
||||
restore
|
||||
|
||||
longlong:
|
||||
st %o1, [%i4+4]
|
||||
restore
|
||||
E SP_V8_RET_CPLX8
|
||||
stb %o0, [%i2+1]
|
||||
b 10f
|
||||
srl %o0, 8, %o0
|
||||
E SPARC_RET_F_1
|
||||
st %f0, [%i2]
|
||||
ret
|
||||
restore
|
||||
.LLFE1:
|
||||
restore
|
||||
|
||||
.ffi_call_v8_end:
|
||||
.size ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
|
||||
.align 8
|
||||
9: sth %o0, [%i2]
|
||||
ret
|
||||
restore
|
||||
.align 8
|
||||
10: stb %o0, [%i2]
|
||||
ret
|
||||
restore
|
||||
|
||||
! Struct returning functions expect and skip the unimp here.
|
||||
! To make it worse, conforming callees examine the unimp and
|
||||
! make sure the low 12 bits of the unimp match the size of
|
||||
! the struct being returned.
|
||||
.align 8
|
||||
8: call 1f ! load pc in %o7
|
||||
sll %l1, 2, %l0 ! size * 4
|
||||
1: sll %l1, 4, %l1 ! size * 16
|
||||
add %l0, %l1, %l0 ! size * 20
|
||||
add %o7, %l0, %o7 ! o7 = 0b + size*20
|
||||
jmp %o7+(2f-8b)
|
||||
mov %i5, %g2 ! load static chain
|
||||
2:
|
||||
.rept 0x1000
|
||||
call %i1
|
||||
nop
|
||||
unimp (. - 2b) / 20
|
||||
ret
|
||||
restore
|
||||
.endr
|
||||
|
||||
cfi_endproc
|
||||
.size C(ffi_call_v8),. - C(ffi_call_v8)
|
||||
|
||||
|
||||
#undef STACKFRAME
|
||||
#define STACKFRAME 104 /* 16*4 register window +
|
||||
1*4 struct return +
|
||||
6*4 args backing store +
|
||||
3*4 locals */
|
||||
/* 16*4 register window + 1*4 struct return + 6*4 args backing store
|
||||
+ 8*4 return storage + 1*4 alignment. */
|
||||
#define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4)
|
||||
|
||||
/* ffi_closure_v8(...)
|
||||
|
||||
Receives the closure argument in %g2. */
|
||||
|
||||
.text
|
||||
.align 8
|
||||
.globl ffi_closure_v8
|
||||
|
||||
ffi_closure_v8:
|
||||
#ifdef HAVE_AS_REGISTER_PSEUDO_OP
|
||||
.register %g2, #scratch
|
||||
.register %g2, #scratch
|
||||
#endif
|
||||
.LLFB2:
|
||||
! Reserve frame space for all arguments in case
|
||||
! we need to align them on a 8-byte boundary.
|
||||
ld [%g2+FFI_TRAMPOLINE_SIZE], %g1
|
||||
ld [%g1+4], %g1
|
||||
sll %g1, 3, %g1
|
||||
add %g1, STACKFRAME, %g1
|
||||
! %g1 == STACKFRAME + 8*nargs
|
||||
neg %g1
|
||||
save %sp, %g1, %sp
|
||||
.LLCFI1:
|
||||
|
||||
.align 8
|
||||
.globl C(ffi_go_closure_v8)
|
||||
.type C(ffi_go_closure_v8),@function
|
||||
FFI_HIDDEN(C(ffi_go_closure_v8))
|
||||
|
||||
C(ffi_go_closure_v8):
|
||||
cfi_startproc
|
||||
save %sp, -STACKFRAME, %sp
|
||||
cfi_def_cfa_register(%fp)
|
||||
cfi_window_save
|
||||
|
||||
ld [%g2+4], %o0 ! load cif
|
||||
ld [%g2+8], %o1 ! load fun
|
||||
b 0f
|
||||
mov %g2, %o2 ! load user_data
|
||||
cfi_endproc
|
||||
.size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8)
|
||||
|
||||
.align 8
|
||||
.globl C(ffi_closure_v8)
|
||||
.type C(ffi_closure_v8),@function
|
||||
FFI_HIDDEN(C(ffi_closure_v8))
|
||||
|
||||
C(ffi_closure_v8):
|
||||
cfi_startproc
|
||||
save %sp, -STACKFRAME, %sp
|
||||
cfi_def_cfa_register(%fp)
|
||||
cfi_window_save
|
||||
|
||||
ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif
|
||||
ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun
|
||||
ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data
|
||||
0:
|
||||
! Store all of the potential argument registers in va_list format.
|
||||
st %i0, [%fp+68+0]
|
||||
st %i1, [%fp+68+4]
|
||||
|
@ -180,137 +271,91 @@ ffi_closure_v8:
|
|||
st %i5, [%fp+68+20]
|
||||
|
||||
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
||||
mov %g2, %o0
|
||||
add %fp, -8, %o1
|
||||
add %fp, 64, %o2
|
||||
add %fp, -8*4, %o3
|
||||
call ffi_closure_sparc_inner_v8
|
||||
add %fp, -16, %o3
|
||||
add %fp, 64, %o4
|
||||
|
||||
! Load up the return value in the proper type.
|
||||
! See ffi_prep_cif_machdep for the list of cases.
|
||||
cmp %o0, FFI_TYPE_VOID
|
||||
be done1
|
||||
|
||||
cmp %o0, FFI_TYPE_INT
|
||||
be done1
|
||||
ld [%fp-8], %i0
|
||||
|
||||
cmp %o0, FFI_TYPE_FLOAT
|
||||
be,a done1
|
||||
ld [%fp-8], %f0
|
||||
|
||||
cmp %o0, FFI_TYPE_DOUBLE
|
||||
be,a done1
|
||||
ldd [%fp-8], %f0
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
cmp %o0, FFI_TYPE_LONGDOUBLE
|
||||
be done2
|
||||
#endif
|
||||
|
||||
cmp %o0, FFI_TYPE_STRUCT
|
||||
be done2
|
||||
|
||||
cmp %o0, FFI_TYPE_SINT64
|
||||
be,a done1
|
||||
ldd [%fp-8], %i0
|
||||
|
||||
ld [%fp-8], %i0
|
||||
done1:
|
||||
jmp %i7+8
|
||||
0: call 1f
|
||||
and %o0, SPARC_FLAG_RET_MASK, %o0
|
||||
1: sll %o0, 4, %o0 ! o0 = o0 * 16
|
||||
add %o7, %o0, %o7 ! o7 = 0b + o0*16
|
||||
jmp %o7+(2f-0b)
|
||||
add %fp, -8*4, %i2
|
||||
|
||||
! Note that each entry is 4 insns, enforced by the E macro.
|
||||
.align 16
|
||||
2:
|
||||
E SPARC_RET_VOID
|
||||
ret
|
||||
restore
|
||||
done2:
|
||||
! Skip 'unimp'.
|
||||
E SPARC_RET_STRUCT
|
||||
ld [%i2], %i0
|
||||
jmp %i7+12
|
||||
restore
|
||||
.LLFE2:
|
||||
|
||||
.ffi_closure_v8_end:
|
||||
.size ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
|
||||
|
||||
#ifdef SPARC64
|
||||
#define WS 8
|
||||
#define nword xword
|
||||
#define uanword uaxword
|
||||
#else
|
||||
#define WS 4
|
||||
#define nword long
|
||||
#define uanword uaword
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RO_EH_FRAME
|
||||
.section ".eh_frame",#alloc
|
||||
#else
|
||||
.section ".eh_frame",#alloc,#write
|
||||
#endif
|
||||
.LLframe1:
|
||||
.uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry
|
||||
.LLSCIE1:
|
||||
.uaword 0x0 ! CIE Identifier Tag
|
||||
.byte 0x1 ! CIE Version
|
||||
.ascii "zR\0" ! CIE Augmentation
|
||||
.byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x80-WS ! sleb128 -WS; CIE Data Alignment Factor
|
||||
.byte 0xf ! CIE RA Column
|
||||
.byte 0x1 ! uleb128 0x1; Augmentation size
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.byte 0x1b ! FDE Encoding (pcrel sdata4)
|
||||
#else
|
||||
.byte 0x50 ! FDE Encoding (aligned absolute)
|
||||
#endif
|
||||
.byte 0xc ! DW_CFA_def_cfa
|
||||
.byte 0xe ! uleb128 0xe
|
||||
.byte 0x0 ! uleb128 0x0
|
||||
.align WS
|
||||
.LLECIE1:
|
||||
.LLSFDE1:
|
||||
.uaword .LLEFDE1-.LLASFDE1 ! FDE Length
|
||||
.LLASFDE1:
|
||||
.uaword .LLASFDE1-.LLframe1 ! FDE CIE offset
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.uaword %r_disp32(.LLFB1)
|
||||
.uaword .LLFE1-.LLFB1 ! FDE address range
|
||||
#else
|
||||
.align WS
|
||||
.nword .LLFB1
|
||||
.uanword .LLFE1-.LLFB1 ! FDE address range
|
||||
#endif
|
||||
.byte 0x0 ! uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ! DW_CFA_advance_loc4
|
||||
.uaword .LLCFI0-.LLFB1
|
||||
.byte 0xd ! DW_CFA_def_cfa_register
|
||||
.byte 0x1e ! uleb128 0x1e
|
||||
.byte 0x2d ! DW_CFA_GNU_window_save
|
||||
.byte 0x9 ! DW_CFA_register
|
||||
.byte 0xf ! uleb128 0xf
|
||||
.byte 0x1f ! uleb128 0x1f
|
||||
.align WS
|
||||
.LLEFDE1:
|
||||
.LLSFDE2:
|
||||
.uaword .LLEFDE2-.LLASFDE2 ! FDE Length
|
||||
.LLASFDE2:
|
||||
.uaword .LLASFDE2-.LLframe1 ! FDE CIE offset
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.uaword %r_disp32(.LLFB2)
|
||||
.uaword .LLFE2-.LLFB2 ! FDE address range
|
||||
#else
|
||||
.align WS
|
||||
.nword .LLFB2
|
||||
.uanword .LLFE2-.LLFB2 ! FDE address range
|
||||
#endif
|
||||
.byte 0x0 ! uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ! DW_CFA_advance_loc4
|
||||
.uaword .LLCFI1-.LLFB2
|
||||
.byte 0xd ! DW_CFA_def_cfa_register
|
||||
.byte 0x1e ! uleb128 0x1e
|
||||
.byte 0x2d ! DW_CFA_GNU_window_save
|
||||
.byte 0x9 ! DW_CFA_register
|
||||
.byte 0xf ! uleb128 0xf
|
||||
.byte 0x1f ! uleb128 0x1f
|
||||
.align WS
|
||||
.LLEFDE2:
|
||||
#endif
|
||||
E SPARC_RET_UINT8
|
||||
ldub [%i2+3], %i0
|
||||
ret
|
||||
restore
|
||||
E SPARC_RET_SINT8
|
||||
ldsb [%i2+3], %i0
|
||||
ret
|
||||
restore
|
||||
E SPARC_RET_UINT16
|
||||
lduh [%i2+2], %i0
|
||||
ret
|
||||
restore
|
||||
E SPARC_RET_SINT16
|
||||
ldsh [%i2+2], %i0
|
||||
ret
|
||||
restore
|
||||
E SPARC_RET_UINT32
|
||||
ld [%i2], %i0
|
||||
ret
|
||||
restore
|
||||
E SP_V8_RET_CPLX16
|
||||
ld [%i2], %i0
|
||||
ret
|
||||
restore
|
||||
E SPARC_RET_INT64
|
||||
ldd [%i2], %i0
|
||||
ret
|
||||
restore
|
||||
E SPARC_RET_INT128
|
||||
ldd [%i2], %i0
|
||||
ldd [%i2+8], %i2
|
||||
ret
|
||||
restore
|
||||
E SPARC_RET_F_8
|
||||
ld [%i2+7*4], %f7
|
||||
nop
|
||||
ld [%i2+6*4], %f6
|
||||
nop
|
||||
E SPARC_RET_F_6
|
||||
ld [%i2+5*4], %f5
|
||||
nop
|
||||
ld [%i2+4*4], %f4
|
||||
nop
|
||||
E SPARC_RET_F_4
|
||||
ld [%i2+3*4], %f3
|
||||
nop
|
||||
ld [%i2+2*4], %f2
|
||||
nop
|
||||
E SPARC_RET_F_2
|
||||
ldd [%i2], %f0
|
||||
ret
|
||||
restore
|
||||
E SP_V8_RET_CPLX8
|
||||
lduh [%i2], %i0
|
||||
ret
|
||||
restore
|
||||
E SPARC_RET_F_1
|
||||
ld [%i2], %f0
|
||||
ret
|
||||
restore
|
||||
|
||||
cfi_endproc
|
||||
.size C(ffi_closure_v8), . - C(ffi_closure_v8)
|
||||
#endif /* !SPARC64 */
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
|
||||
|
||||
|
||||
SPARC 64-bit Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -27,103 +27,178 @@
|
|||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <ffi_cfi.h>
|
||||
#include "internal.h"
|
||||
|
||||
#ifdef SPARC64
|
||||
|
||||
#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */
|
||||
#define C2(X, Y) X ## Y
|
||||
#define C1(X, Y) C2(X, Y)
|
||||
|
||||
#ifdef __USER_LABEL_PREFIX__
|
||||
# define C(Y) C1(__USER_LABEL_PREFIX__, Y)
|
||||
#else
|
||||
# define C(Y) Y
|
||||
#endif
|
||||
#define L(Y) C1(.L, Y)
|
||||
|
||||
.macro E index
|
||||
.align 16
|
||||
.org 2b + \index * 16
|
||||
.endm
|
||||
|
||||
#define STACK_BIAS 2047
|
||||
#define ARGS (128) /* Offset of register area in frame */
|
||||
|
||||
.text
|
||||
.text
|
||||
.align 8
|
||||
.globl ffi_call_v9
|
||||
.globl _ffi_call_v9
|
||||
.globl C(ffi_call_v9)
|
||||
.type C(ffi_call_v9),@function
|
||||
FFI_HIDDEN(C(ffi_call_v9))
|
||||
|
||||
ffi_call_v9:
|
||||
_ffi_call_v9:
|
||||
.LLFB1:
|
||||
save %sp, -STACKFRAME, %sp
|
||||
.LLCFI0:
|
||||
C(ffi_call_v9):
|
||||
cfi_startproc
|
||||
save %sp, %o4, %sp
|
||||
cfi_def_cfa_register(%fp)
|
||||
cfi_window_save
|
||||
|
||||
sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
|
||||
add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of
|
||||
! frame to set up
|
||||
mov %i0, %o0 ! copy cif
|
||||
add %sp, STACK_BIAS+128+48, %o1 ! load args area
|
||||
mov %i2, %o2 ! copy rvalue
|
||||
call C(ffi_prep_args_v9)
|
||||
mov %i3, %o3 ! copy avalue
|
||||
|
||||
mov %l0, %o0 ! call routine to set up frame
|
||||
call %i0
|
||||
mov %i1, %o1 ! (delay)
|
||||
brz,pt %o0, 1f
|
||||
ldx [%l0+ARGS], %o0 ! call foreign function
|
||||
andcc %o0, SPARC_FLAG_FP_ARGS, %g0 ! need fp regs?
|
||||
add %sp, 48, %sp ! deallocate prep frame
|
||||
be,pt %xcc, 1f
|
||||
mov %o0, %l0 ! save flags
|
||||
|
||||
ldd [%l0+ARGS], %f0
|
||||
ldd [%l0+ARGS+8], %f2
|
||||
ldd [%l0+ARGS+16], %f4
|
||||
ldd [%l0+ARGS+24], %f6
|
||||
ldd [%l0+ARGS+32], %f8
|
||||
ldd [%l0+ARGS+40], %f10
|
||||
ldd [%l0+ARGS+48], %f12
|
||||
ldd [%l0+ARGS+56], %f14
|
||||
ldd [%l0+ARGS+64], %f16
|
||||
ldd [%l0+ARGS+72], %f18
|
||||
ldd [%l0+ARGS+80], %f20
|
||||
ldd [%l0+ARGS+88], %f22
|
||||
ldd [%l0+ARGS+96], %f24
|
||||
ldd [%l0+ARGS+104], %f26
|
||||
ldd [%l0+ARGS+112], %f28
|
||||
ldd [%l0+ARGS+120], %f30
|
||||
ldd [%sp+STACK_BIAS+128], %f0 ! load all fp arg regs
|
||||
ldd [%sp+STACK_BIAS+128+8], %f2
|
||||
ldd [%sp+STACK_BIAS+128+16], %f4
|
||||
ldd [%sp+STACK_BIAS+128+24], %f6
|
||||
ldd [%sp+STACK_BIAS+128+32], %f8
|
||||
ldd [%sp+STACK_BIAS+128+40], %f10
|
||||
ldd [%sp+STACK_BIAS+128+48], %f12
|
||||
ldd [%sp+STACK_BIAS+128+56], %f14
|
||||
ldd [%sp+STACK_BIAS+128+64], %f16
|
||||
ldd [%sp+STACK_BIAS+128+72], %f18
|
||||
ldd [%sp+STACK_BIAS+128+80], %f20
|
||||
ldd [%sp+STACK_BIAS+128+88], %f22
|
||||
ldd [%sp+STACK_BIAS+128+96], %f24
|
||||
ldd [%sp+STACK_BIAS+128+104], %f26
|
||||
ldd [%sp+STACK_BIAS+128+112], %f28
|
||||
ldd [%sp+STACK_BIAS+128+120], %f30
|
||||
|
||||
1: ldx [%l0+ARGS+8], %o1
|
||||
ldx [%l0+ARGS+16], %o2
|
||||
ldx [%l0+ARGS+24], %o3
|
||||
ldx [%l0+ARGS+32], %o4
|
||||
ldx [%l0+ARGS+40], %o5
|
||||
call %i5
|
||||
sub %l0, STACK_BIAS, %sp ! (delay) switch to frame
|
||||
1: ldx [%sp+STACK_BIAS+128], %o0 ! load all int arg regs
|
||||
ldx [%sp+STACK_BIAS+128+8], %o1
|
||||
ldx [%sp+STACK_BIAS+128+16], %o2
|
||||
ldx [%sp+STACK_BIAS+128+24], %o3
|
||||
ldx [%sp+STACK_BIAS+128+32], %o4
|
||||
ldx [%sp+STACK_BIAS+128+40], %o5
|
||||
call %i1
|
||||
mov %i5, %g5 ! load static chain
|
||||
|
||||
! If the return value pointer is NULL, assume no return value.
|
||||
brz,pn %i4, done
|
||||
0: call 1f ! load pc in %o7
|
||||
and %l0, SPARC_FLAG_RET_MASK, %l1
|
||||
1: sll %l1, 4, %l1
|
||||
add %o7, %l1, %o7 ! o7 = 0b + ret_type*16
|
||||
jmp %o7+(2f-0b)
|
||||
nop
|
||||
|
||||
cmp %i3, FFI_TYPE_INT
|
||||
be,a,pt %icc, done
|
||||
stx %o0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_FLOAT
|
||||
be,a,pn %icc, done
|
||||
st %f0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_DOUBLE
|
||||
be,a,pn %icc, done
|
||||
std %f0, [%i4+0] ! (delay)
|
||||
|
||||
cmp %i3, FFI_TYPE_STRUCT
|
||||
be,pn %icc, dostruct
|
||||
|
||||
cmp %i3, FFI_TYPE_LONGDOUBLE
|
||||
bne,pt %icc, done
|
||||
.align 16
|
||||
2:
|
||||
E SPARC_RET_VOID
|
||||
return %i7+8
|
||||
nop
|
||||
std %f0, [%i4+0]
|
||||
std %f2, [%i4+8]
|
||||
E SPARC_RET_STRUCT
|
||||
add %sp, STACK_BIAS-64+128+48, %l2
|
||||
sub %sp, 64, %sp
|
||||
b 8f
|
||||
stx %o0, [%l2]
|
||||
E SPARC_RET_UINT8
|
||||
and %o0, 0xff, %i0
|
||||
return %i7+8
|
||||
stx %o0, [%o2]
|
||||
E SPARC_RET_SINT8
|
||||
sll %o0, 24, %o0
|
||||
sra %o0, 24, %i0
|
||||
return %i7+8
|
||||
stx %o0, [%o2]
|
||||
E SPARC_RET_UINT16
|
||||
sll %o0, 16, %o0
|
||||
srl %o0, 16, %i0
|
||||
return %i7+8
|
||||
stx %o0, [%o2]
|
||||
E SPARC_RET_SINT16
|
||||
sll %o0, 16, %o0
|
||||
sra %o0, 16, %i0
|
||||
return %i7+8
|
||||
stx %o0, [%o2]
|
||||
E SPARC_RET_UINT32
|
||||
srl %o0, 0, %i0
|
||||
return %i7+8
|
||||
stx %o0, [%o2]
|
||||
E SP_V9_RET_SINT32
|
||||
sra %o0, 0, %i0
|
||||
return %i7+8
|
||||
stx %o0, [%o2]
|
||||
E SPARC_RET_INT64
|
||||
stx %o0, [%i2]
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_INT128
|
||||
stx %o0, [%i2]
|
||||
stx %o1, [%i2+8]
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_F_8
|
||||
st %f7, [%i2+7*4]
|
||||
nop
|
||||
st %f6, [%i2+6*4]
|
||||
nop
|
||||
E SPARC_RET_F_6
|
||||
st %f5, [%i2+5*4]
|
||||
nop
|
||||
st %f4, [%i2+4*4]
|
||||
nop
|
||||
E SPARC_RET_F_4
|
||||
std %f2, [%i2+2*4]
|
||||
return %i7+8
|
||||
std %f0, [%o2]
|
||||
E SPARC_RET_F_2
|
||||
return %i7+8
|
||||
std %f0, [%o2]
|
||||
E SP_V9_RET_F_3
|
||||
st %f2, [%i2+2*4]
|
||||
nop
|
||||
st %f1, [%i2+1*4]
|
||||
nop
|
||||
E SPARC_RET_F_1
|
||||
return %i7+8
|
||||
st %f0, [%o2]
|
||||
|
||||
done: ret
|
||||
restore
|
||||
! Finish the SPARC_RET_STRUCT sequence.
|
||||
.align 8
|
||||
8: stx %o1, [%l2+8]
|
||||
stx %o2, [%l2+16]
|
||||
stx %o3, [%l2+24]
|
||||
std %f0, [%l2+32]
|
||||
std %f2, [%l2+40]
|
||||
std %f4, [%l2+48]
|
||||
std %f6, [%l2+56]
|
||||
|
||||
dostruct:
|
||||
/* This will not work correctly for unions. */
|
||||
stx %o0, [%i4+0]
|
||||
stx %o1, [%i4+8]
|
||||
stx %o2, [%i4+16]
|
||||
stx %o3, [%i4+24]
|
||||
std %f0, [%i4+32]
|
||||
std %f2, [%i4+40]
|
||||
std %f4, [%i4+48]
|
||||
std %f6, [%i4+56]
|
||||
ret
|
||||
restore
|
||||
.LLFE1:
|
||||
! Copy the structure into place.
|
||||
srl %l0, SPARC_SIZEMASK_SHIFT, %o0 ! load size_mask
|
||||
mov %i2, %o1 ! load dst
|
||||
mov %l2, %o2 ! load src_gp
|
||||
call C(ffi_struct_float_copy)
|
||||
add %l2, 32, %o3 ! load src_fp
|
||||
|
||||
.ffi_call_v9_end:
|
||||
.size ffi_call_v9,.ffi_call_v9_end-ffi_call_v9
|
||||
return %i7+8
|
||||
nop
|
||||
|
||||
cfi_endproc
|
||||
.size C(ffi_call_v9), . - C(ffi_call_v9)
|
||||
|
||||
|
||||
#undef STACKFRAME
|
||||
|
@ -136,15 +211,40 @@ dostruct:
|
|||
|
||||
Receives the closure argument in %g1. */
|
||||
|
||||
.text
|
||||
.align 8
|
||||
.globl ffi_closure_v9
|
||||
.globl C(ffi_go_closure_v9)
|
||||
.type C(ffi_go_closure_v9),@function
|
||||
FFI_HIDDEN(C(ffi_go_closure_v9))
|
||||
|
||||
ffi_closure_v9:
|
||||
.LLFB2:
|
||||
C(ffi_go_closure_v9):
|
||||
cfi_startproc
|
||||
save %sp, -STACKFRAME, %sp
|
||||
.LLCFI1:
|
||||
cfi_def_cfa_register(%fp)
|
||||
cfi_window_save
|
||||
|
||||
ldx [%g5+8], %o0
|
||||
ldx [%g5+16], %o1
|
||||
b 0f
|
||||
mov %g5, %o2
|
||||
|
||||
cfi_endproc
|
||||
.size C(ffi_go_closure_v9), . - C(ffi_go_closure_v9)
|
||||
|
||||
.align 8
|
||||
.globl C(ffi_closure_v9)
|
||||
.type C(ffi_closure_v9),@function
|
||||
FFI_HIDDEN(C(ffi_closure_v9))
|
||||
|
||||
C(ffi_closure_v9):
|
||||
cfi_startproc
|
||||
save %sp, -STACKFRAME, %sp
|
||||
cfi_def_cfa_register(%fp)
|
||||
cfi_window_save
|
||||
|
||||
ldx [%g1+FFI_TRAMPOLINE_SIZE], %o0
|
||||
ldx [%g1+FFI_TRAMPOLINE_SIZE+8], %o1
|
||||
ldx [%g1+FFI_TRAMPOLINE_SIZE+16], %o2
|
||||
0:
|
||||
! Store all of the potential argument registers in va_list format.
|
||||
stx %i0, [FP+128+0]
|
||||
stx %i1, [FP+128+8]
|
||||
|
@ -172,134 +272,106 @@ ffi_closure_v9:
|
|||
std %f30, [FP-8]
|
||||
|
||||
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
||||
mov %g1, %o0
|
||||
add %fp, STACK_BIAS-160, %o1
|
||||
add %fp, STACK_BIAS+128, %o2
|
||||
call ffi_closure_sparc_inner_v9
|
||||
add %fp, STACK_BIAS-128, %o3
|
||||
add %fp, STACK_BIAS-160, %o3
|
||||
add %fp, STACK_BIAS+128, %o4
|
||||
call C(ffi_closure_sparc_inner_v9)
|
||||
add %fp, STACK_BIAS-128, %o5
|
||||
|
||||
! Load up the return value in the proper type.
|
||||
! See ffi_prep_cif_machdep for the list of cases.
|
||||
cmp %o0, FFI_TYPE_VOID
|
||||
be,pn %icc, done1
|
||||
0: call 1f ! load pc in %o7
|
||||
and %o0, SPARC_FLAG_RET_MASK, %o0
|
||||
1: sll %o0, 4, %o0 ! o2 = i2 * 16
|
||||
add %o7, %o0, %o7 ! o7 = 0b + i2*16
|
||||
jmp %o7+(2f-0b)
|
||||
nop
|
||||
|
||||
cmp %o0, FFI_TYPE_INT
|
||||
be,pn %icc, integer
|
||||
|
||||
cmp %o0, FFI_TYPE_FLOAT
|
||||
be,a,pn %icc, done1
|
||||
ld [FP-160], %f0
|
||||
|
||||
cmp %o0, FFI_TYPE_DOUBLE
|
||||
be,a,pn %icc, done1
|
||||
ldd [FP-160], %f0
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
cmp %o0, FFI_TYPE_LONGDOUBLE
|
||||
be,a,pn %icc, longdouble1
|
||||
ldd [FP-160], %f0
|
||||
#endif
|
||||
|
||||
! FFI_TYPE_STRUCT
|
||||
ldx [FP-152], %i1
|
||||
ldx [FP-144], %i2
|
||||
ldx [FP-136], %i3
|
||||
ldd [FP-160], %f0
|
||||
ldd [FP-152], %f2
|
||||
ldd [FP-144], %f4
|
||||
ldd [FP-136], %f6
|
||||
|
||||
integer:
|
||||
! Note that we cannot load the data in the delay slot of
|
||||
! the return insn because the data is in the stack frame
|
||||
! that is deallocated by the return.
|
||||
.align 16
|
||||
2:
|
||||
E SPARC_RET_VOID
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_STRUCT
|
||||
ldx [FP-160], %i0
|
||||
ldd [FP-160], %f0
|
||||
b 8f
|
||||
ldx [FP-152], %i1
|
||||
E SPARC_RET_UINT8
|
||||
ldub [FP-160+7], %i0
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_SINT8
|
||||
ldsb [FP-160+7], %i0
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_UINT16
|
||||
lduh [FP-160+6], %i0
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_SINT16
|
||||
ldsh [FP-160+6], %i0
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_UINT32
|
||||
lduw [FP-160+4], %i0
|
||||
return %i7+8
|
||||
nop
|
||||
E SP_V9_RET_SINT32
|
||||
ldsw [FP-160+4], %i0
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_INT64
|
||||
ldx [FP-160], %i0
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_INT128
|
||||
ldx [FP-160], %i0
|
||||
ldx [FP-160+8], %i1
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_F_8
|
||||
ld [FP-160+7*4], %f7
|
||||
nop
|
||||
ld [FP-160+6*4], %f6
|
||||
nop
|
||||
E SPARC_RET_F_6
|
||||
ld [FP-160+5*4], %f5
|
||||
nop
|
||||
ld [FP-160+4*4], %f4
|
||||
nop
|
||||
E SPARC_RET_F_4
|
||||
ldd [FP-160], %f0
|
||||
ldd [FP-160+8], %f2
|
||||
return %i7+8
|
||||
nop
|
||||
E SPARC_RET_F_2
|
||||
ldd [FP-160], %f0
|
||||
return %i7+8
|
||||
nop
|
||||
E SP_V9_RET_F_3
|
||||
ld [FP-160+2*4], %f2
|
||||
nop
|
||||
ld [FP-160+1*4], %f1
|
||||
nop
|
||||
E SPARC_RET_F_1
|
||||
ld [FP-160], %f0
|
||||
return %i7+8
|
||||
nop
|
||||
|
||||
done1:
|
||||
ret
|
||||
restore
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
longdouble1:
|
||||
ldd [FP-152], %f2
|
||||
ret
|
||||
restore
|
||||
#endif
|
||||
.LLFE2:
|
||||
|
||||
.ffi_closure_v9_end:
|
||||
.size ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
|
||||
|
||||
#ifdef HAVE_RO_EH_FRAME
|
||||
.section ".eh_frame",#alloc
|
||||
#else
|
||||
.section ".eh_frame",#alloc,#write
|
||||
#endif
|
||||
.LLframe1:
|
||||
.uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry
|
||||
.LLSCIE1:
|
||||
.uaword 0x0 ! CIE Identifier Tag
|
||||
.byte 0x1 ! CIE Version
|
||||
.ascii "zR\0" ! CIE Augmentation
|
||||
.byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 ! sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 0xf ! CIE RA Column
|
||||
.byte 0x1 ! uleb128 0x1; Augmentation size
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.byte 0x1b ! FDE Encoding (pcrel sdata4)
|
||||
#else
|
||||
.byte 0x50 ! FDE Encoding (aligned absolute)
|
||||
#endif
|
||||
.byte 0xc ! DW_CFA_def_cfa
|
||||
.byte 0xe ! uleb128 0xe
|
||||
.byte 0xff,0xf ! uleb128 0x7ff
|
||||
.align 8
|
||||
.LLECIE1:
|
||||
.LLSFDE1:
|
||||
.uaword .LLEFDE1-.LLASFDE1 ! FDE Length
|
||||
.LLASFDE1:
|
||||
.uaword .LLASFDE1-.LLframe1 ! FDE CIE offset
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.uaword %r_disp32(.LLFB1)
|
||||
.uaword .LLFE1-.LLFB1 ! FDE address range
|
||||
#else
|
||||
.align 8
|
||||
.xword .LLFB1
|
||||
.uaxword .LLFE1-.LLFB1 ! FDE address range
|
||||
#endif
|
||||
.byte 0x0 ! uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ! DW_CFA_advance_loc4
|
||||
.uaword .LLCFI0-.LLFB1
|
||||
.byte 0xd ! DW_CFA_def_cfa_register
|
||||
.byte 0x1e ! uleb128 0x1e
|
||||
.byte 0x2d ! DW_CFA_GNU_window_save
|
||||
.byte 0x9 ! DW_CFA_register
|
||||
.byte 0xf ! uleb128 0xf
|
||||
.byte 0x1f ! uleb128 0x1f
|
||||
.align 8
|
||||
.LLEFDE1:
|
||||
.LLSFDE2:
|
||||
.uaword .LLEFDE2-.LLASFDE2 ! FDE Length
|
||||
.LLASFDE2:
|
||||
.uaword .LLASFDE2-.LLframe1 ! FDE CIE offset
|
||||
#ifdef HAVE_AS_SPARC_UA_PCREL
|
||||
.uaword %r_disp32(.LLFB2)
|
||||
.uaword .LLFE2-.LLFB2 ! FDE address range
|
||||
#else
|
||||
.align 8
|
||||
.xword .LLFB2
|
||||
.uaxword .LLFE2-.LLFB2 ! FDE address range
|
||||
#endif
|
||||
.byte 0x0 ! uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ! DW_CFA_advance_loc4
|
||||
.uaword .LLCFI1-.LLFB2
|
||||
.byte 0xd ! DW_CFA_def_cfa_register
|
||||
.byte 0x1e ! uleb128 0x1e
|
||||
.byte 0x2d ! DW_CFA_GNU_window_save
|
||||
.byte 0x9 ! DW_CFA_register
|
||||
.byte 0xf ! uleb128 0xf
|
||||
.byte 0x1f ! uleb128 0x1f
|
||||
.align 8
|
||||
.LLEFDE2:
|
||||
#endif
|
||||
! Finish the SPARC_RET_STRUCT sequence.
|
||||
.align 8
|
||||
8: ldd [FP-152], %f2
|
||||
ldx [FP-144], %i2
|
||||
ldd [FP-144], %f4
|
||||
ldx [FP-136], %i3
|
||||
ldd [FP-136], %f6
|
||||
return %i7+8
|
||||
nop
|
||||
|
||||
cfi_endproc
|
||||
.size C(ffi_closure_v9), . - C(ffi_closure_v9)
|
||||
#endif /* SPARC64 */
|
||||
#ifdef __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
void (*fnaddr)(void));
|
||||
|
||||
On entry, REG_ARGS contain the outgoing register values,
|
||||
and STACK_ARGS containts STACK_ARG_BYTES of additional values
|
||||
and STACK_ARGS contains STACK_ARG_BYTES of additional values
|
||||
to be passed on the stack. If STACK_ARG_BYTES is zero, then
|
||||
STACK_ARGS is ignored.
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue