aboutsummaryrefslogtreecommitdiff
path: root/libffi/src
diff options
context:
space:
mode:
authorAnthony Green <green@gcc.gnu.org>2012-03-04 21:11:09 +0000
committerAnthony Green <green@gcc.gnu.org>2012-03-04 21:11:09 +0000
commit34fa7690ac66c6d3c5ddb1d35d267836e3c23f3d (patch)
tree3289bacfc83a97eaf50f42a61d0b9a06f4c76e9c /libffi/src
parent8b59af5c6af6e67e151b72e48074f58b677b2e42 (diff)
downloadgcc-34fa7690ac66c6d3c5ddb1d35d267836e3c23f3d.zip
gcc-34fa7690ac66c6d3c5ddb1d35d267836e3c23f3d.tar.gz
gcc-34fa7690ac66c6d3c5ddb1d35d267836e3c23f3d.tar.bz2
Merge upstream libffi
From-SVN: r184897
Diffstat (limited to 'libffi/src')
-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
45 files changed, 5603 insertions, 553 deletions
diff --git a/libffi/src/alpha/ffi.c b/libffi/src/alpha/ffi.c
index 8d6b2ba..192f691 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 7d06eb0..af145bc 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 d526033..1f8597d 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 ce25b23..26d494d 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 0000000..74f0b86
--- /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 be6493a..60e2ae3 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 0000000..7b47429
--- /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 39fba2b..3d43397 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 1c799b1..d0c7586 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 ff2b1bd..1b37827 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 e9c3953..aaca5b1 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 4257f10..b837e97 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 0fa235a..5c9f9c2 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 1c319ea9..d42540e 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 79e29b4..9533ef6 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 d85c049..e68cea6 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 9c5383e..522c8bf 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 6a761f6..6c34801 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 0d4df1e..d95c72b 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 633717b..e81dde2 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 d714cc9..79cff9b 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 d0fc983..717d659 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 6d7606f..4ce2bc6 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 001f891..5e364d3 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 c6f8764..213f2db 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 5c74448..c906017c 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 e86e6b0..994f62d 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 3b425da..4f987dc 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 b43f965..3f6790f 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 75784a9..1920c9110 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 d17f731..3c9db49 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 56f7d1a..41fb885 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 96ea22b..675ed03 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 e0a0c68..eb68341 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 3862738..97fa5c4 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 218ae3d..a36bf42 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 4e922fc..08a6fe9 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 1d01f59..1ac5d46 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 50554b8..d89f787 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 bf31a2b..489ff02 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 469578e..9343c26 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 bd907d7..defd774 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 dfecd1b..54a61212 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 deb4a03..e5c93ecf 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 6e918186..fcdb270 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)