summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgreen <green@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-04 21:11:09 +0000
committergreen <green@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-04 21:11:09 +0000
commitf51aab02abe223469d9f39e4e46250b65fd18a8b (patch)
tree3289bacfc83a97eaf50f42a61d0b9a06f4c76e9c
parentde3e3c185df5165793e9c0459732eb5c2bede7c5 (diff)
downloadgcc-f51aab02abe223469d9f39e4e46250b65fd18a8b.tar.gz
Merge upstream libffi
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184897 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libffi/ChangeLog288
-rw-r--r--libffi/LICENSE19
-rw-r--r--libffi/README54
-rwxr-xr-xlibffi/build-ios.sh67
-rw-r--r--libffi/doc/libffi.texi38
-rw-r--r--libffi/fficonfig.h.in3
-rw-r--r--libffi/include/ffi.h.in67
-rw-r--r--libffi/include/ffi_common.h16
-rw-r--r--libffi/man/ffi.310
-rw-r--r--libffi/man/ffi_prep_cif.38
-rw-r--r--libffi/man/ffi_prep_cif_var.373
-rwxr-xr-xlibffi/msvcc.sh28
-rw-r--r--libffi/src/alpha/ffi.c6
-rw-r--r--libffi/src/alpha/ffitarget.h7
-rw-r--r--libffi/src/arm/ffi.c260
-rw-r--r--libffi/src/arm/ffitarget.h12
-rwxr-xr-xlibffi/src/arm/gentramp.sh118
-rw-r--r--libffi/src/arm/sysv.S45
-rw-r--r--libffi/src/arm/trampoline.S4450
-rw-r--r--libffi/src/avr32/ffi.c6
-rw-r--r--libffi/src/avr32/ffitarget.h11
-rw-r--r--libffi/src/closures.c23
-rw-r--r--libffi/src/cris/ffi.c15
-rw-r--r--libffi/src/cris/ffitarget.h11
-rw-r--r--libffi/src/dlmalloc.c3
-rw-r--r--libffi/src/frv/ffitarget.h15
-rw-r--r--libffi/src/ia64/ffi.c4
-rw-r--r--libffi/src/ia64/ffitarget.h11
-rw-r--r--libffi/src/java_raw_api.c2
-rw-r--r--libffi/src/m32r/ffitarget.h11
-rw-r--r--libffi/src/m68k/ffi.c3
-rw-r--r--libffi/src/m68k/ffitarget.h11
-rw-r--r--libffi/src/mips/ffi.c17
-rw-r--r--libffi/src/mips/ffitarget.h28
-rw-r--r--libffi/src/pa/ffi.c11
-rw-r--r--libffi/src/pa/ffitarget.h18
-rw-r--r--libffi/src/powerpc/aix.S6
-rw-r--r--libffi/src/powerpc/aix_closure.S2
-rw-r--r--libffi/src/powerpc/asm.h2
-rw-r--r--libffi/src/powerpc/darwin.S2
-rw-r--r--libffi/src/powerpc/darwin_closure.S2
-rw-r--r--libffi/src/powerpc/ffi.c630
-rw-r--r--libffi/src/powerpc/ffitarget.h24
-rw-r--r--libffi/src/powerpc/ppc_closure.S19
-rw-r--r--libffi/src/powerpc/sysv.S27
-rw-r--r--libffi/src/prep_cif.c68
-rw-r--r--libffi/src/s390/ffitarget.h11
-rw-r--r--libffi/src/sh/ffitarget.h11
-rw-r--r--libffi/src/sh64/ffitarget.h11
-rw-r--r--libffi/src/sparc/ffi.c66
-rw-r--r--libffi/src/sparc/ffitarget.h13
-rw-r--r--libffi/src/sparc/v9.S2
-rw-r--r--libffi/src/x86/ffi.c50
-rw-r--r--libffi/src/x86/ffi64.c22
-rw-r--r--libffi/src/x86/ffitarget.h38
-rw-r--r--libffi/src/x86/win32.S30
-rw-r--r--libffi/src/x86/win64.S22
-rw-r--r--libffi/testsuite/libffi.call/cls_double_va.c6
-rw-r--r--libffi/testsuite/libffi.call/cls_longdouble_va.c7
-rw-r--r--libffi/testsuite/libffi.call/err_bad_abi.c3
-rw-r--r--libffi/testsuite/libffi.call/err_bad_typedef.c3
-rw-r--r--libffi/testsuite/libffi.call/float_va.c107
-rw-r--r--libffi/testsuite/libffi.call/return_sc.c2
63 files changed, 6319 insertions, 636 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 76fb1d4fbf0..bb5bc1625ce 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,37 +1,36 @@
-2012-02-27 Mikael Pettersson <mikpe@it.uu.se>
+2012-03-03 H.J. Lu <hongjiu.lu@intel.com>
- PR libffi/52223
- * Makefile.am (FLAGS_TO_PASS): Define.
- * Makefile.in: Regenerate.
+ * src/x86/ffi64.c (ffi_call): Cast the return value to unsigned
+ long.
+ (ffi_prep_closure_loc): Cast to 64bit address in trampoline.
+ (ffi_closure_unix64_inner): Cast return pointer to unsigned long
+ first.
+
+ * src/x86/ffitarget.h (FFI_SIZEOF_ARG): Defined to 8 for x32.
+ (ffi_arg): Set to unsigned long long for x32.
+ (ffi_sarg): Set to long long for x32.
-2012-02-23 Kai Tietz <ktietz@redhat.com>
+2012-03-03 H.J. Lu <hongjiu.lu@intel.com>
- PR libffi/52221
- * src/x86/ffi.c (ffi_closure_raw_THISCALL): New
- prototype.
- (ffi_prep_raw_closure_loc): Use ffi_closure_raw_THISCALL for
- thiscall-convention.
- (ffi_raw_call): Use ffi_prep_args_raw.
- * src/x86/win32.S (ffi_closure_raw_THISCALL): Add
- implementation for stub.
+ * src/prep_cif.c (ffi_prep_cif_core): Properly check bad ABI.
-2012-02-13 Kai Tietz <ktietz@redhat.com>
+2012-03-03 Andoni Morales Alastruey <ylatuya@gmail.com>
- PR libffi/52221
- * src/x86/ffi.c (ffi_prep_raw_closure_loc): Add thiscall
- support for X86_WIN32.
- (FFI_INIT_TRAMPOLINE_THISCALL): Fix displacement.
+ * configure.ac: Add -no-undefined for both 32- and 64-bit x86
+ windows-like hosts.
+ * configure: Rebuilt.
-2012-02-11 Eric Botcazou <ebotcazou@adacore.com>
+2012-02-23 Anthony Green <green@moxielogic.com>
- * src/sparc/v9.S (STACKFRAME): Bump to 176.
+ * src/*/ffitarget.h: Ensure that users never include ffitarget.h
+ directly.
2012-02-10 Kai Tietz <ktietz@redhat.com>
* configure.ac (AM_LTLDFLAGS): Add -no-undefine for x64
windows target.
* configure: Regenerated.
-
+
2012-02-08 Kai Tietz <ktietz@redhat.com>
* src/prep_cif.c (ffi_prep_cif): Allow for X86_WIN32
@@ -63,6 +62,20 @@
* testsuite/libffi.call/struct1_win32.c: New test.
* testsuite/libffi.call/struct2_win32.c: New test.
+2012-01-23 Uros Bizjak <ubizjak@gmail.com>
+
+ * src/alpha/ffi.c (ffi_prep_closure_loc): Check for bad ABI.
+
+2012-01-23 Anthony Green <green@moxielogic.com>
+ Chris Young <cdyoung@ntlworld.com>
+
+ * configure.ac: Add Amiga support.
+ * configure: Rebuilt.
+
+2012-01-23 Dmitry Nadezhin <dmitry.nadezhin@gmail.com>
+
+ * include/ffi_common.h (LIKELY, UNLIKELY): Fix definitions.
+
2012-01-23 Andreas Schwab <schwab@linux-m68k.org>
* src/m68k/sysv.S (ffi_call_SYSV): Properly test for plain
@@ -87,6 +100,67 @@
* configure: Regenerate.
+2011-11-12 David Gilbert <david.gilbert@linaro.org>
+
+ * doc/libffi.texi, include/ffi.h.in, include/ffi_common.h,
+ man/Makefile.am, man/ffi.3, man/ffi_prep_cif.3,
+ man/ffi_prep_cif_var.3, src/arm/ffi.c, src/arm/ffitarget.h,
+ src/cris/ffi.c, src/prep_cif.c,
+ testsuite/libffi.call/cls_double_va.c,
+ testsuite/libffi.call/cls_longdouble_va.c,
+ testsuite/libffi.call/float_va.c: Many changes to support variadic
+ function calls.
+
+2011-11-12 Kyle Moffett <Kyle.D.Moffett@boeing.com>
+
+ * src/powerpc/ffi.c, src/powerpc/ffitarget.h,
+ src/powerpc/ppc_closure.S, src/powerpc/sysv.S: Many changes for
+ softfloat powerpc variants.
+
+2011-11-12 Petr Salinger <Petr.Salinger@seznam.cz>
+
+ * configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support.
+ * configure: Rebuilt.
+
+2011-11-12 Timothy Wall <twall@users.sf.net>
+
+ * src/arm/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV): Max
+ alignment of 4 for wince on ARM.
+
+2011-11-12 Kyle Moffett <Kyle.D.Moffett@boeing.com>
+ Anthony Green <green@moxielogic.com>
+
+ * src/ppc/sysv.S, src/ppc/ffi.c: Remove use of ppc string
+ instructions (not available on some cores, like the PPC440).
+
+2011-11-12 Kimura Wataru <kimuraw@i.nifty.jp>
+
+ * m4/ax_enable_builddir: Change from string comparison to numeric
+ comparison for wc output.
+ * configure.ac: Enable FFI_MMAP_EXEC_WRIT for darwin11 aka Mac OS
+ X 10.7.
+ * configure: Rebuilt.
+
+2011-11-12 Anthony Green <green@moxielogic.com>
+
+ * Makefile.am (AM_CCASFLAGS): Add -g option to build assembly
+ files with debug info.
+ * Makefile.in: Rebuilt.
+
+2011-11-12 Jasper Lievisse Adriaanse <jasper@openbsd.org>
+
+ * README: Update list of supported OpenBSD systems.
+
+2011-11-12 Anthony Green <green@moxielogic.com>
+
+ * libtool-version: Update.
+ * Makefile.am (nodist_libffi_la_SOURCES): Add src/debug.c if
+ FFI_DEBUG.
+ (libffi_la_SOURCES): Remove src/debug.c
+ (EXTRA_DIST): Add src/debug.c
+ * Makefile.in: Rebuilt.
+ * README: Update for 3.0.11.
+
2011-11-10 Richard Henderson <rth@redhat.com>
* configure.ac (GCC_AS_CFI_PSEUDO_OP): Use it instead of inline check.
@@ -135,10 +209,127 @@
Use them to handle ELF vs. ECOFF differences.
[__osf__] (_GLOBAL__F_ffi_call_osf): Define.
+2011-03-30 Timothy Wall <twall@users.sf.net>
+
+ * src/powerpc/darwin.S: Fix unknown FDE encoding.
+ * src/powerpc/darwin_closure.S: ditto.
+
+2011-02-25 Anthony Green <green@moxielogic.com>
+
+ * src/powerpc/ffi.c (ffi_prep_closure_loc): Allow for more
+ 32-bit ABIs.
+
+2011-02-15 Anthony Green <green@moxielogic.com>
+
+ * m4/ax_cc_maxopt.m4: Don't -malign-double or use -ffast-math.
+ * configure: Rebuilt.
+
2011-02-13 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* configure: Regenerate.
+2011-02-13 Anthony Green <green@moxielogic.com>
+
+ * include/ffi_common.h (UNLIKELY, LIKELY): Define.
+ * src/x86/ffi64.c (UNLIKELY, LIKELY): Remove definition.
+ * src/prep_cif.c (UNLIKELY, LIKELY): Remove definition.
+
+ * src/prep_cif.c (initialize_aggregate): Convert assertion into
+ FFI_BAD_TYPEDEF return. Initialize arg size and alignment to 0.
+
+ * src/pa/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test,
+ just return FFI_BAD_ABI when things are wrong.
+ * src/arm/ffi.c (ffi_prep_closure_loc): Ditto.
+ * src/powerpc/ffi.c (ffi_prep_closure_loc): Ditto.
+ * src/mips/ffi.c (ffi_prep_closure_loc): Ditto.
+ * src/ia64/ffi.c (ffi_prep_closure_loc): Ditto.
+ * src/avr32/ffi.c (ffi_prep_closure_loc): Ditto.
+
+2011-02-11 Anthony Green <green@moxielogic.com>
+
+ * src/sparc/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test,
+ just return FFI_BAD_ABI when things are wrong.
+
+2011-02-09 Stuart Shelton <srcshelton@gmail.com>
+
+ http://bugs.gentoo.org/show_bug.cgi?id=286911
+ * src/mips/ffitarget.h: Clean up error messages.
+ * src/java_raw_api.c (ffi_java_translate_args): Cast raw arg to
+ ffi_raw*.
+ * include/ffi.h.in: Add pragma for SGI compiler.
+
+2011-02-09 Anthony Green <green@moxielogic.com>
+
+ * configure.ac: Add powerpc64-*-darwin* support.
+
+2011-02-09 Anthony Green <green@moxielogic.com>
+
+ * README: Mention Interix.
+
+2011-02-09 Jonathan Callen <abcd@gentoo.org>
+
+ * configure.ac: Add Interix to win32/cygwin/mingw case.
+ * configure: Ditto.
+ * src/closures.c: Treat Interix like Cygwin, instead of as a
+ generic win32.
+
+2011-02-09 Anthony Green <green@moxielogic.com>
+
+ * testsuite/libffi.call/err_bad_typedef.c: Remove xfail.
+ * testsuite/libffi.call/err_bad_abi.c: Remove xfail.
+ * src/x86/ffi64.c (UNLIKELY, LIKELY): Define.
+ (ffi_prep_closure_loc): Check for bad ABI.
+ * src/prep_cif.c (UNLIKELY, LIKELY): Define.
+ (initialize_aggregate): Check for bad types.
+
+2011-02-09 Landon Fuller <landonf@plausible.coop>
+
+ * Makefile.am (EXTRA_DIST): Add build-ios.sh, src/arm/gentramp.sh,
+ src/arm/trampoline.S.
+ (nodist_libffi_la_SOURCES): Add src/arc/trampoline.S.
+ * configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Define.
+ * src/arm/ffi.c (ffi_trampoline_table)
+ (ffi_closure_trampoline_table_page, ffi_trampoline_table_entry)
+ (FFI_TRAMPOLINE_CODELOC_CONFIG, FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET)
+ (FFI_TRAMPOLINE_COUNT, ffi_trampoline_lock, ffi_trampoline_tables)
+ (ffi_trampoline_table_alloc, ffi_closure_alloc, ffi_closure_free):
+ Define for FFI_EXEC_TRAMPOLINE_TABLE case (iOS).
+ (ffi_prep_closure_loc): Handl FFI_EXEC_TRAMPOLINE_TABLE case
+ separately.
+ * src/arm/sysv.S: Handle Apple iOS host.
+ * src/closures.c: Handle FFI_EXEC_TRAMPOLINE_TABLE case.
+ * build-ios.sh: New file.
+ * fficonfig.h.in, configure, Makefile.in: Rebuilt.
+ * README: Mention ARM iOS.
+
+2011-02-08 Oren Held <orenhe@il.ibm.com>
+
+ * src/dlmalloc.c (_STRUCT_MALLINFO): Define in order to avoid
+ redefinition of mallinfo on HP-UX.
+
+2011-02-08 Ginn Chen <ginn.chen@oracle.com>
+
+ * src/sparc/ffi.c (ffi_call): Make compatible with Solaris Studio
+ aggregate return ABI. Flush cache.
+ (ffi_prep_closure_loc): Flush cache.
+
+2011-02-11 Anthony Green <green@moxielogic.com>
+
+ From Tom Honermann <tom.honermann@oracle.com>:
+ * src/powerpc/aix.S (ffi_call_AIX): Support for xlc toolchain on
+ AIX. Declare .ffi_prep_args. Insert nops after branch
+ instructions so that the AIX linker can insert TOC reload
+ instructions.
+ * src/powerpc/aix_closure.S: Declare .ffi_closure_helper_DARWIN.
+
+2011-02-08 Ed <ed@kdtc.net>
+
+ * src/powerpc/asm.h: Fix grammar nit in comment.
+
+2011-02-08 Uli Link <ul.mcamafia@linkitup.de>
+
+ * include/ffi.h.in (FFI_64_BIT_MAX): Define and use.
+
2011-02-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR libffi/46661
@@ -146,6 +337,11 @@
uintptr_t first.
* testsuite/libffi.call/cls_pointer_stack.c (main): Likewise.
+2011-02-08 Rafael Avila de Espindola <respindola@mozilla.com>
+
+ * configure.ac: Fix x86 test for pc related relocs.
+ * configure: Rebuilt.
+
2011-02-07 Joel Sherrill <joel.sherrill@oarcorp.com>
* libffi/src/m68k/ffi.c: Add RTEMS support for cache flushing.
@@ -204,6 +400,13 @@
(.eh_frame): Use FDE_ENCODING.
(.LASFDE1, .LASFDE2, LASFDE3): Simplify with FDE_ENCODE.
+2010-11-22 Jacek Caban <jacek@codeweavers.com>
+
+ * configure.ac: Check for symbol underscores on mingw-w64.
+ * configure: Rebuilt.
+ * src/x86/win64.S: Correctly access extern symbols in respect to
+ underscores.
+
2010-11-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* testsuite/lib/libffi-dg.exp: Rename ...
@@ -271,6 +474,31 @@
* testsuite/libffi.call/cls_longdouble.c: Likewise.
* testsuite/libffi.call/huge_struct.c: Likewise.
+2010-08-05 Dan Witte <dwitte@mozilla.com>
+
+ * Makefile.am: Pass FFI_DEBUG define to msvcc.sh for linking to the
+ debug CRT when --enable-debug is given.
+ * configure.ac: Define it.
+ * msvcc.sh: Translate -g and -DFFI_DEBUG appropriately.
+
+2010-08-04 Dan Witte <dwitte@mozilla.com>
+
+ * src/x86/ffitarget.h: Add X86_ANY define for all x86/x86_64
+ platforms.
+ * src/x86/ffi.c: Remove redundant ifdef checks.
+ * src/prep_cif.c: Push stack space computation into src/x86/ffi.c
+ for X86_ANY so return value space doesn't get added twice.
+
+2010-08-03 Neil Rashbrooke <neil@parkwaycc.co.uk>
+
+ * msvcc.sh: Don't pass -safeseh to ml64 because behavior is buggy.
+
+2010-07-22 Dan Witte <dwitte@mozilla.com>
+
+ * src/*/ffitarget.h: Make FFI_LAST_ABI one past the last valid ABI.
+ * src/prep_cif.c: Fix ABI assertion.
+ * src/cris/ffi.c: Ditto.
+
2010-07-10 Evan Phoenix <evan@fallingsnow.net>
* src/closures.c (selinux_enabled_check): Fix strncmp usage bug.
@@ -302,6 +530,14 @@
* fficonfig.h.in: Regenerate.
* src/x86/sysv.S (.eh_frame): Use .ascii, .string or error.
+2010-05-11 Dan Witte <dwitte@mozilla.com>
+
+ * doc/libffi.tex: Document previous change.
+
+2010-05-11 Makoto Kato <m_kato@ga2.so-net.ne.jp>
+
+ * src/x86/ffi.c (ffi_call): Don't copy structs passed by value.
+
2010-05-05 Michael Kohler <michaelkohler@live.com>
* src/dlmalloc.c (dlfree): Fix spelling.
@@ -337,6 +573,11 @@
* man/Makefile.in: Regenerate.
* testsuite/Makefile.in: Regenerate.
+2010-03-30 Dan Witte <dwitte@mozilla.com>
+
+ * msvcc.sh: Disable build warnings.
+ * README (tested): Clarify windows build procedure.
+
2010-03-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac (libffi_cv_as_x86_64_unwind_section_type): New test.
@@ -711,6 +952,11 @@
* man/Makefile.in: Regenerate.
* testsuite/Makefile.in: Regenerate.
+2011-08-22 Jasper Lievisse Adriaanse <jasper@openbsd.org>
+
+ * configure.ac: Add OpenBSD/hppa and OpenBSD/powerpc support.
+ * configure: Rebuilt.
+
2009-07-30 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* configure.ac (_AC_ARG_VAR_PRECIOUS): Use m4_rename_force.
diff --git a/libffi/LICENSE b/libffi/LICENSE
index f591795152d..aa60342dfcc 100644
--- a/libffi/LICENSE
+++ b/libffi/LICENSE
@@ -1,4 +1,5 @@
-libffi - Copyright (c) 1996-2003 Red Hat, Inc.
+libffi - Copyright (c) 1996-2012 Anthony Green, Red Hat, Inc and others.
+See source files for details.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -8,13 +9,13 @@ 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 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
+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 CYGNUS SOLUTIONS 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.
+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.
diff --git a/libffi/README b/libffi/README
index 3e3ab3fc950..1da4e89c736 100644
--- a/libffi/README
+++ b/libffi/README
@@ -1,10 +1,7 @@
-This directory contains the libffi package, which is not part of GCC but
-shipped with GCC as convenience.
-
Status
======
-libffi-3.0.9 was released on December 31, 2009. Check the libffi web
+libffi-3.0.11 was released on *****************. Check the libffi web
page for updates: <URL:http://sourceware.org/libffi/>.
@@ -46,7 +43,7 @@ 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.9
+ http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
At the time of release, the following basic configurations have been
tested:
@@ -55,13 +52,18 @@ tested:
| Architecture | Operating System |
|--------------+------------------|
| Alpha | Linux |
+| Alpha | Tru64 |
| ARM | Linux |
+| ARM | iOS |
| AVR32 | Linux |
| HPPA | HPUX |
| IA-64 | Linux |
+| M68K | RTEMS |
| MIPS | IRIX |
| MIPS | Linux |
+| MIPS | RTEMS |
| MIPS64 | Linux |
+| PowerPC | AMIGA |
| PowerPC | Linux |
| PowerPC | Mac OSX |
| PowerPC | FreeBSD |
@@ -73,8 +75,10 @@ tested:
| SPARC64 | Linux |
| SPARC64 | FreeBSD |
| X86 | FreeBSD |
+| X86 | Interix |
| X86 | kFreeBSD |
| X86 | Linux |
+| X86 | Linux/x32 |
| X86 | Mac OSX |
| X86 | OpenBSD |
| X86 | OS/2 |
@@ -84,6 +88,7 @@ tested:
| X86-64 | FreeBSD |
| X86-64 | Linux |
| X86-64 | OpenBSD |
+| X86-64 | Windows/MingW |
|--------------+------------------|
Please send additional platform test results to
@@ -115,9 +120,15 @@ 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 --enable-shared --enable-static \
- CC=path/to/msvcc.sh LD=link \
- CPP=\"cl -nologo -EP\"
+path/to/configure CC=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 iOS builds, refer to the build-ios.sh script for guidance.
Configure has many other options. Use "configure --help" to see them all.
@@ -135,11 +146,27 @@ History
See the ChangeLog files for details.
-3.0.10 ???-??-??
+3.0.11 MMM-DD-YY
+ Lots of build fixes.
+ Add Amiga newer MacOS support.
+ Add Linux/x32 support.
+ Add thiscall and fastcall support on Windows.
+ Fix Octeon and MC68881 support.
+ Fix code pessimizations.
+
+3.0.10 Aug-23-11
+ Add support for Apple's iOS.
+ Add support for ARM VFP ABI.
+ Add RTEMS support for MIPS and M68K.
+ Fix instruction cache clearing problems on
+ ARM and SPARC.
Fix the N64 build on mips-sgi-irix6.5.
- Testsuite fixes for Tru64 Unix.
Enable builds with Microsoft's compiler.
- Enable x86 builds with Sun's compiler.
+ Enable x86 builds with Oracle's Solaris compiler.
+ Fix support for calling code compiled with Oracle's Sparc
+ Solaris compiler.
+ Testsuite fixes for Tru64 Unix.
+ Additional platform support.
3.0.9 Dec-31-09
Add AVR32 and win64 ports. Add ARM softfp support.
@@ -320,5 +347,6 @@ Alex Oliva solved the executable page problem for SElinux.
The list above is almost certainly incomplete and inaccurate. I'm
happy to make corrections or additions upon request.
-If you have a problem, or have found a bug, please send a note to
-green@redhat.com.
+If you have a problem, or have found a bug, please send a note to the
+author at green@moxielogic.com, or the project mailing list at
+libffi-discuss@sourceware.org.
diff --git a/libffi/build-ios.sh b/libffi/build-ios.sh
new file mode 100755
index 00000000000..3dea242255e
--- /dev/null
+++ b/libffi/build-ios.sh
@@ -0,0 +1,67 @@
+#!/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"
diff --git a/libffi/doc/libffi.texi b/libffi/doc/libffi.texi
index cbd78aa928f..f0e6517de16 100644
--- a/libffi/doc/libffi.texi
+++ b/libffi/doc/libffi.texi
@@ -19,7 +19,7 @@
This manual is for Libffi, a portable foreign-function interface
library.
-Copyright @copyright{} 2008, 2010 Red Hat, Inc.
+Copyright @copyright{} 2008, 2010, 2011 Red Hat, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -133,8 +133,6 @@ This initializes @var{cif} according to the given parameters.
you want. @ref{Multiple ABIs} for more information.
@var{nargs} is the number of arguments that this function accepts.
-@samp{libffi} does not yet handle varargs functions; see @ref{Missing
-Features} for more information.
@var{rtype} is a pointer to an @code{ffi_type} structure that
describes the return type of the function. @xref{Types}.
@@ -150,6 +148,30 @@ objects is incorrect; or @code{FFI_BAD_ABI} if the @var{abi} parameter
is invalid.
@end defun
+If the function being called is variadic (varargs) then
+@code{ffi_prep_cif_var} must be used instead of @code{ffi_prep_cif}.
+
+@findex ffi_prep_cif_var
+@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi var{abi}, unsigned int @var{nfixedargs}, unsigned int var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes})
+This initializes @var{cif} according to the given parameters for
+a call to a variadic function. In general it's operation is the
+same as for @code{ffi_prep_cif} except that:
+
+@var{nfixedargs} is the number of fixed arguments, prior to any
+variadic arguments. It must be greater than zero.
+
+@var{ntotalargs} the total number of arguments, including variadic
+and fixed arguments.
+
+Note that, different cif's must be prepped for calls to the same
+function when different numbers of arguments are passed.
+
+Also note that a call to @code{ffi_prep_cif_var} with
+@var{nfixedargs}=@var{nototalargs} is NOT equivalent to a call to
+@code{ffi_prep_cif}.
+
+@end defun
+
To call a function using an initialized @code{ffi_cif}, use the
@code{ffi_call} function:
@@ -171,7 +193,9 @@ discarded.
@var{avalues} is a vector of @code{void *} pointers that point to the
memory locations holding the argument values for a call. If @var{cif}
declares that the function has no arguments (i.e., @var{nargs} was 0),
-then @var{avalues} is ignored.
+then @var{avalues} is ignored. Note that argument values may be
+modified by the callee (for instance, structs passed by value); the
+burden of copying pass-by-value arguments is placed on the caller.
@end defun
@@ -570,9 +594,7 @@ support for these.
@itemize @bullet
@item
-There is no support for calling varargs functions. This may work on
-some platforms, depending on how the ABI is defined, but it is not
-reliable.
+Variadic closures.
@item
There is no support for bit fields in structures.
@@ -589,6 +611,8 @@ The ``raw'' API is undocumented.
@c anything else?
@end itemize
+Note that variadic support is very new and tested on a relatively
+small number of platforms.
@node Index
@unnumbered Index
diff --git a/libffi/fficonfig.h.in b/libffi/fficonfig.h.in
index e012ebba84b..b54b273f957 100644
--- a/libffi/fficonfig.h.in
+++ b/libffi/fficonfig.h.in
@@ -17,6 +17,9 @@
/* Define this if you want extra debugging. */
#undef FFI_DEBUG
+/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
+#undef FFI_EXEC_TRAMPOLINE_TABLE
+
/* Cannot use malloc on this target, so, we revert to alternative means */
#undef FFI_MMAP_EXEC_WRIT
diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in
index 92e38c42f2d..84017f1f445 100644
--- a/libffi/include/ffi.h.in
+++ b/libffi/include/ffi.h.in
@@ -1,16 +1,17 @@
/* -----------------------------------------------------------------*-C-*-
- libffi @VERSION@ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
+ libffi @VERSION@ - Copyright (c) 2011 Anthony Green
+ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, 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:
+ 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 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
@@ -77,15 +78,31 @@ extern "C" {
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
But we can find it either under the correct ANSI name, or under GNU
C's internal name. */
+
+#define FFI_64_BIT_MAX 9223372036854775807
+
#ifdef LONG_LONG_MAX
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
#else
# ifdef LLONG_MAX
# define FFI_LONG_LONG_MAX LLONG_MAX
+# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
+# undef FFI_64_BIT_MAX
+# define FFI_64_BIT_MAX 9223372036854775807LL
+# endif /* _AIX52 or newer */
# else
# ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif
+# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
+# ifndef __PPC64__
+# if defined (__IBMC__) || defined (__IBMCPP__)
+# define FFI_LONG_LONG_MAX LONGLONG_MAX
+# endif
+# endif /* __PPC64__ */
+# undef FFI_64_BIT_MAX
+# define FFI_64_BIT_MAX 9223372036854775807LL
+# endif
# endif
#endif
@@ -132,17 +149,17 @@ typedef struct _ffi_type
#endif
#if LONG_MAX == 2147483647
-# if FFI_LONG_LONG_MAX != 9223372036854775807
+# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
#error "no 64-bit data type supported"
# endif
-#elif LONG_MAX != 9223372036854775807
+#elif LONG_MAX != FFI_64_BIT_MAX
#error "long size not supported"
#endif
#if LONG_MAX == 2147483647
# define ffi_type_ulong ffi_type_uint32
# define ffi_type_slong ffi_type_sint32
-#elif LONG_MAX == 9223372036854775807
+#elif LONG_MAX == FFI_64_BIT_MAX
# define ffi_type_ulong ffi_type_uint64
# define ffi_type_slong ffi_type_sint64
#else
@@ -190,12 +207,21 @@ typedef struct {
#endif
} ffi_cif;
+/* Used internally, but overridden by some architectures */
+ffi_status ffi_prep_cif_core(ffi_cif *cif,
+ ffi_abi abi,
+ unsigned int isvariadic,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs,
+ ffi_type *rtype,
+ ffi_type **atypes);
+
/* ---- Definitions for the raw API -------------------------------------- */
#ifndef FFI_SIZEOF_ARG
# if LONG_MAX == 2147483647
# define FFI_SIZEOF_ARG 4
-# elif LONG_MAX == 9223372036854775807
+# elif LONG_MAX == FFI_64_BIT_MAX
# define FFI_SIZEOF_ARG 8
# endif
#endif
@@ -265,6 +291,9 @@ typedef struct {
} ffi_closure __attribute__((aligned (8)));
#else
} ffi_closure;
+# ifdef __sgi
+# pragma pack 0
+# endif
#endif
void *ffi_closure_alloc (size_t size, void **code);
@@ -283,6 +312,9 @@ ffi_prep_closure_loc (ffi_closure*,
void *user_data,
void*codeloc);
+#ifdef __sgi
+# pragma pack 8
+#endif
typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE];
@@ -361,6 +393,13 @@ ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_type *rtype,
ffi_type **atypes);
+ffi_status ffi_prep_cif_var(ffi_cif *cif,
+ ffi_abi abi,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs,
+ ffi_type *rtype,
+ ffi_type **atypes);
+
void ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
diff --git a/libffi/include/ffi_common.h b/libffi/include/ffi_common.h
index 42cace91502..c179d68157b 100644
--- a/libffi/include/ffi_common.h
+++ b/libffi/include/ffi_common.h
@@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
- ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
- Copyright (C) 2007 Free Software Foundation, Inc
-
+ ffi_common.h - Copyright (C) 2011, 2012 Anthony Green
+ Copyright (C) 2007 Free Software Foundation, Inc
+ Copyright (c) 1996 Red Hat, Inc.
+
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
@@ -74,6 +75,8 @@ void ffi_type_test(ffi_type *a, char *file, int line);
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
+ unsigned int nfixedargs, unsigned int ntotalargs);
/* Extended cif, used in callback from assembly routine */
typedef struct
@@ -112,11 +115,14 @@ typedef signed int SINT64 __attribute__((__mode__(__DI__)));
typedef float FLOAT32;
+#ifndef __GNUC__
+#define __builtin_expect(x, expected_value) (x)
+#endif
+#define LIKELY(x) __builtin_expect(!!(x),1)
+#define UNLIKELY(x) __builtin_expect((x)!=0,0)
#ifdef __cplusplus
}
#endif
#endif
-
-
diff --git a/libffi/man/ffi.3 b/libffi/man/ffi.3
index 18b5d5d2d4a..1f1d3031c99 100644
--- a/libffi/man/ffi.3
+++ b/libffi/man/ffi.3
@@ -16,6 +16,15 @@ libffi, -lffi
.Fa "ffi_type **atypes"
.Fc
.Ft void
+.Fo ffi_prep_cif_var
+.Fa "ffi_cif *cif"
+.Fa "ffi_abi abi"
+.Fa "unsigned int nfixedargs"
+.Fa "unsigned int ntotalargs"
+.Fa "ffi_type *rtype"
+.Fa "ffi_type **atypes"
+.Fc
+.Ft void
.Fo ffi_call
.Fa "ffi_cif *cif"
.Fa "void (*fn)(void)"
@@ -28,4 +37,5 @@ generate a call to another function at runtime without requiring knowledge of
the called function's interface at compile time.
.Sh SEE ALSO
.Xr ffi_prep_cif 3 ,
+.Xr ffi_prep_cif_var 3 ,
.Xr ffi_call 3
diff --git a/libffi/man/ffi_prep_cif.3 b/libffi/man/ffi_prep_cif.3
index 9436b31191e..e1bdbd7c46a 100644
--- a/libffi/man/ffi_prep_cif.3
+++ b/libffi/man/ffi_prep_cif.3
@@ -37,7 +37,9 @@ structs that describe the data type, size and alignment of each argument.
points to an
.Nm ffi_type
that describes the data type, size and alignment of the
-return value.
+return value. Note that to call a variadic function
+.Nm ffi_prep_cif_var
+must be used instead.
.Sh RETURN VALUES
Upon successful completion,
.Nm ffi_prep_cif
@@ -63,4 +65,6 @@ defined in
.
.Sh SEE ALSO
.Xr ffi 3 ,
-.Xr ffi_call 3
+.Xr ffi_call 3 ,
+.Xr ffi_prep_cif_var 3
+
diff --git a/libffi/man/ffi_prep_cif_var.3 b/libffi/man/ffi_prep_cif_var.3
new file mode 100644
index 00000000000..7e19d0b070f
--- /dev/null
+++ b/libffi/man/ffi_prep_cif_var.3
@@ -0,0 +1,73 @@
+.Dd January 25, 2011
+.Dt ffi_prep_cif_var 3
+.Sh NAME
+.Nm ffi_prep_cif_var
+.Nd Prepare a
+.Nm ffi_cif
+structure for use with
+.Nm ffi_call
+for variadic functions.
+.Sh SYNOPSIS
+.In ffi.h
+.Ft ffi_status
+.Fo ffi_prep_cif_var
+.Fa "ffi_cif *cif"
+.Fa "ffi_abi abi"
+.Fa "unsigned int nfixedargs"
+.Fa "unsigned int ntotalargs"
+.Fa "ffi_type *rtype"
+.Fa "ffi_type **atypes"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm ffi_prep_cif_var
+function prepares a
+.Nm ffi_cif
+structure for use with
+.Nm ffi_call
+for variadic functions.
+.Fa abi
+specifies a set of calling conventions to use.
+.Fa atypes
+is an array of
+.Fa ntotalargs
+pointers to
+.Nm ffi_type
+structs that describe the data type, size and alignment of each argument.
+.Fa rtype
+points to an
+.Nm ffi_type
+that describes the data type, size and alignment of the
+return value.
+.Fa nfixedargs
+must contain the number of fixed (non-variadic) arguments.
+Note that to call a non-variadic function
+.Nm ffi_prep_cif
+must be used.
+.Sh RETURN VALUES
+Upon successful completion,
+.Nm ffi_prep_cif_var
+returns
+.Nm FFI_OK .
+It will return
+.Nm FFI_BAD_TYPEDEF
+if
+.Fa cif
+is
+.Nm NULL
+or
+.Fa atypes
+or
+.Fa rtype
+is malformed. If
+.Fa abi
+does not refer to a valid ABI,
+.Nm FFI_BAD_ABI
+will be returned. Available ABIs are
+defined in
+.Nm <ffitarget.h>
+.
+.Sh SEE ALSO
+.Xr ffi 3 ,
+.Xr ffi_call 3 ,
+.Xr ffi_prep_cif 3
diff --git a/libffi/msvcc.sh b/libffi/msvcc.sh
index 551c73d9655..dcdbeab16ae 100755
--- a/libffi/msvcc.sh
+++ b/libffi/msvcc.sh
@@ -42,10 +42,11 @@
# format and translated into something sensible for cl or ml.
#
-args="-nologo"
+args="-nologo -W3"
md=-MD
cl="cl"
ml="ml"
+safeseh="-safeseh"
output=
while [ $# -gt 0 ]
@@ -63,15 +64,28 @@ do
-m64)
cl="cl" # "$MSVC/x86_amd64/cl"
ml="ml64" # "$MSVC/x86_amd64/ml64"
+ safeseh=
+ shift 1
+ ;;
+ -O0)
+ args="$args -Od"
shift 1
;;
-O*)
- args="$args $1"
+ # 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"
shift 1
;;
-g)
- # Can't specify -RTC1 or -Zi in opt. -Gy is ok. Use -OPT:REF?
- args="$args -D_DEBUG -RTC1 -Zi"
+ # Enable debug symbol generation.
+ args="$args -Zi -DEBUG"
+ shift 1
+ ;;
+ -DFFI_DEBUG)
+ # Link against debug CRT and enable runtime error checks.
+ args="$args -RTC1"
+ defines="$defines $1"
md=-MDd
shift 1
;;
@@ -108,8 +122,8 @@ do
shift 1
;;
-Wall)
- # -Wall on MSVC is overzealous. Use -W3 instead.
- args="$args -W3"
+ # -Wall on MSVC is overzealous, and we already build with -W3. Nothing
+ # to do here.
shift 1
;;
-Werror)
@@ -164,7 +178,7 @@ if [ -n "$assembly" ]; then
echo "$cl -nologo -EP $includes $defines $src > $ppsrc"
"$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $?
output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')"
- args="-nologo -safeseh $single $output $ppsrc"
+ args="-nologo $safeseh $single $output $ppsrc"
echo "$ml $args"
eval "\"$ml\" $args"
diff --git a/libffi/src/alpha/ffi.c b/libffi/src/alpha/ffi.c
index 8d6b2ba279e..192f691c4a2 100644
--- a/libffi/src/alpha/ffi.c
+++ b/libffi/src/alpha/ffi.c
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
+ ffi.c - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
Alpha Foreign Function Interface
@@ -178,6 +179,9 @@ ffi_prep_closure_loc (ffi_closure* closure,
{
unsigned int *tramp;
+ if (cif->abi != FFI_OSF)
+ return FFI_BAD_ABI;
+
tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x47fb0401; /* mov $27,$1 */
tramp[1] = 0xa77b0010; /* ldq $27,16($27) */
diff --git a/libffi/src/alpha/ffitarget.h b/libffi/src/alpha/ffitarget.h
index 7d06eb0bc22..af145bce839 100644
--- a/libffi/src/alpha/ffitarget.h
+++ b/libffi/src/alpha/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for Alpha.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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;
diff --git a/libffi/src/arm/ffi.c b/libffi/src/arm/ffi.c
index d5260333637..1f8597da88c 100644
--- a/libffi/src/arm/ffi.c
+++ b/libffi/src/arm/ffi.c
@@ -1,6 +1,10 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998, 2008 Red Hat, Inc.
-
+ ffi.c - Copyright (c) 2011 Timothy Wall
+ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
+ Copyright (c) 2011 Anthony Green
+ Copyright (c) 2011 Free Software Foundation
+ Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
+
ARM Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
@@ -61,6 +65,7 @@ int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
i--, p_arg++)
{
size_t z;
+ size_t alignment;
/* Allocated in VFP registers. */
if (ecif->cif->abi == FFI_VFP
@@ -78,8 +83,13 @@ int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
}
/* Align if necessary */
- if (((*p_arg)->alignment - 1) & (unsigned) argp) {
- argp = (char *) ALIGN(argp, (*p_arg)->alignment);
+ alignment = (*p_arg)->alignment;
+#ifdef _WIN32_WCE
+ if (alignment > 4)
+ alignment = 4;
+#endif
+ if ((alignment - 1) & (unsigned) argp) {
+ argp = (char *) ALIGN(argp, alignment);
}
if ((*p_arg)->type == FFI_TYPE_STRUCT)
@@ -186,6 +196,18 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
+/* Perform machine dependent cif processing for variadic calls */
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs)
+{
+ /* VFP variadic calls actually use the SYSV ABI */
+ if (cif->abi == FFI_VFP)
+ cif->abi = FFI_SYSV;
+
+ return ffi_prep_cif_machdep(cif);
+}
+
/* Prototypes for assembly functions, in sysv.S */
extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
@@ -317,6 +339,11 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
alignment = (*p_arg)->alignment;
if (alignment < 4)
alignment = 4;
+#ifdef _WIN32_WCE
+ else
+ if (alignment > 4)
+ alignment = 4;
+#endif
/* Align if necessary */
if ((alignment - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, alignment);
@@ -339,6 +366,220 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
extern unsigned int ffi_arm_trampoline[3];
+#if FFI_EXEC_TRAMPOLINE_TABLE
+
+#include <mach/mach.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern void *ffi_closure_trampoline_table_page;
+
+typedef struct ffi_trampoline_table ffi_trampoline_table;
+typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
+
+struct ffi_trampoline_table {
+ /* contigious writable and executable pages */
+ vm_address_t config_page;
+ vm_address_t trampoline_page;
+
+ /* free list tracking */
+ uint16_t free_count;
+ ffi_trampoline_table_entry *free_list;
+ ffi_trampoline_table_entry *free_list_pool;
+
+ ffi_trampoline_table *prev;
+ ffi_trampoline_table *next;
+};
+
+struct ffi_trampoline_table_entry {
+ void *(*trampoline)();
+ ffi_trampoline_table_entry *next;
+};
+
+/* Override the standard architecture trampoline size */
+// XXX TODO - Fix
+#undef FFI_TRAMPOLINE_SIZE
+#define FFI_TRAMPOLINE_SIZE 12
+
+/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */
+#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080));
+
+/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */
+#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16
+
+/* Total number of trampolines that fit in one trampoline table */
+#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE)
+
+static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
+static ffi_trampoline_table *ffi_trampoline_tables = NULL;
+
+static ffi_trampoline_table *
+ffi_trampoline_table_alloc ()
+{
+ ffi_trampoline_table *table = NULL;
+
+ /* Loop until we can allocate two contigious pages */
+ while (table == NULL) {
+ vm_address_t config_page = 0x0;
+ kern_return_t kt;
+
+ /* Try to allocate two pages */
+ kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
+ if (kt != KERN_SUCCESS) {
+ fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+ break;
+ }
+
+ /* Now drop the second half of the allocation to make room for the trampoline table */
+ vm_address_t trampoline_page = config_page+PAGE_SIZE;
+ kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
+ if (kt != KERN_SUCCESS) {
+ fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+ break;
+ }
+
+ /* Remap the trampoline table to directly follow the config page */
+ vm_prot_t cur_prot;
+ vm_prot_t max_prot;
+
+ kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
+
+ /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
+ if (kt != KERN_SUCCESS) {
+ /* Log unexpected failures */
+ if (kt != KERN_NO_SPACE) {
+ fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+ }
+
+ vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
+ continue;
+ }
+
+ /* We have valid trampoline and config pages */
+ table = calloc (1, sizeof(ffi_trampoline_table));
+ table->free_count = FFI_TRAMPOLINE_COUNT;
+ table->config_page = config_page;
+ table->trampoline_page = trampoline_page;
+
+ /* Create and initialize the free list */
+ table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry));
+
+ uint16_t i;
+ for (i = 0; i < table->free_count; i++) {
+ ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
+ entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
+
+ if (i < table->free_count - 1)
+ entry->next = &table->free_list_pool[i+1];
+ }
+
+ table->free_list = table->free_list_pool;
+ }
+
+ return table;
+}
+
+void *
+ffi_closure_alloc (size_t size, void **code)
+{
+ /* Create the closure */
+ ffi_closure *closure = malloc(size);
+ if (closure == NULL)
+ return NULL;
+
+ pthread_mutex_lock(&ffi_trampoline_lock);
+
+ /* Check for an active trampoline table with available entries. */
+ ffi_trampoline_table *table = ffi_trampoline_tables;
+ if (table == NULL || table->free_list == NULL) {
+ table = ffi_trampoline_table_alloc ();
+ if (table == NULL) {
+ free(closure);
+ return NULL;
+ }
+
+ /* Insert the new table at the top of the list */
+ table->next = ffi_trampoline_tables;
+ if (table->next != NULL)
+ table->next->prev = table;
+
+ ffi_trampoline_tables = table;
+ }
+
+ /* Claim the free entry */
+ ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
+ ffi_trampoline_tables->free_list = entry->next;
+ ffi_trampoline_tables->free_count--;
+ entry->next = NULL;
+
+ pthread_mutex_unlock(&ffi_trampoline_lock);
+
+ /* Initialize the return values */
+ *code = entry->trampoline;
+ closure->trampoline_table = table;
+ closure->trampoline_table_entry = entry;
+
+ return closure;
+}
+
+void
+ffi_closure_free (void *ptr)
+{
+ ffi_closure *closure = ptr;
+
+ pthread_mutex_lock(&ffi_trampoline_lock);
+
+ /* Fetch the table and entry references */
+ ffi_trampoline_table *table = closure->trampoline_table;
+ ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
+
+ /* Return the entry to the free list */
+ entry->next = table->free_list;
+ table->free_list = entry;
+ table->free_count++;
+
+ /* If all trampolines within this table are free, and at least one other table exists, deallocate
+ * the table */
+ if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
+ /* Remove from the list */
+ if (table->prev != NULL)
+ table->prev->next = table->next;
+
+ if (table->next != NULL)
+ table->next->prev = table->prev;
+
+ /* Deallocate pages */
+ kern_return_t kt;
+ kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
+ if (kt != KERN_SUCCESS)
+ fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+
+ kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
+ if (kt != KERN_SUCCESS)
+ fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
+
+ /* Deallocate free list */
+ free (table->free_list_pool);
+ free (table);
+ } else if (ffi_trampoline_tables != table) {
+ /* Otherwise, bump this table to the top of the list */
+ table->prev = NULL;
+ table->next = ffi_trampoline_tables;
+ if (ffi_trampoline_tables != NULL)
+ ffi_trampoline_tables->prev = table;
+
+ ffi_trampoline_tables = table;
+ }
+
+ pthread_mutex_unlock (&ffi_trampoline_lock);
+
+ /* Free the closure */
+ free (closure);
+}
+
+#else
+
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
@@ -353,6 +594,7 @@ extern unsigned int ffi_arm_trampoline[3];
mapping. */ \
})
+#endif
/* the cif must already be prep'ed */
@@ -370,12 +612,18 @@ ffi_prep_closure_loc (ffi_closure* closure,
else if (cif->abi == FFI_VFP)
closure_func = &ffi_closure_VFP;
else
- FFI_ASSERT (0);
+ return FFI_BAD_ABI;
+#if FFI_EXEC_TRAMPOLINE_TABLE
+ void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
+ config[0] = closure;
+ config[1] = closure_func;
+#else
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
closure_func, \
codeloc);
-
+#endif
+
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
diff --git a/libffi/src/arm/ffitarget.h b/libffi/src/arm/ffitarget.h
index ce25b23f5a3..26d494d616a 100644
--- a/libffi/src/arm/ffitarget.h
+++ b/libffi/src/arm/ffitarget.h
@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
- Copyright (c) 2010 CodeSourcery
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 2010 CodeSourcery
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for ARM.
@@ -29,6 +30,10 @@
#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;
@@ -55,6 +60,8 @@ typedef enum ffi_abi {
#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
+
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
@@ -62,4 +69,3 @@ typedef enum ffi_abi {
#define FFI_NATIVE_RAW_API 0
#endif
-
diff --git a/libffi/src/arm/gentramp.sh b/libffi/src/arm/gentramp.sh
new file mode 100755
index 00000000000..74f0b867dae
--- /dev/null
+++ b/libffi/src/arm/gentramp.sh
@@ -0,0 +1,118 @@
+#!/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
diff --git a/libffi/src/arm/sysv.S b/libffi/src/arm/sysv.S
index be6493a25b1..60e2ae3d552 100644
--- a/libffi/src/arm/sysv.S
+++ b/libffi/src/arm/sysv.S
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
- sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc.
+ sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
+ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
ARM Foreign Function Interface
@@ -39,7 +40,11 @@
#else
#define CNAME(x) x
#endif
+#ifdef __APPLE__
+#define ENTRY(x) .globl CNAME(x); CNAME(x):
+#else
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif /* __APPLE__ */
#endif
#ifdef __ELF__
@@ -48,6 +53,12 @@
#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.
@@ -105,21 +116,33 @@
.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. */
-_L__\name:
+#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
#endif
@@ -141,8 +164,7 @@ _L__\name:
#endif
.endm
-
- @ r0: fn
+ @ r0: ffi_prep_args
@ r1: &ecif
@ r2: cif->bytes
@ r3: fig->flags
@@ -222,11 +244,18 @@ ARM_FUNC_START ffi_call_SYSV
#endif
LSYM(Lepilogue):
- RETLDM "r0-r3,fp"
+#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
/*
@@ -247,7 +276,7 @@ ARM_FUNC_START ffi_closure_SYSV
sub sp, sp, #16
str sp, [sp, #8]
add r1, sp, #8
- bl ffi_closure_SYSV_inner
+ bl CNAME(ffi_closure_SYSV_inner)
cmp r0, #FFI_TYPE_INT
beq .Lretint
@@ -299,7 +328,9 @@ ARM_FUNC_START ffi_closure_SYSV
.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.
@@ -371,7 +402,7 @@ LSYM(Lbase_args):
@ assume no return value.
cmp r2, #0
beq LSYM(Lepilogue_vfp)
-
+
cmp r3, #FFI_TYPE_INT
streq r0, [r2]
beq LSYM(Lepilogue_vfp)
diff --git a/libffi/src/arm/trampoline.S b/libffi/src/arm/trampoline.S
new file mode 100644
index 00000000000..7b474291a25
--- /dev/null
+++ b/libffi/src/arm/trampoline.S
@@ -0,0 +1,4450 @@
+# GENERATED CODE - DO NOT EDIT
+# This file was generated by ./gentramp.sh
+
+# 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.
+# -----------------------------------------------------------------------
+
+.text
+.align 12
+.globl _ffi_closure_trampoline_table_page
+_ffi_closure_trampoline_table_page:
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
+
+ // 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]
+
diff --git a/libffi/src/avr32/ffi.c b/libffi/src/avr32/ffi.c
index 39fba2b03b6..3d43397b03a 100644
--- a/libffi/src/avr32/ffi.c
+++ b/libffi/src/avr32/ffi.c
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
+ ffi.c - Copyright (c) 2011 Anthony Green
+ Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
AVR32 Foreign Function Interface
@@ -394,7 +395,8 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void *user_data,
void *codeloc)
{
- FFI_ASSERT(cif->abi == FFI_SYSV);
+ if (cif->abi != FFI_SYSV)
+ return FFI_BAD_ABI;
unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]);
unsigned int __fun = (unsigned int)(&ffi_closure_SYSV);
diff --git a/libffi/src/avr32/ffitarget.h b/libffi/src/avr32/ffitarget.h
index 1c799b1de72..d0c7586f9a8 100644
--- a/libffi/src/avr32/ffitarget.h
+++ b/libffi/src/avr32/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
Target configuration macros for AVR32.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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;
@@ -34,8 +39,8 @@ 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_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
diff --git a/libffi/src/closures.c b/libffi/src/closures.c
index ff2b1bd21bd..1b378270363 100644
--- a/libffi/src/closures.c
+++ b/libffi/src/closures.c
@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
- closures.c - Copyright (c) 2007 Red Hat, Inc.
- Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
+ closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc.
+ Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
+ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
Code to allocate and deallocate memory for closures.
@@ -32,7 +33,7 @@
#include <ffi.h>
#include <ffi_common.h>
-#ifndef FFI_MMAP_EXEC_WRIT
+#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
# if __gnu_linux__
/* This macro indicates it may be forbidden to map anonymous memory
with both write and execute permission. Code compiled when this
@@ -63,7 +64,11 @@
#if FFI_CLOSURES
-# if FFI_MMAP_EXEC_WRIT
+# if FFI_EXEC_TRAMPOLINE_TABLE
+
+// Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations.
+
+# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */
#define USE_LOCKS 1
#define USE_DL_PREFIX 1
@@ -167,7 +172,7 @@ selinux_enabled_check (void)
#endif /* !FFI_MMAP_EXEC_SELINUX */
-#elif defined (__CYGWIN__)
+#elif defined (__CYGWIN__) || defined(__INTERIX)
#include <sys/mman.h>
@@ -193,11 +198,11 @@ static int dlmalloc_trim(size_t) MAYBE_UNUSED;
static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
static void dlmalloc_stats(void) MAYBE_UNUSED;
-#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
/* Use these for mmap and munmap within dlmalloc.c. */
static void *dlmmap(void *, size_t, int, int, int, off_t);
static int dlmunmap(void *, size_t);
-#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
#define mmap dlmmap
#define munmap dlmunmap
@@ -207,7 +212,7 @@ static int dlmunmap(void *, size_t);
#undef mmap
#undef munmap
-#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
/* A mutex used to synchronize access to *exec* variables in this file. */
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -522,7 +527,7 @@ segment_holding_code (mstate m, char* addr)
}
#endif
-#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
/* Allocate a chunk of memory with the given size. Returns a pointer
to the writable address, and sets *CODE to the executable
diff --git a/libffi/src/cris/ffi.c b/libffi/src/cris/ffi.c
index e9c39530c22..aaca5b1cbaa 100644
--- a/libffi/src/cris/ffi.c
+++ b/libffi/src/cris/ffi.c
@@ -153,21 +153,24 @@ ffi_prep_args (char *stack, extended_cif * ecif)
return (struct_count);
}
-ffi_status
-ffi_prep_cif (ffi_cif * cif,
- ffi_abi abi, unsigned int nargs,
- ffi_type * rtype, ffi_type ** atypes)
+ffi_status FFI_HIDDEN
+ffi_prep_cif_core (ffi_cif * cif,
+ ffi_abi abi, unsigned int isvariadic,
+ unsigned int nfixedargs, unsigned int ntotalargs,
+ ffi_type * rtype, ffi_type ** atypes)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT (cif != NULL);
- FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
+ FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
+ FFI_ASSERT(nfixedargs <= ntotalargs);
+ FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI);
cif->abi = abi;
cif->arg_types = atypes;
- cif->nargs = nargs;
+ cif->nargs = ntotalargs;
cif->rtype = rtype;
cif->flags = 0;
diff --git a/libffi/src/cris/ffitarget.h b/libffi/src/cris/ffitarget.h
index 4257f10a73c..b837e976e4e 100644
--- a/libffi/src/cris/ffitarget.h
+++ b/libffi/src/cris/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for CRIS.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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;
@@ -34,8 +39,8 @@ 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_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
diff --git a/libffi/src/dlmalloc.c b/libffi/src/dlmalloc.c
index 0fa235af22e..5c9f9c2d239 100644
--- a/libffi/src/dlmalloc.c
+++ b/libffi/src/dlmalloc.c
@@ -622,6 +622,9 @@ DEFAULT_MMAP_THRESHOLD default: 256K
#include "/usr/include/malloc.h"
#else /* HAVE_USR_INCLUDE_MALLOC_H */
+/* HP-UX's stdlib.h redefines mallinfo unless _STRUCT_MALLINFO is defined */
+#define _STRUCT_MALLINFO
+
struct mallinfo {
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
diff --git a/libffi/src/frv/ffitarget.h b/libffi/src/frv/ffitarget.h
index 1c319ea9488..d42540e53d3 100644
--- a/libffi/src/frv/ffitarget.h
+++ b/libffi/src/frv/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2004 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2004 Red Hat, Inc.
Target configuration macros for FR-V
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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
@@ -35,13 +40,9 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
-
-#ifdef FRV
FFI_EABI,
- FFI_DEFAULT_ABI = FFI_EABI,
-#endif
-
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+ FFI_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_EABI
} ffi_abi;
#endif
diff --git a/libffi/src/ia64/ffi.c b/libffi/src/ia64/ffi.c
index 79e29b45a89..9533ef68b58 100644
--- a/libffi/src/ia64/ffi.c
+++ b/libffi/src/ia64/ffi.c
@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc.
Copyright (c) 2000 Hewlett Packard Company
+ Copyright (c) 2011 Anthony Green
IA64 Foreign Function Interface
@@ -429,7 +430,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
struct ffi_ia64_trampoline_struct *tramp;
struct ia64_fd *fd;
- FFI_ASSERT (cif->abi == FFI_UNIX);
+ if (cif->abi != FFI_UNIX)
+ return FFI_BAD_ABI;
tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
fd = (struct ia64_fd *)(void *)ffi_closure_unix;
diff --git a/libffi/src/ia64/ffitarget.h b/libffi/src/ia64/ffitarget.h
index d85c049ba39..e68cea61544 100644
--- a/libffi/src/ia64/ffitarget.h
+++ b/libffi/src/ia64/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for IA-64.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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 long ffi_arg;
typedef signed long long ffi_sarg;
@@ -34,8 +39,8 @@ typedef signed long long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_UNIX, /* Linux and all Unix variants use the same conventions */
- FFI_DEFAULT_ABI = FFI_UNIX,
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+ FFI_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_UNIX
} ffi_abi;
#endif
diff --git a/libffi/src/java_raw_api.c b/libffi/src/java_raw_api.c
index 9c5383e6d5a..522c8bfd67e 100644
--- a/libffi/src/java_raw_api.c
+++ b/libffi/src/java_raw_api.c
@@ -311,7 +311,7 @@ ffi_java_translate_args (ffi_cif *cif, void *rvalue,
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
ffi_java_ptrarray_to_raw (cif, avalue, raw);
- (*cl->fun) (cif, rvalue, raw, cl->user_data);
+ (*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data);
ffi_java_raw_to_rvalue (cif, rvalue);
}
diff --git a/libffi/src/m32r/ffitarget.h b/libffi/src/m32r/ffitarget.h
index 6a761f6593a..6c34801982f 100644
--- a/libffi/src/m32r/ffitarget.h
+++ b/libffi/src/m32r/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 2004 Renesas Technology.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 2004 Renesas Technology.
Target configuration macros for M32R.
Permission is hereby granted, free of charge, to any person obtaining
@@ -26,6 +27,10 @@
#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
@@ -36,8 +41,8 @@ typedef enum ffi_abi
{
FFI_FIRST_ABI = 0,
FFI_SYSV,
- FFI_DEFAULT_ABI = FFI_SYSV,
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+ FFI_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
diff --git a/libffi/src/m68k/ffi.c b/libffi/src/m68k/ffi.c
index 0d4df1e235f..d95c72b93bd 100644
--- a/libffi/src/m68k/ffi.c
+++ b/libffi/src/m68k/ffi.c
@@ -261,7 +261,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
void *user_data,
void *codeloc)
{
- FFI_ASSERT (cif->abi == FFI_SYSV);
+ if (cif->abi != FFI_SYSV)
+ return FFI_BAD_ABI;
*(unsigned short *)closure->tramp = 0x207c;
*(void **)(closure->tramp + 2) = codeloc;
diff --git a/libffi/src/m68k/ffitarget.h b/libffi/src/m68k/ffitarget.h
index 633717bbfa8..e81dde2b2eb 100644
--- a/libffi/src/m68k/ffitarget.h
+++ b/libffi/src/m68k/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for Motorola 68K.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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;
@@ -34,8 +39,8 @@ 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_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
diff --git a/libffi/src/mips/ffi.c b/libffi/src/mips/ffi.c
index d714cc9e998..79cff9b5304 100644
--- a/libffi/src/mips/ffi.c
+++ b/libffi/src/mips/ffi.c
@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1996, 2007, 2008 Red Hat, Inc.
- Copyright (c) 2008 David Daney
+ ffi.c - Copyright (c) 2011 Anthony Green
+ Copyright (c) 2008 David Daney
+ Copyright (c) 1996, 2007, 2008, 2011 Red Hat, Inc.
MIPS Foreign Function Interface
@@ -37,7 +38,11 @@
#endif
#ifndef USE__BUILTIN___CLEAR_CACHE
-#include <sys/cachectl.h>
+# if defined(__OpenBSD__)
+# include <mips64/sysarch.h>
+# else
+# include <sys/cachectl.h>
+# endif
#endif
#ifdef FFI_DEBUG
@@ -662,10 +667,12 @@ ffi_prep_closure_loc (ffi_closure *closure,
char *clear_location = (char *) codeloc;
#if defined(FFI_MIPS_O32)
- FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
+ if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
+ return FFI_BAD_ABI;
fn = ffi_closure_O32;
#else /* FFI_MIPS_N32 */
- FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
+ if (cif->abi != FFI_N32 && cif->abi != FFI_N64)
+ return FFI_BAD_ABI;
fn = ffi_closure_N32;
#endif /* FFI_MIPS_O32 */
diff --git a/libffi/src/mips/ffitarget.h b/libffi/src/mips/ffitarget.h
index d0fc983a74f..717d65951c3 100644
--- a/libffi/src/mips/ffitarget.h
+++ b/libffi/src/mips/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for MIPS.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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
+
#ifdef linux
# include <asm/sgidefs.h>
#elif defined(__rtems__)
@@ -36,7 +41,7 @@
#define _MIPS_SIM_ABI32 1
#define _MIPS_SIM_NABI32 2
#define _MIPS_SIM_ABI64 3
-#else
+#elif !defined(__OpenBSD__)
# include <sgidefs.h>
#endif
@@ -51,7 +56,7 @@
# endif
#if !defined(_MIPS_SIM)
--- something is very wrong --
+# error -- something is very wrong --
#else
# if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
# define FFI_MIPS_N32
@@ -59,7 +64,7 @@
# if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
# define FFI_MIPS_O32
# else
--- this is an unsupported platform --
+# error -- this is an unsupported platform --
# endif
# endif
#endif
@@ -194,30 +199,29 @@ typedef enum ffi_abi {
FFI_O32_SOFT_FLOAT,
FFI_N32_SOFT_FLOAT,
FFI_N64_SOFT_FLOAT,
+ FFI_LAST_ABI,
#ifdef FFI_MIPS_O32
#ifdef __mips_soft_float
- FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT,
+ FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT
#else
- FFI_DEFAULT_ABI = FFI_O32,
+ FFI_DEFAULT_ABI = FFI_O32
#endif
#else
# if _MIPS_SIM==_ABI64
# ifdef __mips_soft_float
- FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT,
+ FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT
# else
- FFI_DEFAULT_ABI = FFI_N64,
+ FFI_DEFAULT_ABI = FFI_N64
# endif
# else
# ifdef __mips_soft_float
- FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT,
+ FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT
# else
- FFI_DEFAULT_ABI = FFI_N32,
+ FFI_DEFAULT_ABI = FFI_N32
# endif
# endif
#endif
-
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
diff --git a/libffi/src/pa/ffi.c b/libffi/src/pa/ffi.c
index 6d7606f89bc..4ce2bc6f0e4 100644
--- a/libffi/src/pa/ffi.c
+++ b/libffi/src/pa/ffi.c
@@ -1,9 +1,11 @@
/* -----------------------------------------------------------------------
- ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
+ ffi.c - (c) 2011 Anthony Green
(c) 2008 Red Hat, Inc.
-
+ (c) 2006 Free Software Foundation, Inc.
+ (c) 2003-2004 Randolph Chung <tausq@debian.org>
+
HPPA Foreign Function Interface
- HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
+ HP-UX PA ABI support
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -633,7 +635,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
UINT32 *tmp;
#endif
- FFI_ASSERT (cif->abi == FFI_PA32);
+ if (cif->abi != FFI_PA32)
+ return FFI_BAD_ABI;
/* Make a small trampoline that will branch to our
handler function. Use PC-relative addressing. */
diff --git a/libffi/src/pa/ffitarget.h b/libffi/src/pa/ffitarget.h
index 001f8917d87..5e364d38f8b 100644
--- a/libffi/src/pa/ffitarget.h
+++ b/libffi/src/pa/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for hppa.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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
@@ -38,21 +43,22 @@ typedef enum ffi_abi {
#ifdef PA_LINUX
FFI_PA32,
- FFI_DEFAULT_ABI = FFI_PA32,
+ FFI_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_PA32
#endif
#ifdef PA_HPUX
FFI_PA32,
- FFI_DEFAULT_ABI = FFI_PA32,
+ FFI_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_PA32
#endif
#ifdef PA64_HPUX
#error "PA64_HPUX FFI is not yet implemented"
FFI_PA64,
- FFI_DEFAULT_ABI = FFI_PA64,
+ FFI_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_PA64
#endif
-
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif
diff --git a/libffi/src/powerpc/aix.S b/libffi/src/powerpc/aix.S
index c6f87644d94..213f2db39de 100644
--- a/libffi/src/powerpc/aix.S
+++ b/libffi/src/powerpc/aix.S
@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
- aix.S - Copyright (c) 2002,2009 Free Software Foundation, Inc.
+ aix.S - Copyright (c) 2002, 2009 Free Software Foundation, Inc.
based on darwin.S by John Hornkvist
PowerPC Assembly glue.
@@ -79,6 +79,8 @@
.set f20,20
.set f21,21
+ .extern .ffi_prep_args
+
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
@@ -125,6 +127,7 @@ ffi_call_AIX:
/* Call ffi_prep_args. */
mr r4, r1
bl .ffi_prep_args
+ nop
/* Now do the call. */
ld r0, 0(r29)
@@ -226,6 +229,7 @@ L(float_return_value):
/* Call ffi_prep_args. */
mr r4, r1
bl .ffi_prep_args
+ nop
/* Now do the call. */
lwz r0, 0(r29)
diff --git a/libffi/src/powerpc/aix_closure.S b/libffi/src/powerpc/aix_closure.S
index 5c74448f2b1..c906017c459 100644
--- a/libffi/src/powerpc/aix_closure.S
+++ b/libffi/src/powerpc/aix_closure.S
@@ -79,6 +79,8 @@
.set f20,20
.set f21,21
+ .extern .ffi_closure_helper_DARWIN
+
#define LIBFFI_ASM
#define JUMPTARGET(name) name
#define L(x) x
diff --git a/libffi/src/powerpc/asm.h b/libffi/src/powerpc/asm.h
index e86e6b09147..994f62d079d 100644
--- a/libffi/src/powerpc/asm.h
+++ b/libffi/src/powerpc/asm.h
@@ -42,7 +42,7 @@
/* If compiled for profiling, call `_mcount' at the start of each function. */
#ifdef PROF
-/* The mcount code relies on a the return address being on the stack
+/* The mcount code relies on the return address being on the stack
to locate our caller and so it can restore it; so store one just
for its benefit. */
#ifdef PIC
diff --git a/libffi/src/powerpc/darwin.S b/libffi/src/powerpc/darwin.S
index 3b425da78b8..4f987dc7482 100644
--- a/libffi/src/powerpc/darwin.S
+++ b/libffi/src/powerpc/darwin.S
@@ -335,7 +335,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 0x90 ; FDE Encoding (indirect pcrel)
+ .byte 0x10 ; FDE Encoding (indirect pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0
diff --git a/libffi/src/powerpc/darwin_closure.S b/libffi/src/powerpc/darwin_closure.S
index b43f9658fce..3f6790f6bb3 100644
--- a/libffi/src/powerpc/darwin_closure.S
+++ b/libffi/src/powerpc/darwin_closure.S
@@ -484,7 +484,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 0x90 ; FDE Encoding (indirect pcrel)
+ .byte 0x10 ; FDE Encoding (indirect pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0
diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c
index 75784a96d3b..1920c91104d 100644
--- a/libffi/src/powerpc/ffi.c
+++ b/libffi/src/powerpc/ffi.c
@@ -1,7 +1,9 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1998 Geoffrey Keating
- Copyright (C) 2007, 2008 Free Software Foundation, Inc
- Copyright (C) 2008 Red Hat, Inc
+ ffi.c - Copyright (C) 2011 Anthony Green
+ Copyright (C) 2011 Kyle Moffett
+ Copyright (C) 2008 Red Hat, Inc
+ Copyright (C) 2007, 2008 Free Software Foundation, Inc
+ Copyright (c) 1998 Geoffrey Keating
PowerPC Foreign Function Interface
@@ -39,32 +41,28 @@ enum {
/* The assembly depends on these exact flags. */
FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
+#ifndef __NO_FPRS__
FLAG_RETURNS_FP = 1 << (31-29),
+#endif
FLAG_RETURNS_64BITS = 1 << (31-28),
FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
- FLAG_SYSV_SMST_R4 = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
- structs. */
- FLAG_SYSV_SMST_R3 = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
- structs. */
- /* Bits (31-24) through (31-19) store shift value for SMST */
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
+#ifndef __NO_FPRS__
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
+#endif
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
};
/* About the SYSV ABI. */
-unsigned int NUM_GPR_ARG_REGISTERS = 8;
+#define ASM_NEEDS_REGISTERS 4
+#define NUM_GPR_ARG_REGISTERS 8
#ifndef __NO_FPRS__
-unsigned int NUM_FPR_ARG_REGISTERS = 8;
-#else
-unsigned int NUM_FPR_ARG_REGISTERS = 0;
+# define NUM_FPR_ARG_REGISTERS 8
#endif
-enum { ASM_NEEDS_REGISTERS = 4 };
-
/* ffi_prep_args_SYSV is called by the assembly routine once stack space
has been allocated for the function's arguments.
@@ -113,10 +111,12 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
valp gpr_base;
int intarg_count;
+#ifndef __NO_FPRS__
/* 'fpr_base' points at the space for fpr1, and grows upwards as
we use FPR registers. */
valp fpr_base;
int fparg_count;
+#endif
/* 'copy_space' grows down as we put structures in it. It should
stay 16-byte aligned. */
@@ -125,9 +125,8 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
/* 'next_arg' grows up as we put parameters in it. */
valp next_arg;
- int i, ii MAYBE_UNUSED;
+ int i;
ffi_type **ptr;
- double double_tmp;
union {
void **v;
char **c;
@@ -143,15 +142,16 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
size_t struct_copy_size;
unsigned gprvalue;
- if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
- NUM_FPR_ARG_REGISTERS = 0;
-
stacktop.c = (char *) stack + bytes;
gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
intarg_count = 0;
+#ifndef __NO_FPRS__
fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
fparg_count = 0;
copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
+#else
+ copy_space.c = gpr_base.c;
+#endif
next_arg.u = stack + 2;
/* Check that everything starts aligned properly. */
@@ -174,12 +174,28 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
i > 0;
i--, ptr++, p_argv.v++)
{
- switch ((*ptr)->type)
- {
+ unsigned short typenum = (*ptr)->type;
+
+ /* We may need to handle some values depending on ABI */
+ if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) {
+ if (typenum == FFI_TYPE_FLOAT)
+ typenum = FFI_TYPE_UINT32;
+ if (typenum == FFI_TYPE_DOUBLE)
+ typenum = FFI_TYPE_UINT64;
+ if (typenum == FFI_TYPE_LONGDOUBLE)
+ typenum = FFI_TYPE_UINT128;
+ } else if (ecif->cif->abi != FFI_LINUX) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ if (typenum == FFI_TYPE_LONGDOUBLE)
+ typenum = FFI_TYPE_STRUCT;
+#endif
+ }
+
+ /* Now test the translated value */
+ switch (typenum) {
+#ifndef __NO_FPRS__
case FFI_TYPE_FLOAT:
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
- if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
- goto soft_float_prep;
double_tmp = **p_argv.f;
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
{
@@ -218,43 +234,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
- if ((ecif->cif->abi != FFI_LINUX)
- && (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
- goto do_struct;
- /* The soft float ABI for long doubles works like this,
- a long double is passed in four consecutive gprs if available.
- A maximum of 2 long doubles can be passed in gprs.
- If we do not have 4 gprs left, the long double is passed on the
- stack, 4-byte aligned. */
- if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
- {
- unsigned int int_tmp = (*p_argv.ui)[0];
- if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
- {
- if (intarg_count < NUM_GPR_ARG_REGISTERS)
- intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
- *next_arg.u = int_tmp;
- next_arg.u++;
- for (ii = 1; ii < 4; ii++)
- {
- int_tmp = (*p_argv.ui)[ii];
- *next_arg.u = int_tmp;
- next_arg.u++;
- }
- }
- else
- {
- *gpr_base.u++ = int_tmp;
- for (ii = 1; ii < 4; ii++)
- {
- int_tmp = (*p_argv.ui)[ii];
- *gpr_base.u++ = int_tmp;
- }
- }
- intarg_count +=4;
- }
- else
- {
double_tmp = (*p_argv.d)[0];
if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
@@ -280,13 +259,40 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
fparg_count += 2;
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
- }
break;
#endif
+#endif /* have FPRs */
+
+ /*
+ * The soft float ABI for long doubles works like this, a long double
+ * is passed in four consecutive GPRs if available. A maximum of 2
+ * long doubles can be passed in gprs. If we do not have 4 GPRs
+ * left, the long double is passed on the stack, 4-byte aligned.
+ */
+ case FFI_TYPE_UINT128: {
+ unsigned int int_tmp = (*p_argv.ui)[0];
+ unsigned int ii;
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3) {
+ if (intarg_count < NUM_GPR_ARG_REGISTERS)
+ intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
+ *(next_arg.u++) = int_tmp;
+ for (ii = 1; ii < 4; ii++) {
+ int_tmp = (*p_argv.ui)[ii];
+ *(next_arg.u++) = int_tmp;
+ }
+ } else {
+ *(gpr_base.u++) = int_tmp;
+ for (ii = 1; ii < 4; ii++) {
+ int_tmp = (*p_argv.ui)[ii];
+ *(gpr_base.u++) = int_tmp;
+ }
+ }
+ intarg_count += 4;
+ break;
+ }
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
- soft_double_prep:
if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
intarg_count++;
if (intarg_count >= NUM_GPR_ARG_REGISTERS)
@@ -319,9 +325,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
break;
case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- do_struct:
-#endif
struct_copy_size = ((*ptr)->size + 15) & ~0xF;
copy_space.c -= struct_copy_size;
memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
@@ -349,7 +352,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
- soft_float_prep:
gprvalue = **p_argv.ui;
@@ -366,8 +368,10 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
/* Check that we didn't overrun the stack... */
FFI_ASSERT (copy_space.c >= next_arg.c);
FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
+#ifndef __NO_FPRS__
FFI_ASSERT (fpr_base.u
<= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+#endif
FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
}
@@ -604,9 +608,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
unsigned type = cif->rtype->type;
unsigned size = cif->rtype->size;
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
- NUM_FPR_ARG_REGISTERS = 0;
-
if (cif->abi != FFI_LINUX64)
{
/* All the machine-independent calculation of cif->bytes will be wrong.
@@ -646,62 +647,56 @@ ffi_prep_cif_machdep (ffi_cif *cif)
- Single/double FP values in fpr1, long double in fpr1,fpr2.
- soft-float float/doubles are treated as UINT32/UINT64 respectivley.
- soft-float long doubles are returned in gpr3-gpr6. */
+ /* First translate for softfloat/nonlinux */
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
+ if (type == FFI_TYPE_FLOAT)
+ type = FFI_TYPE_UINT32;
+ if (type == FFI_TYPE_DOUBLE)
+ type = FFI_TYPE_UINT64;
+ if (type == FFI_TYPE_LONGDOUBLE)
+ type = FFI_TYPE_UINT128;
+ } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ if (type == FFI_TYPE_LONGDOUBLE)
+ type = FFI_TYPE_STRUCT;
+#endif
+ }
+
switch (type)
{
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+#ifndef __NO_FPRS__
case FFI_TYPE_LONGDOUBLE:
- if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
- && cif->abi != FFI_LINUX_SOFT_FLOAT)
- goto byref;
flags |= FLAG_RETURNS_128BITS;
/* Fall through. */
-#endif
case FFI_TYPE_DOUBLE:
flags |= FLAG_RETURNS_64BITS;
/* Fall through. */
case FFI_TYPE_FLOAT:
- /* With FFI_LINUX_SOFT_FLOAT no fp registers are used. */
- if (cif->abi != FFI_LINUX_SOFT_FLOAT)
- flags |= FLAG_RETURNS_FP;
+ flags |= FLAG_RETURNS_FP;
break;
+#endif
+ case FFI_TYPE_UINT128:
+ flags |= FLAG_RETURNS_128BITS;
+ /* Fall through. */
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
flags |= FLAG_RETURNS_64BITS;
break;
case FFI_TYPE_STRUCT:
- if (cif->abi == FFI_SYSV)
- {
- /* The final SYSV ABI says that structures smaller or equal 8 bytes
- are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
- in memory. */
-
- /* Treat structs with size <= 8 bytes. */
- if (size <= 8)
- {
- flags |= FLAG_RETURNS_SMST;
- /* These structs are returned in r3. We pack the type and the
- precalculated shift value (needed in the sysv.S) into flags.
- The same applies for the structs returned in r3/r4. */
- if (size <= 4)
- {
- flags |= FLAG_SYSV_SMST_R3;
- flags |= 8 * (4 - size) << 8;
- break;
- }
- /* These structs are returned in r3 and r4. See above. */
- if (size <= 8)
- {
- flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
- flags |= 8 * (8 - size) << 8;
- break;
- }
- }
- }
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- byref:
-#endif
+ /*
+ * The final SYSV ABI says that structures smaller or equal 8 bytes
+ * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
+ * in memory.
+ *
+ * NOTE: The assembly code can safely assume that it just needs to
+ * store both r3 and r4 into a 8-byte word-aligned buffer, as
+ * we allocate a temporary buffer in ffi_call() if this flag is
+ * set.
+ */
+ if (cif->abi == FFI_SYSV && size <= 8)
+ flags |= FLAG_RETURNS_SMST;
intarg_count++;
flags |= FLAG_RETVAL_REFERENCE;
/* Fall through. */
@@ -722,39 +717,36 @@ ffi_prep_cif_machdep (ffi_cif *cif)
Stuff on the stack needs to keep proper alignment. */
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
- switch ((*ptr)->type)
- {
+ unsigned short typenum = (*ptr)->type;
+
+ /* We may need to handle some values depending on ABI */
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
+ if (typenum == FFI_TYPE_FLOAT)
+ typenum = FFI_TYPE_UINT32;
+ if (typenum == FFI_TYPE_DOUBLE)
+ typenum = FFI_TYPE_UINT64;
+ if (typenum == FFI_TYPE_LONGDOUBLE)
+ typenum = FFI_TYPE_UINT128;
+ } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ if (typenum == FFI_TYPE_LONGDOUBLE)
+ typenum = FFI_TYPE_STRUCT;
+#endif
+ }
+
+ switch (typenum) {
+#ifndef __NO_FPRS__
case FFI_TYPE_FLOAT:
- /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
- goto soft_float_cif;
fparg_count++;
/* floating singles are not 8-aligned on stack */
break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
- if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
- goto do_struct;
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
- {
- if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
- || intarg_count < NUM_GPR_ARG_REGISTERS)
- /* A long double in FFI_LINUX_SOFT_FLOAT can use only
- a set of four consecutive gprs. If we have not enough,
- we have to adjust the intarg_count value. */
- intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
- intarg_count += 4;
- break;
- }
- else
- fparg_count++;
+ fparg_count++;
/* Fall thru */
#endif
case FFI_TYPE_DOUBLE:
- /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
- goto soft_double_cif;
fparg_count++;
/* If this FP arg is going on the stack, it must be
8-byte-aligned. */
@@ -763,10 +755,21 @@ ffi_prep_cif_machdep (ffi_cif *cif)
&& intarg_count % 2 != 0)
intarg_count++;
break;
+#endif
+ case FFI_TYPE_UINT128:
+ /*
+ * A long double in FFI_LINUX_SOFT_FLOAT can use only a set
+ * of four consecutive gprs. If we do not have enough, we
+ * have to adjust the intarg_count value.
+ */
+ if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
+ && intarg_count < NUM_GPR_ARG_REGISTERS)
+ intarg_count = NUM_GPR_ARG_REGISTERS;
+ intarg_count += 4;
+ break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
- soft_double_cif:
/* 'long long' arguments are passed as two words, but
either both words must fit in registers or both go
on the stack. If they go on the stack, they must
@@ -783,9 +786,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
break;
case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- do_struct:
-#endif
/* We must allocate space for a copy of these to enforce
pass-by-value. Pad the space up to a multiple of 16
bytes (the maximum alignment required for anything under
@@ -793,12 +793,20 @@ ffi_prep_cif_machdep (ffi_cif *cif)
struct_copy_size += ((*ptr)->size + 15) & ~0xF;
/* Fall through (allocate space for the pointer). */
- default:
- soft_float_cif:
+ case FFI_TYPE_POINTER:
+ case FFI_TYPE_INT:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT32:
+ case FFI_TYPE_UINT16:
+ case FFI_TYPE_SINT16:
+ case FFI_TYPE_UINT8:
+ case FFI_TYPE_SINT8:
/* Everything else is passed as a 4-byte word in a GPR, either
the object itself or a pointer to it. */
intarg_count++;
break;
+ default:
+ FFI_ASSERT (0);
}
}
else
@@ -827,16 +835,29 @@ ffi_prep_cif_machdep (ffi_cif *cif)
intarg_count += ((*ptr)->size + 7) / 8;
break;
- default:
+ case FFI_TYPE_POINTER:
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_INT:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT32:
+ case FFI_TYPE_UINT16:
+ case FFI_TYPE_SINT16:
+ case FFI_TYPE_UINT8:
+ case FFI_TYPE_SINT8:
/* Everything else is passed as a 8-byte word in a GPR, either
the object itself or a pointer to it. */
intarg_count++;
break;
+ default:
+ FFI_ASSERT (0);
}
}
+#ifndef __NO_FPRS__
if (fparg_count != 0)
flags |= FLAG_FP_ARGUMENTS;
+#endif
if (intarg_count > 4)
flags |= FLAG_4_GPR_ARGUMENTS;
if (struct_copy_size != 0)
@@ -844,21 +865,27 @@ ffi_prep_cif_machdep (ffi_cif *cif)
if (cif->abi != FFI_LINUX64)
{
+#ifndef __NO_FPRS__
/* Space for the FPR registers, if needed. */
if (fparg_count != 0)
bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
+#endif
/* Stack space. */
if (intarg_count > NUM_GPR_ARG_REGISTERS)
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
+#ifndef __NO_FPRS__
if (fparg_count > NUM_FPR_ARG_REGISTERS)
bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
+#endif
}
else
{
+#ifndef __NO_FPRS__
/* Space for the FPR registers, if needed. */
if (fparg_count != 0)
bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
+#endif
/* Stack space. */
if (intarg_count > NUM_GPR_ARG_REGISTERS64)
@@ -886,28 +913,41 @@ extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
+ /*
+ * The final SYSV ABI says that structures smaller or equal 8 bytes
+ * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
+ * in memory.
+ *
+ * Just to keep things simple for the assembly code, we will always
+ * bounce-buffer struct return values less than or equal to 8 bytes.
+ * This allows the ASM to handle SYSV small structures by directly
+ * writing r3 and r4 to memory without worrying about struct size.
+ */
+ unsigned int smst_buffer[2];
extended_cif ecif;
+ unsigned int rsize;
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;
-
+ /* Ensure that we have a valid struct return value */
+ ecif.rvalue = rvalue;
+ if (cif->rtype->type == FFI_TYPE_STRUCT) {
+ rsize = cif->rtype->size;
+ if (rsize <= 8)
+ ecif.rvalue = smst_buffer;
+ else if (!rvalue)
+ ecif.rvalue = alloca(rsize);
+ }
switch (cif->abi)
{
#ifndef POWERPC64
+# ifndef __NO_FPRS__
case FFI_SYSV:
case FFI_GCC_SYSV:
case FFI_LINUX:
+# endif
case FFI_LINUX_SOFT_FLOAT:
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
break;
@@ -920,6 +960,10 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
FFI_ASSERT (0);
break;
}
+
+ /* Check for a bounce-buffered return value */
+ if (rvalue && ecif.rvalue == smst_buffer)
+ memcpy(rvalue, smst_buffer, rsize);
}
@@ -949,14 +993,19 @@ ffi_prep_closure_loc (ffi_closure *closure,
#ifdef POWERPC64
void **tramp = (void **) &closure->tramp[0];
- FFI_ASSERT (cif->abi == FFI_LINUX64);
+ if (cif->abi != FFI_LINUX64)
+ return FFI_BAD_ABI;
/* Copy function address and TOC from ffi_closure_LINUX64. */
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
tramp[2] = codeloc;
#else
unsigned int *tramp;
- FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
+ if (! (cif->abi == FFI_GCC_SYSV
+ || cif->abi == FFI_SYSV
+ || cif->abi == FFI_LINUX
+ || cif->abi == FFI_LINUX_SOFT_FLOAT))
+ return FFI_BAD_ABI;
tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x7c0802a6; /* mflr r0 */
@@ -1011,32 +1060,38 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
void ** avalue;
ffi_type ** arg_types;
long i, avn;
- long nf; /* number of floating registers already used */
- long ng; /* number of general registers already used */
- ffi_cif * cif;
- double temp;
- unsigned size;
+#ifndef __NO_FPRS__
+ long nf = 0; /* number of floating registers already used */
+#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;
- cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *));
- size = cif->rtype->size;
- nf = 0;
- ng = 0;
+ /* First translate for softfloat/nonlinux */
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
+ if (rtypenum == FFI_TYPE_FLOAT)
+ rtypenum = FFI_TYPE_UINT32;
+ if (rtypenum == FFI_TYPE_DOUBLE)
+ rtypenum = FFI_TYPE_UINT64;
+ if (rtypenum == FFI_TYPE_LONGDOUBLE)
+ rtypenum = FFI_TYPE_UINT128;
+ } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ if (rtypenum == FFI_TYPE_LONGDOUBLE)
+ rtypenum = FFI_TYPE_STRUCT;
+#endif
+ }
+
/* Copy the caller's structure return value address so that the closure
returns the data directly to the caller.
For FFI_SYSV the result is passed in r3/r4 if the struct size is less
or equal 8 bytes. */
-
- if ((cif->rtype->type == FFI_TYPE_STRUCT
- && !((cif->abi == FFI_SYSV) && (size <= 8)))
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
- && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
-#endif
- )
- {
+ if (rtypenum == FFI_TYPE_STRUCT && ((cif->abi != FFI_SYSV) || (size > 8))) {
rvalue = (void *) *pgr;
ng++;
pgr++;
@@ -1047,10 +1102,109 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
arg_types = cif->arg_types;
/* Grab the addresses of the arguments from the stack frame. */
- while (i < avn)
- {
- switch (arg_types[i]->type)
- {
+ while (i < avn) {
+ unsigned short typenum = arg_types[i]->type;
+
+ /* We may need to handle some values depending on ABI */
+ if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
+ if (typenum == FFI_TYPE_FLOAT)
+ typenum = FFI_TYPE_UINT32;
+ if (typenum == FFI_TYPE_DOUBLE)
+ typenum = FFI_TYPE_UINT64;
+ if (typenum == FFI_TYPE_LONGDOUBLE)
+ typenum = FFI_TYPE_UINT128;
+ } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ if (typenum == FFI_TYPE_LONGDOUBLE)
+ typenum = FFI_TYPE_STRUCT;
+#endif
+ }
+
+ switch (typenum) {
+#ifndef __NO_FPRS__
+ case FFI_TYPE_FLOAT:
+ /* unfortunately float values are stored as doubles
+ * in the ffi_closure_SYSV code (since we don't check
+ * the type in that routine).
+ */
+
+ /* there are 8 64bit floating point registers */
+
+ if (nf < 8)
+ {
+ temp = pfr->d;
+ pfr->f = (float) temp;
+ avalue[i] = pfr;
+ nf++;
+ pfr++;
+ }
+ else
+ {
+ /* FIXME? here we are really changing the values
+ * stored in the original calling routines outgoing
+ * parameter stack. This is probably a really
+ * naughty thing to do but...
+ */
+ avalue[i] = pst;
+ pst += 1;
+ }
+ break;
+
+ case FFI_TYPE_DOUBLE:
+ /* On the outgoing stack all values are aligned to 8 */
+ /* there are 8 64bit floating point registers */
+
+ if (nf < 8)
+ {
+ avalue[i] = pfr;
+ nf++;
+ pfr++;
+ }
+ else
+ {
+ if (((long) pst) & 4)
+ pst++;
+ avalue[i] = pst;
+ pst += 2;
+ }
+ break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ case FFI_TYPE_LONGDOUBLE:
+ if (nf < 7)
+ {
+ avalue[i] = pfr;
+ pfr += 2;
+ nf += 2;
+ }
+ else
+ {
+ if (((long) pst) & 4)
+ pst++;
+ avalue[i] = pst;
+ pst += 4;
+ nf = 8;
+ }
+ break;
+#endif
+#endif /* have FPRS */
+
+ case FFI_TYPE_UINT128:
+ /*
+ * Test if for the whole long double, 4 gprs are available.
+ * otherwise the stuff ends up on the stack.
+ */
+ if (ng < 5) {
+ avalue[i] = pgr;
+ pgr += 4;
+ ng += 4;
+ } else {
+ avalue[i] = pst;
+ pst += 4;
+ ng = 8+4;
+ }
+ break;
+
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
/* there are 8 gpr registers used to pass values */
@@ -1086,7 +1240,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
- soft_float_closure:
/* there are 8 gpr registers used to pass values */
if (ng < 8)
{
@@ -1102,9 +1255,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
break;
case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- do_struct:
-#endif
/* Structs are passed by reference. The address will appear in a
gpr if it is one of the first 8 arguments. */
if (ng < 8)
@@ -1122,7 +1272,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
- soft_double_closure:
/* passing long long ints are complex, they must
* be passed in suitable register pairs such as
* (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
@@ -1154,99 +1303,8 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
}
break;
- case FFI_TYPE_FLOAT:
- /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
- goto soft_float_closure;
- /* unfortunately float values are stored as doubles
- * in the ffi_closure_SYSV code (since we don't check
- * the type in that routine).
- */
-
- /* there are 8 64bit floating point registers */
-
- if (nf < 8)
- {
- temp = pfr->d;
- pfr->f = (float) temp;
- avalue[i] = pfr;
- nf++;
- pfr++;
- }
- else
- {
- /* FIXME? here we are really changing the values
- * stored in the original calling routines outgoing
- * parameter stack. This is probably a really
- * naughty thing to do but...
- */
- avalue[i] = pst;
- pst += 1;
- }
- break;
-
- case FFI_TYPE_DOUBLE:
- /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
- goto soft_double_closure;
- /* On the outgoing stack all values are aligned to 8 */
- /* there are 8 64bit floating point registers */
-
- if (nf < 8)
- {
- avalue[i] = pfr;
- nf++;
- pfr++;
- }
- else
- {
- if (((long) pst) & 4)
- pst++;
- avalue[i] = pst;
- pst += 2;
- }
- break;
-
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- case FFI_TYPE_LONGDOUBLE:
- if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
- goto do_struct;
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
- { /* Test if for the whole long double, 4 gprs are available.
- otherwise the stuff ends up on the stack. */
- if (ng < 5)
- {
- avalue[i] = pgr;
- pgr += 4;
- ng += 4;
- }
- else
- {
- avalue[i] = pst;
- pst += 4;
- ng = 8;
- }
- break;
- }
- if (nf < 7)
- {
- avalue[i] = pfr;
- pfr += 2;
- nf += 2;
- }
- else
- {
- if (((long) pst) & 4)
- pst++;
- avalue[i] = pst;
- pst += 4;
- nf = 8;
- }
- break;
-#endif
-
default:
- FFI_ASSERT (0);
+ FFI_ASSERT (0);
}
i++;
@@ -1263,39 +1321,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
already used and we never have a struct with size zero. That is the reason
for the subtraction of 1. See the comment in ffitarget.h about ordering.
*/
- if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
- && size <= 8)
+ if (cif->abi == FFI_SYSV && rtypenum == FFI_TYPE_STRUCT && size <= 8)
return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
- && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
- return FFI_TYPE_STRUCT;
-#endif
- /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
- respectivley UINT64. */
- if (cif->abi == FFI_LINUX_SOFT_FLOAT)
- {
- switch (cif->rtype->type)
- {
- case FFI_TYPE_FLOAT:
- return FFI_TYPE_UINT32;
- break;
- case FFI_TYPE_DOUBLE:
- return FFI_TYPE_UINT64;
- break;
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- case FFI_TYPE_LONGDOUBLE:
- return FFI_TYPE_UINT128;
- break;
-#endif
- default:
- return cif->rtype->type;
- }
- }
- else
- {
- return cif->rtype->type;
- }
+ return rtypenum;
}
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
diff --git a/libffi/src/powerpc/ffitarget.h b/libffi/src/powerpc/ffitarget.h
index d17f7312d81..3c9db495f49 100644
--- a/libffi/src/powerpc/ffitarget.h
+++ b/libffi/src/powerpc/ffitarget.h
@@ -1,6 +1,8 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
- Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc
+ Copyright (c) 1996-2003 Red Hat, Inc.
+
Target configuration macros for PowerPC.
Permission is hereby granted, free of charge, to any person obtaining
@@ -28,6 +30,10 @@
#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 ----------------------------------- */
#if defined (POWERPC) && defined (__powerpc64__) /* linux64 */
@@ -60,18 +66,14 @@ typedef enum ffi_abi {
FFI_LINUX64,
FFI_LINUX,
FFI_LINUX_SOFT_FLOAT,
-# ifdef POWERPC64
+# if defined(POWERPC64)
FFI_DEFAULT_ABI = FFI_LINUX64,
-# else
-# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
- FFI_DEFAULT_ABI = FFI_LINUX,
-# else
-# ifdef __NO_FPRS__
+# elif defined(__NO_FPRS__)
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
-# else
+# elif (__LDBL_MANT_DIG__ == 106)
+ FFI_DEFAULT_ABI = FFI_LINUX,
+# else
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
-# endif
-# endif
# endif
#endif
diff --git a/libffi/src/powerpc/ppc_closure.S b/libffi/src/powerpc/ppc_closure.S
index 56f7d1af2c8..41fb8851b62 100644
--- a/libffi/src/powerpc/ppc_closure.S
+++ b/libffi/src/powerpc/ppc_closure.S
@@ -122,22 +122,41 @@ ENTRY(ffi_closure_SYSV)
blr
# case FFI_TYPE_FLOAT
+#ifndef __NO_FPRS__
lfs %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
+#else
+ nop
+ nop
+ nop
+#endif
blr
# case FFI_TYPE_DOUBLE
+#ifndef __NO_FPRS__
lfd %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
+#else
+ nop
+ nop
+ nop
+#endif
blr
# case FFI_TYPE_LONGDOUBLE
+#ifndef __NO_FPRS__
lfd %f1,112+0(%r1)
lfd %f2,112+8(%r1)
mtlr %r0
b .Lfinish
+#else
+ nop
+ nop
+ nop
+ blr
+#endif
# case FFI_TYPE_UINT8
lbz %r3,112+3(%r1)
diff --git a/libffi/src/powerpc/sysv.S b/libffi/src/powerpc/sysv.S
index 96ea22b0b40..675ed03eeb9 100644
--- a/libffi/src/powerpc/sysv.S
+++ b/libffi/src/powerpc/sysv.S
@@ -83,6 +83,7 @@ ENTRY(ffi_call_SYSV)
nop
1:
+#ifndef __NO_FPRS__
/* Load all the FP registers. */
bf- 6,2f
lfd %f1,-16-(8*4)-(8*8)(%r28)
@@ -94,6 +95,7 @@ ENTRY(ffi_call_SYSV)
lfd %f6,-16-(8*4)-(3*8)(%r28)
lfd %f7,-16-(8*4)-(2*8)(%r28)
lfd %f8,-16-(8*4)-(1*8)(%r28)
+#endif
2:
/* Make the call. */
@@ -103,7 +105,9 @@ ENTRY(ffi_call_SYSV)
mtcrf 0x01,%r31 /* cr7 */
bt- 31,L(small_struct_return_value)
bt- 30,L(done_return_value)
+#ifndef __NO_FPRS__
bt- 29,L(fp_return_value)
+#endif
stw %r3,0(%r30)
bf+ 28,L(done_return_value)
stw %r4,4(%r30)
@@ -124,6 +128,7 @@ L(done_return_value):
lwz %r1,0(%r1)
blr
+#ifndef __NO_FPRS__
L(fp_return_value):
bf 28,L(float_return_value)
stfd %f1,0(%r30)
@@ -134,21 +139,17 @@ L(fp_return_value):
L(float_return_value):
stfs %f1,0(%r30)
b L(done_return_value)
+#endif
L(small_struct_return_value):
- extrwi %r6,%r31,2,19 /* number of bytes padding = shift/8 */
- mtcrf 0x02,%r31 /* copy flags to cr[24:27] (cr6) */
- extrwi %r5,%r31,5,19 /* r5 <- number of bits of padding */
- subfic %r6,%r6,4 /* r6 <- number of useful bytes in r3 */
- bf- 25,L(done_return_value) /* struct in r3 ? if not, done. */
-/* smst_one_register: */
- slw %r3,%r3,%r5 /* Left-justify value in r3 */
- mtxer %r6 /* move byte count to XER ... */
- stswx %r3,0,%r30 /* ... and store that many bytes */
- bf+ 26,L(done_return_value) /* struct in r3:r4 ? */
- add %r6,%r6,%r30 /* adjust pointer */
- stswi %r4,%r6,4 /* store last four bytes */
- b L(done_return_value)
+ /*
+ * The C code always allocates a properly-aligned 8-byte bounce
+ * buffer to make this assembly code very simple. Just write out
+ * r3 and r4 to the buffer to allow the C code to handle the rest.
+ */
+ stw %r3, 0(%r30)
+ stw %r4, 4(%r30)
+ b L(done_return_value)
.LFE1:
END(ffi_call_SYSV)
diff --git a/libffi/src/prep_cif.c b/libffi/src/prep_cif.c
index e0a0c68cac5..eb6834199b1 100644
--- a/libffi/src/prep_cif.c
+++ b/libffi/src/prep_cif.c
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
- prep_cif.c - Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
+ prep_cif.c - Copyright (c) 2011, 2012 Anthony Green
+ Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -37,17 +38,21 @@ static ffi_status initialize_aggregate(ffi_type *arg)
{
ffi_type **ptr;
- FFI_ASSERT(arg != NULL);
+ if (UNLIKELY(arg == NULL || arg->elements == NULL))
+ return FFI_BAD_TYPEDEF;
- FFI_ASSERT(arg->elements != NULL);
- FFI_ASSERT(arg->size == 0);
- FFI_ASSERT(arg->alignment == 0);
+ arg->size = 0;
+ arg->alignment = 0;
ptr = &(arg->elements[0]);
+ if (UNLIKELY(ptr == 0))
+ return FFI_BAD_TYPEDEF;
+
while ((*ptr) != NULL)
{
- if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+ if (UNLIKELY(((*ptr)->size == 0)
+ && (initialize_aggregate((*ptr)) != FFI_OK)))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */
@@ -85,24 +90,38 @@ static ffi_status initialize_aggregate(ffi_type *arg)
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
-ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
- ffi_type *rtype, ffi_type **atypes)
+/* For non variadic functions isvariadic should be 0 and
+ nfixedargs==ntotalargs.
+
+ For variadic calls, isvariadic should be 1 and nfixedargs
+ and ntotalargs set as appropriate. nfixedargs must always be >=1 */
+
+
+ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
+ unsigned int isvariadic,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs,
+ ffi_type *rtype, ffi_type **atypes)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT(cif != NULL);
+ FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
+ FFI_ASSERT(nfixedargs <= ntotalargs);
+
#ifndef X86_WIN32
- FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
+ if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
+ return FFI_BAD_ABI;
#else
- FFI_ASSERT(abi > FFI_FIRST_ABI && abi <= FFI_DEFAULT_ABI
- || abi == FFI_THISCALL);
+ if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL))
+ return FFI_BAD_ABI;
#endif
cif->abi = abi;
cif->arg_types = atypes;
- cif->nargs = nargs;
+ cif->nargs = ntotalargs;
cif->rtype = rtype;
cif->flags = 0;
@@ -115,7 +134,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
-#if !defined M68K && !defined __i386__ && !defined __x86_64__ && !defined S390 && !defined PA
+#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC
@@ -136,7 +155,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
-#if !defined __i386__ && !defined __x86_64__ && !defined S390 && !defined PA
+#if !defined X86_ANY && !defined S390 && !defined PA
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
@@ -158,10 +177,31 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
cif->bytes = bytes;
/* Perform machine dependent cif processing */
+#ifdef FFI_TARGET_SPECIFIC_VARIADIC
+ if (isvariadic)
+ return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
+#endif
+
return ffi_prep_cif_machdep(cif);
}
#endif /* not __CRIS__ */
+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
+ ffi_type *rtype, ffi_type **atypes)
+{
+ return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
+}
+
+ffi_status ffi_prep_cif_var(ffi_cif *cif,
+ ffi_abi abi,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs,
+ ffi_type *rtype,
+ ffi_type **atypes)
+{
+ return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
+}
+
#if FFI_CLOSURES
ffi_status
diff --git a/libffi/src/s390/ffitarget.h b/libffi/src/s390/ffitarget.h
index 386273897e2..97fa5c4b671 100644
--- a/libffi/src/s390/ffitarget.h
+++ b/libffi/src/s390/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for S390.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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
+
#if defined (__s390x__)
#ifndef S390X
#define S390X
@@ -42,8 +47,8 @@ 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_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
diff --git a/libffi/src/sh/ffitarget.h b/libffi/src/sh/ffitarget.h
index 218ae3d0a4a..a36bf420704 100644
--- a/libffi/src/sh/ffitarget.h
+++ b/libffi/src/sh/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for SuperH.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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
@@ -36,8 +41,8 @@ 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_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif
diff --git a/libffi/src/sh64/ffitarget.h b/libffi/src/sh64/ffitarget.h
index 4e922fc79f1..08a6fe96cc7 100644
--- a/libffi/src/sh64/ffitarget.h
+++ b/libffi/src/sh64/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for SuperH - SHmedia.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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
@@ -36,8 +41,8 @@ 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_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#define FFI_EXTRA_CIF_FIELDS long long flags2
diff --git a/libffi/src/sparc/ffi.c b/libffi/src/sparc/ffi.c
index 1d01f59ec23..1ac5d464e8b 100644
--- a/libffi/src/sparc/ffi.c
+++ b/libffi/src/sparc/ffi.c
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1996, 2003, 2004, 2007, 2008 Red Hat, Inc.
+ ffi.c - Copyright (c) 2011 Anthony Green
+ Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
SPARC Foreign Function Interface
@@ -406,8 +407,50 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
/* We don't yet support calling 32bit code from 64bit */
FFI_ASSERT(0);
#else
- ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
- cif->flags, rvalue, fn);
+ if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ || cif->flags == FFI_TYPE_LONGDOUBLE
+#endif
+ ))
+ {
+ /* For v8, we need an "unimp" with size of returning struct */
+ /* behind "call", so we alloc some executable space for it. */
+ /* l7 is used, we need to make sure v8.S doesn't use %l7. */
+ unsigned int *call_struct = NULL;
+ ffi_closure_alloc(32, &call_struct);
+ if (call_struct)
+ {
+ unsigned long f = (unsigned long)fn;
+ call_struct[0] = 0xae10001f; /* mov %i7, %l7 */
+ call_struct[1] = 0xbe10000f; /* mov %o7, %i7 */
+ call_struct[2] = 0x03000000 | f >> 10; /* sethi %hi(fn), %g1 */
+ call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
+ call_struct[4] = 0x01000000; /* nop */
+ if (cif->rtype->size < 0x7f)
+ call_struct[5] = cif->rtype->size; /* unimp */
+ else
+ call_struct[5] = 0x01000000; /* nop */
+ call_struct[6] = 0x81c7e008; /* ret */
+ call_struct[7] = 0xbe100017; /* mov %l7, %i7 */
+ asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
+ "r" (call_struct) : "memory");
+ /* SPARC v8 requires 5 instructions for flush to be visible */
+ asm volatile ("nop; nop; nop; nop; nop");
+ ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
+ cif->flags, rvalue, call_struct);
+ ffi_closure_free(call_struct);
+ }
+ else
+ {
+ ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
+ cif->flags, rvalue, fn);
+ }
+ }
+ else
+ {
+ ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
+ cif->flags, rvalue, fn);
+ }
#endif
break;
case FFI_V9:
@@ -425,7 +468,6 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
FFI_ASSERT(0);
break;
}
-
}
@@ -447,7 +489,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
#ifdef SPARC64
/* Trampoline address is equal to the closure address. We take advantage
of that to reduce the trampoline size by 8 bytes. */
- FFI_ASSERT (cif->abi == FFI_V9);
+ if (cif->abi != FFI_V9)
+ return FFI_BAD_ABI;
fn = (unsigned long) ffi_closure_v9;
tramp[0] = 0x83414000; /* rd %pc, %g1 */
tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
@@ -456,7 +499,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
*((unsigned long *) &tramp[4]) = fn;
#else
unsigned long ctx = (unsigned long) codeloc;
- FFI_ASSERT (cif->abi == FFI_V8);
+ if (cif->abi != FFI_V8)
+ return FFI_BAD_ABI;
fn = (unsigned long) ffi_closure_v8;
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */
@@ -468,13 +512,13 @@ ffi_prep_closure_loc (ffi_closure* closure,
closure->fun = fun;
closure->user_data = user_data;
- /* Flush the Icache. FIXME: alignment isn't certain, assume 8 bytes */
+ /* Flush the Icache. closure is 8 bytes aligned. */
#ifdef SPARC64
- asm volatile ("flush %0" : : "r" (closure) : "memory");
- asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory");
+ asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory");
#else
- asm volatile ("iflush %0" : : "r" (closure) : "memory");
- asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory");
+ asm volatile ("iflush %0; iflush %0+8" : : "r" (closure) : "memory");
+ /* SPARC v8 requires 5 instructions for flush to be visible */
+ asm volatile ("nop; nop; nop; nop; nop");
#endif
return FFI_OK;
diff --git a/libffi/src/sparc/ffitarget.h b/libffi/src/sparc/ffitarget.h
index 50554b8805d..d89f7877a81 100644
--- a/libffi/src/sparc/ffitarget.h
+++ b/libffi/src/sparc/ffitarget.h
@@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for SPARC.
Permission is hereby granted, free of charge, to any person obtaining
@@ -27,6 +28,10 @@
#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 ----------------------------------- */
#if defined(__arch64__) || defined(__sparcv9)
@@ -44,12 +49,12 @@ typedef enum ffi_abi {
FFI_V8,
FFI_V8PLUS,
FFI_V9,
+ FFI_LAST_ABI,
#ifdef SPARC64
- FFI_DEFAULT_ABI = FFI_V9,
+ FFI_DEFAULT_ABI = FFI_V9
#else
- FFI_DEFAULT_ABI = FFI_V8,
+ FFI_DEFAULT_ABI = FFI_V8
#endif
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif
diff --git a/libffi/src/sparc/v9.S b/libffi/src/sparc/v9.S
index bf31a2b5110..489ff0293f2 100644
--- a/libffi/src/sparc/v9.S
+++ b/libffi/src/sparc/v9.S
@@ -32,7 +32,7 @@
/* Only compile this in for 64bit builds, because otherwise the object file
will have inproper architecture due to used instructions. */
-#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */
+#define STACKFRAME 128 /* Minimum stack framesize for SPARC */
#define STACK_BIAS 2047
#define ARGS (128) /* Offset of register area in frame */
diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c
index 469578ea504..9343c260728 100644
--- a/libffi/src/x86/ffi.c
+++ b/libffi/src/x86/ffi.c
@@ -228,12 +228,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
-#if defined(X86) || defined (X86_WIN32) || defined(X86_FREEBSD) || defined(X86_DARWIN) || defined(X86_WIN64)
case FFI_TYPE_UINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT8:
case FFI_TYPE_SINT16:
-#endif
#ifdef X86_WIN64
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
@@ -364,27 +362,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
#ifdef X86_WIN64
case FFI_WIN64:
- {
- /* Make copies of all struct arguments
- NOTE: not sure if responsibility should be here or in caller */
- unsigned int i;
- for (i=0; i < cif->nargs;i++) {
- size_t size = cif->arg_types[i]->size;
- if ((cif->arg_types[i]->type == FFI_TYPE_STRUCT
- && (size != 1 && size != 2 && size != 4 && size != 8))
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
- || cif->arg_types[i]->type == FFI_TYPE_LONGDOUBLE
-#endif
- )
- {
- void *local = alloca(size);
- memcpy(local, avalue[i], size);
- avalue[i] = local;
- }
- }
- ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- }
+ ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
+ cif->flags, ecif.rvalue, fn);
break;
#elif defined(X86_WIN32)
case FFI_SYSV:
@@ -447,8 +426,6 @@ unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
__attribute__ ((regparm(1)));
#ifdef X86_WIN32
-void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
- __attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
__attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
@@ -616,7 +593,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
- unsigned int __dis = __fun - (__ctx + 49); \
+ unsigned int __dis = __fun - (__ctx + 22); \
unsigned short __size = (unsigned short)(SIZE); \
*(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
*(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
@@ -722,9 +699,6 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
int i;
if (cif->abi != FFI_SYSV) {
-#ifdef X86_WIN32
- if (cif->abi != FFI_THISCALL)
-#endif
return FFI_BAD_ABI;
}
@@ -739,20 +713,10 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
}
-#ifdef X86_WIN32
- if (cif->abi == FFI_SYSV)
- {
-#endif
+
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
codeloc);
-#ifdef X86_WIN32
- }
- else if (cif->abi == FFI_THISCALL)
- {
- FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
- codeloc, cif->bytes);
- }
-#endif
+
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
@@ -797,7 +761,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
#ifdef X86_WIN32
case FFI_SYSV:
case FFI_STDCALL:
- ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
+ ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
ecif.rvalue, fn);
break;
case FFI_THISCALL:
@@ -825,7 +789,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
cif->abi = abi = FFI_THISCALL;
if (passed_regs < 1 && abi == FFI_THISCALL)
cif->abi = abi = FFI_STDCALL;
- ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
+ ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
ecif.rvalue, fn);
}
break;
diff --git a/libffi/src/x86/ffi64.c b/libffi/src/x86/ffi64.c
index bd907d7208c..defd7744cce 100644
--- a/libffi/src/x86/ffi64.c
+++ b/libffi/src/x86/ffi64.c
@@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
- ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
+ ffi64.c - Copyright (c) 20011 Anthony Green
Copyright (c) 2008, 2010 Red Hat, Inc.
-
+ Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
+
x86-64 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
@@ -426,7 +427,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
/* If the return value is passed in memory, add the pointer as the
first integer argument. */
if (ret_in_memory)
- reg_args->gpr[gprcount++] = (long) rvalue;
+ reg_args->gpr[gprcount++] = (unsigned long) rvalue;
avn = cif->nargs;
arg_types = cif->arg_types;
@@ -498,12 +499,21 @@ ffi_prep_closure_loc (ffi_closure* closure,
{
volatile unsigned short *tramp;
+ /* Sanity check on the cif ABI. */
+ {
+ int abi = cif->abi;
+ if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)))
+ return FFI_BAD_ABI;
+ }
+
tramp = (volatile unsigned short *) &closure->tramp[0];
tramp[0] = 0xbb49; /* mov <code>, %r11 */
- *(void * volatile *) &tramp[1] = ffi_closure_unix64;
+ *((unsigned long long * volatile) &tramp[1])
+ = (unsigned long) ffi_closure_unix64;
tramp[5] = 0xba49; /* mov <data>, %r10 */
- *(void * volatile *) &tramp[6] = codeloc;
+ *((unsigned long long * volatile) &tramp[6])
+ = (unsigned long) codeloc;
/* Set the carry bit iff the function uses any sse registers.
This is clc or stc, together with the first byte of the jmp. */
@@ -542,7 +552,7 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
{
/* The return value goes in memory. Arrange for the closure
return value to go directly back to the original caller. */
- rvalue = (void *) reg_args->gpr[gprcount++];
+ rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
/* We don't have to do anything in asm for the return. */
ret = FFI_TYPE_VOID;
}
diff --git a/libffi/src/x86/ffitarget.h b/libffi/src/x86/ffitarget.h
index dfecd1b3c6e..54a61212e4f 100644
--- a/libffi/src/x86/ffitarget.h
+++ b/libffi/src/x86/ffitarget.h
@@ -1,6 +1,7 @@
/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003, 2010 Red Hat, Inc.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ ffitarget.h - Copyright (c) 2012 Anthony Green
+ Copyright (c) 1996-2003, 2010 Red Hat, Inc.
+ Copyright (C) 2008 Free Software Foundation, Inc.
Target configuration macros for x86 and x86-64.
@@ -29,8 +30,15 @@
#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 ----------------------------------- */
+/* For code common to all platforms on x86 and x86_64. */
+#define X86_ANY
+
#if defined (X86_64) && defined (__i386__)
#undef X86_64
#define X86
@@ -53,9 +61,15 @@ typedef unsigned long long ffi_arg;
typedef long long ffi_sarg;
#endif
#else
+#if defined __x86_64__ && !defined __LP64__
+#define FFI_SIZEOF_ARG 8
+typedef unsigned long long ffi_arg;
+typedef long long ffi_sarg;
+#else
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
#endif
+#endif
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
@@ -66,28 +80,26 @@ typedef enum ffi_abi {
FFI_STDCALL,
FFI_THISCALL,
FFI_FASTCALL,
+ FFI_LAST_ABI,
/* TODO: Add fastcall support for the sake of completeness */
- FFI_DEFAULT_ABI = FFI_SYSV,
-#endif
+ FFI_DEFAULT_ABI = FFI_SYSV
-#ifdef X86_WIN64
+#elif defined(X86_WIN64)
FFI_WIN64,
- FFI_DEFAULT_ABI = FFI_WIN64,
-#else
+ FFI_LAST_ABI,
+ FFI_DEFAULT_ABI = FFI_WIN64
+#else
/* ---- Intel x86 and AMD x86-64 - */
-#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__) || defined(__i386) || defined(__amd64))
FFI_SYSV,
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
+ FFI_LAST_ABI,
#if defined(__i386__) || defined(__i386)
- FFI_DEFAULT_ABI = FFI_SYSV,
+ FFI_DEFAULT_ABI = FFI_SYSV
#else
- FFI_DEFAULT_ABI = FFI_UNIX64,
+ FFI_DEFAULT_ABI = FFI_UNIX64
#endif
#endif
-#endif /* X86_WIN64 */
-
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif
diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S
index deb4a0394d8..e5c93ecf7b9 100644
--- a/libffi/src/x86/win32.S
+++ b/libffi/src/x86/win32.S
@@ -264,18 +264,6 @@ ffi_closure_SYSV ENDP
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20
-ffi_closure_raw_THISCALL PROC NEAR
- push ebp
- mov ebp, esp
- push esi
- sub esp, 36
- mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
- mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
- mov [esp + 12], edx
- lea edx, [ebp + 12], edx
- jmp stubraw
-ffi_closure_raw_SYSV ENDP
-
ffi_closure_raw_SYSV PROC NEAR USES esi
;; the ffi_closure ctx is passed in eax by the trampoline.
@@ -284,7 +272,6 @@ ffi_closure_raw_SYSV PROC NEAR USES esi
mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
mov [esp + 12], edx ;; user_data
lea edx, [ebp + 8]
-stubraw:
mov [esp + 8], edx ;; raw_args
lea edx, [ebp - 24]
mov [esp + 4], edx ;; &res
@@ -735,21 +722,7 @@ _ffi_closure_SYSV:
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20
- .balign 16
- .globl _ffi_closure_raw_THISCALL
-#ifndef __OS2__
- .def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef
-#endif
-_ffi_closure_raw_THISCALL:
- pushl %ebp
- movl %esp, %ebp
- pushl %esi
- subl $36, %esp
- movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
- movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
- movl %edx, 12(%esp) /* user_data */
- leal 12(%ebp), %edx /* __builtin_dwarf_cfa () */
- jmp .stubraw
+
# This assumes we are using gas.
.balign 16
.globl _ffi_closure_raw_SYSV
@@ -769,7 +742,6 @@ _ffi_closure_raw_SYSV:
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
movl %edx, 12(%esp) /* user_data */
leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
-.stubraw:
movl %edx, 8(%esp) /* raw_args */
leal -24(%ebp), %edx
movl %edx, 4(%esp) /* &res */
diff --git a/libffi/src/x86/win64.S b/libffi/src/x86/win64.S
index 6e9181867de..fcdb270faf5 100644
--- a/libffi/src/x86/win64.S
+++ b/libffi/src/x86/win64.S
@@ -232,10 +232,18 @@ ret_void$:
ffi_call_win64 ENDP
_TEXT ENDS
END
-#else
+
+#else
+
+#ifdef SYMBOL_UNDERSCORE
+#define SYMBOL_NAME(name) _##name
+#else
+#define SYMBOL_NAME(name) name
+#endif
+
.text
-.extern _ffi_closure_win64_inner
+.extern SYMBOL_NAME(ffi_closure_win64_inner)
# ffi_closure_win64 will be called with these registers set:
# rax points to 'closure'
@@ -246,8 +254,8 @@ END
# call ffi_closure_win64_inner for the actual work, then return the result.
#
.balign 16
- .globl _ffi_closure_win64
-_ffi_closure_win64:
+ .globl SYMBOL_NAME(ffi_closure_win64)
+SYMBOL_NAME(ffi_closure_win64):
# copy register arguments onto stack
test $1,%r11
jne .Lfirst_is_float
@@ -287,7 +295,7 @@ _ffi_closure_win64:
mov %rax, %rcx # context is first parameter
mov %rsp, %rdx # stack is second parameter
add $48, %rdx # point to start of arguments
- mov $_ffi_closure_win64_inner, %rax
+ mov $SYMBOL_NAME(ffi_closure_win64_inner), %rax
callq *%rax # call the real closure function
add $40, %rsp
movq %rax, %xmm0 # If the closure returned a float,
@@ -296,8 +304,8 @@ _ffi_closure_win64:
.ffi_closure_win64_end:
.balign 16
- .globl _ffi_call_win64
-_ffi_call_win64:
+ .globl SYMBOL_NAME(ffi_call_win64)
+SYMBOL_NAME(ffi_call_win64):
# copy registers onto stack
mov %r9,32(%rsp)
mov %r8,24(%rsp)
diff --git a/libffi/testsuite/libffi.call/cls_double_va.c b/libffi/testsuite/libffi.call/cls_double_va.c
index e769caf47b9..67e44a4ed3d 100644
--- a/libffi/testsuite/libffi.call/cls_double_va.c
+++ b/libffi/testsuite/libffi.call/cls_double_va.c
@@ -37,7 +37,8 @@ int main (void)
arg_types[1] = &ffi_type_double;
arg_types[2] = NULL;
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
+ /* This printf call is variadic */
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
arg_types) == FFI_OK);
args[0] = &format;
@@ -49,6 +50,9 @@ int main (void)
printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" }
+ /* The call to cls_double_va_fn is static, so have to use a normal prep_cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint, arg_types) == FFI_OK);
+
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL, code) == FFI_OK);
res = ((int(*)(char*, double))(code))(format, doubleArg);
diff --git a/libffi/testsuite/libffi.call/cls_longdouble_va.c b/libffi/testsuite/libffi.call/cls_longdouble_va.c
index 07780ede4cd..6b8484a8595 100644
--- a/libffi/testsuite/libffi.call/cls_longdouble_va.c
+++ b/libffi/testsuite/libffi.call/cls_longdouble_va.c
@@ -37,7 +37,8 @@ int main (void)
arg_types[1] = &ffi_type_longdouble;
arg_types[2] = NULL;
- CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
+ /* This printf call is variadic */
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
arg_types) == FFI_OK);
args[0] = &format;
@@ -49,6 +50,10 @@ int main (void)
printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" }
+ /* The call to cls_longdouble_va_fn is static, so have to use a normal prep_cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
+ arg_types) == FFI_OK);
+
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL, code) == FFI_OK);
res = ((int(*)(char*, long double))(code))(format, ldArg);
diff --git a/libffi/testsuite/libffi.call/err_bad_abi.c b/libffi/testsuite/libffi.call/err_bad_abi.c
index ce0f3bb2782..f5a73179ec9 100644
--- a/libffi/testsuite/libffi.call/err_bad_abi.c
+++ b/libffi/testsuite/libffi.call/err_bad_abi.c
@@ -4,7 +4,8 @@
PR: none.
Originator: Blake Chaffin 6/6/2007 */
-/* { dg-do run { xfail *-*-* } } */
+/* { dg-do run } */
+
#include "ffitest.h"
static void
diff --git a/libffi/testsuite/libffi.call/err_bad_typedef.c b/libffi/testsuite/libffi.call/err_bad_typedef.c
index bd2fc54a0e8..253927392d3 100644
--- a/libffi/testsuite/libffi.call/err_bad_typedef.c
+++ b/libffi/testsuite/libffi.call/err_bad_typedef.c
@@ -4,7 +4,8 @@
PR: none.
Originator: Blake Chaffin 6/6/2007 */
-/* { dg-do run { xfail *-*-* } } */
+/* { dg-do run } */
+
#include "ffitest.h"
int main (void)
diff --git a/libffi/testsuite/libffi.call/float_va.c b/libffi/testsuite/libffi.call/float_va.c
new file mode 100644
index 00000000000..2039ae54791
--- /dev/null
+++ b/libffi/testsuite/libffi.call/float_va.c
@@ -0,0 +1,107 @@
+/* Area: fp and variadics
+ Purpose: check fp inputs and returns work on variadics, even the fixed params
+ Limitations: None
+ PR: none
+ Originator: <david.gilbert@linaro.org> 2011-01-25
+
+ Intended to stress the difference in ABI on ARM vfp
+*/
+
+/* { dg-do run } */
+
+#include <stdarg.h>
+
+#include "ffitest.h"
+
+/* prints out all the parameters, and returns the sum of them all.
+ * 'x' is the number of variadic parameters all of which are double in this test
+ */
+double float_va_fn(unsigned int x, double y,...)
+{
+ double total=0.0;
+ va_list ap;
+ unsigned int i;
+
+ total+=(double)x;
+ total+=y;
+
+ printf("%u: %.1lf :", x, y);
+
+ va_start(ap, y);
+ for(i=0;i<x;i++)
+ {
+ double arg=va_arg(ap, double);
+ total+=arg;
+ printf(" %d:%.1lf ", i, arg);
+ }
+ va_end(ap);
+
+ printf(" total: %.1lf\n", total);
+
+ return total;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+
+ ffi_type *arg_types[5];
+ void *values[5];
+ double doubles[5];
+ unsigned int firstarg;
+ double resfp;
+
+ /* First test, pass float_va_fn(0,2.0) - note there are no actual
+ * variadic parameters, but it's declared variadic so the ABI may be
+ * different. */
+ /* Call it statically and then via ffi */
+ resfp=float_va_fn(0,2.0);
+ // { dg-output "0: 2.0 : total: 2.0" }
+ printf("compiled: %.1lf\n", resfp);
+ // { dg-output "\ncompiled: 2.0" }
+
+ arg_types[0] = &ffi_type_uint;
+ arg_types[1] = &ffi_type_double;
+ arg_types[2] = NULL;
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 2,
+ &ffi_type_double, arg_types) == FFI_OK);
+
+ firstarg = 0;
+ doubles[0] = 2.0;
+ values[0] = &firstarg;
+ values[1] = &doubles[0];
+ ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
+ // { dg-output "\n0: 2.0 : total: 2.0" }
+ printf("ffi: %.1lf\n", resfp);
+ // { dg-output "\nffi: 2.0" }
+
+ /* Second test, float_va_fn(2,2.0,3.0,4.0), now with variadic params */
+ /* Call it statically and then via ffi */
+ resfp=float_va_fn(2,2.0,3.0,4.0);
+ // { dg-output "\n2: 2.0 : 0:3.0 1:4.0 total: 11.0" }
+ printf("compiled: %.1lf\n", resfp);
+ // { dg-output "\ncompiled: 11.0" }
+
+ arg_types[0] = &ffi_type_uint;
+ arg_types[1] = &ffi_type_double;
+ arg_types[2] = &ffi_type_double;
+ arg_types[3] = &ffi_type_double;
+ arg_types[4] = NULL;
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 4,
+ &ffi_type_double, arg_types) == FFI_OK);
+
+ firstarg = 2;
+ doubles[0] = 2.0;
+ doubles[1] = 3.0;
+ doubles[2] = 4.0;
+ values[0] = &firstarg;
+ values[1] = &doubles[0];
+ values[2] = &doubles[1];
+ values[3] = &doubles[2];
+ ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
+ // { dg-output "\n2: 2.0 : 0:3.0 1:4.0 total: 11.0" }
+ printf("ffi: %.1lf\n", resfp);
+ // { dg-output "\nffi: 11.0" }
+
+ exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/return_sc.c b/libffi/testsuite/libffi.call/return_sc.c
index 19608ee7c8b..a36cf3eb880 100644
--- a/libffi/testsuite/libffi.call/return_sc.c
+++ b/libffi/testsuite/libffi.call/return_sc.c
@@ -30,7 +30,7 @@ int main (void)
sc < (signed char) 127; sc++)
{
ffi_call(&cif, FFI_FN(return_sc), &rint, values);
- CHECK(rint == (ffi_arg) sc);
+ CHECK((signed char)rint == sc);
}
exit(0);
}