public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 00/10] Go closures for arm
@ 2014-10-29 20:05 Richard Henderson
  2014-10-29 20:06 ` [PATCH 07/10] arm: Remove internal FFI_TYPE constants Richard Henderson
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:05 UTC (permalink / raw)
  To: libffi-discuss

This patch set tidies up the port significantly, and adds
support for complex and Go closures.


r~


Richard Henderson (10):
  arm: Reindent arm/ffi.c
  arm: Deref ffi_align argument
  arm: Deref ffi_put_arg arguments
  arm: Rewrite vfp_type_p
  arm: Rewrite ffi_call
  arm: Rewrite ffi_closure
  arm: Remove internal FFI_TYPE constants
  arm: Add support for complex types
  arm: Add argument space for the hidden struct return pointer
  arm: Add support for Go closures

 Makefile.am                    |    7 +-
 src/arm/ffi.c                  | 1246 ++++++-----
 src/arm/ffitarget.h            |   10 +-
 src/arm/gentramp.sh            |  118 --
 src/arm/internal.h             |    7 +
 src/arm/sysv.S                 |  702 +++----
 src/arm/trampoline.S           | 4450 ----------------------------------------
 testsuite/libffi.call/call.exp |   10 +-
 8 files changed, 968 insertions(+), 5582 deletions(-)
 delete mode 100755 src/arm/gentramp.sh
 create mode 100644 src/arm/internal.h
 delete mode 100644 src/arm/trampoline.S

-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 03/10] arm: Deref ffi_put_arg arguments
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
  2014-10-29 20:06 ` [PATCH 07/10] arm: Remove internal FFI_TYPE constants Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 04/10] arm: Rewrite vfp_type_p Richard Henderson
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

---
 src/arm/ffi.c | 88 ++++++++++++++++++++++++++---------------------------------
 1 file changed, 38 insertions(+), 50 deletions(-)

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index 7d86e94..5e5ad0a 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -56,58 +56,46 @@ ffi_align (ffi_type *ty, void *p)
 }
 
 static size_t
-ffi_put_arg (ffi_type **arg_type, void **arg, char *stack)
+ffi_put_arg (ffi_type *ty, void *src, void *dst)
 {
-  register char *argp = stack;
-  register ffi_type **p_arg = arg_type;
-  register void **p_argv = arg;
-  register size_t z = (*p_arg)->size;
+  size_t z = ty->size;
 
-  if (z < sizeof (int))
+  switch (ty->type)
     {
-      z = sizeof (int);
-      switch ((*p_arg)->type)
-	{
-	case FFI_TYPE_SINT8:
-	  *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
-	  break;
-
-	case FFI_TYPE_UINT8:
-	  *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
-	  break;
-
-	case FFI_TYPE_SINT16:
-	  *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
-	  break;
+    case FFI_TYPE_SINT8:
+      *(UINT32 *)dst = *(SINT8 *)src;
+      break;
+    case FFI_TYPE_UINT8:
+      *(UINT32 *)dst = *(UINT8 *)src;
+      break;
+    case FFI_TYPE_SINT16:
+      *(UINT32 *)dst = *(SINT16 *)src;
+      break;
+    case FFI_TYPE_UINT16:
+      *(UINT32 *)dst = *(UINT16 *)src;
+      break;
 
-	case FFI_TYPE_UINT16:
-	  *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
-	  break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_FLOAT:
+      *(UINT32 *)dst = *(UINT32 *)src;
+      break;
 
-	case FFI_TYPE_STRUCT:
-	  memcpy (argp, *p_argv, (*p_arg)->size);
-	  break;
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_DOUBLE:
+      *(UINT64 *)dst = *(UINT64 *)src;
+      break;
 
-	default:
-	  FFI_ASSERT (0);
-	}
-    }
-  else if (z == sizeof (int))
-    {
-      if ((*p_arg)->type == FFI_TYPE_FLOAT)
-	*(float *) argp = *(float *) (*p_argv);
-      else
-	*(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
-    }
-  else if (z == sizeof (double) && (*p_arg)->type == FFI_TYPE_DOUBLE)
-    {
-      *(double *) argp = *(double *) (*p_argv);
-    }
-  else
-    {
-      memcpy (argp, *p_argv, z);
+    case FFI_TYPE_STRUCT:
+    default:
+      memcpy (dst, src, z);
+      break;
     }
-  return z;
+
+  return ALIGN (z, 4);
 }
 
 /* ffi_prep_args is called by the assembly routine once stack space
@@ -138,7 +126,7 @@ ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space)
        (i != 0); i--, p_arg++, p_argv++)
     {
       argp = ffi_align (*p_arg, argp);
-      argp += ffi_put_arg (p_arg, p_argv, argp);
+      argp += ffi_put_arg (*p_arg, *p_argv, argp);
     }
 
   return 0;
@@ -182,7 +170,7 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
       if (vi < ecif->cif->vfp_nargs && is_vfp_type)
 	{
 	  char *vfp_slot = (char *) (vfp_space + ecif->cif->vfp_args[vi++]);
-	  ffi_put_arg (p_arg, p_argv, vfp_slot);
+	  ffi_put_arg (*p_arg, *p_argv, vfp_slot);
 	  continue;
 	}
       /* Try allocating in core registers. */
@@ -195,7 +183,7 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
 	     area to place the argument.  */
 	  if (tregp + size <= eo_regp)
 	    {
-	      regp = tregp + ffi_put_arg (p_arg, p_argv, tregp);
+	      regp = tregp + ffi_put_arg (*p_arg, *p_argv, tregp);
 	      done_with_regs = (regp == argp);
 	      // ensure we did not write into the stack area
 	      FFI_ASSERT (regp <= argp);
@@ -208,7 +196,7 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
 	    {
 	      stack_used = 1;
 	      done_with_regs = 1;
-	      argp = tregp + ffi_put_arg (p_arg, p_argv, tregp);
+	      argp = tregp + ffi_put_arg (*p_arg, *p_argv, tregp);
 	      FFI_ASSERT (eo_regp < argp);
 	      continue;
 	    }
@@ -216,7 +204,7 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
       /* Base case, arguments are passed on the stack */
       stack_used = 1;
       argp = ffi_align (*p_arg, argp);
-      argp += ffi_put_arg (p_arg, p_argv, argp);
+      argp += ffi_put_arg (*p_arg, *p_argv, argp);
     }
   /* Indicate the VFP registers used. */
   return ecif->cif->vfp_used;
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 07/10] arm: Remove internal FFI_TYPE constants
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 03/10] arm: Deref ffi_put_arg arguments Richard Henderson
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

These have been replaced by the contents of internal.h.
---
 src/arm/ffitarget.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h
index 421bacf..bf36750 100644
--- a/src/arm/ffitarget.h
+++ b/src/arm/ffitarget.h
@@ -56,10 +56,6 @@ typedef enum ffi_abi {
   unsigned short vfp_reg_free, vfp_nargs;	\
   signed char vfp_args[16]			\
 
-/* Internally used. */
-#define FFI_TYPE_STRUCT_VFP_FLOAT  (FFI_TYPE_LAST + 1)
-#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
-
 #define FFI_TARGET_SPECIFIC_VARIADIC
 
 /* ---- Definitions for closures ----------------------------------------- */
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 09/10] arm: Add argument space for the hidden struct return pointer
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
                   ` (7 preceding siblings ...)
  2014-10-29 20:06 ` [PATCH 01/10] arm: Reindent arm/ffi.c Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 06/10] arm: Rewrite ffi_closure Richard Henderson
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

This should have been failing all along, but it's only
exposed by the complex_int test case.
---
 src/arm/ffi.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index 9a11e8f..eabab47 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -202,17 +202,7 @@ ffi_status
 ffi_prep_cif_machdep (ffi_cif *cif)
 {
   int flags = 0, cabi = cif->abi;
-  size_t bytes;
-
-  /* Round the stack up to a multiple of 8 bytes.  This isn't needed
-     everywhere, but it is on some platforms, and it doesn't harm anything
-     when it isn't needed.  */
-  bytes = ALIGN (cif->bytes, 8);
-
-  /* Minimum stack space is the 4 register arguments that we pop.  */
-  if (bytes < 4*4)
-    bytes = 4*4;
-  cif->bytes = bytes;
+  size_t bytes = cif->bytes;
 
   /* Map out the register placements of VFP register args.  The VFP
      hard-float calling conventions are slightly more sophisticated
@@ -270,12 +260,29 @@ ffi_prep_cif_machdep (ffi_cif *cif)
 	 A Composite Type larger than 4 bytes, or whose size cannot
 	 be determined statically ... is stored in memory at an
 	 address passed [in r0].  */
-      flags = (cif->rtype->size <= 4 ? ARM_TYPE_INT : ARM_TYPE_STRUCT);
+      if (cif->rtype->size <= 4)
+	flags = ARM_TYPE_INT;
+      else
+	{
+	  flags = ARM_TYPE_STRUCT;
+	  bytes += 4;
+	}
       break;
 
     default:
       abort();
     }
+
+  /* Round the stack up to a multiple of 8 bytes.  This isn't needed
+     everywhere, but it is on some platforms, and it doesn't harm anything
+     when it isn't needed.  */
+  bytes = ALIGN (bytes, 8);
+
+  /* Minimum stack space is the 4 register arguments that we pop.  */
+  if (bytes < 4*4)
+    bytes = 4*4;
+
+  cif->bytes = bytes;
   cif->flags = flags;
 
   return FFI_OK;
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 02/10] arm: Deref ffi_align argument
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
                   ` (4 preceding siblings ...)
  2014-10-29 20:06 ` [PATCH 08/10] arm: Add support for complex types Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 10/10] arm: Add support for Go closures Richard Henderson
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

---
 src/arm/ffi.c | 41 +++++++++++++++--------------------------
 1 file changed, 15 insertions(+), 26 deletions(-)

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index c5fd831..7d86e94 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -40,30 +40,19 @@ static void layout_vfp_args (ffi_cif *);
 int ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space);
 int ffi_prep_args_VFP (char *stack, extended_cif *ecif, float *vfp_space);
 
-static char *
-ffi_align (ffi_type **p_arg, char *argp)
+static void *
+ffi_align (ffi_type *ty, void *p)
 {
   /* Align if necessary */
-  register size_t alignment = (*p_arg)->alignment;
-  if (alignment < 4)
-    {
-      alignment = 4;
-    }
+  size_t alignment;
 #ifdef _WIN32_WCE
-  if (alignment > 4)
-    {
-      alignment = 4;
-    }
+  alignment = 4;
+#else
+  alignment = ty->alignment;
+  if (alignment < 4)
+    alignment = 4;
 #endif
-  if ((alignment - 1) & (unsigned) argp)
-    {
-      argp = (char *) ALIGN (argp, alignment);
-    }
-  if ((*p_arg)->type == FFI_TYPE_STRUCT)
-    {
-      argp = (char *) ALIGN (argp, 4);
-    }
-  return argp;
+  return (void *) ALIGN (p, alignment);
 }
 
 static size_t
@@ -148,7 +137,7 @@ ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space)
   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
        (i != 0); i--, p_arg++, p_argv++)
     {
-      argp = ffi_align (p_arg, argp);
+      argp = ffi_align (*p_arg, argp);
       argp += ffi_put_arg (p_arg, p_argv, argp);
     }
 
@@ -199,7 +188,7 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
       /* Try allocating in core registers. */
       else if (!done_with_regs && !is_vfp_type)
 	{
-	  char *tregp = ffi_align (p_arg, regp);
+	  char *tregp = ffi_align (*p_arg, regp);
 	  size_t size = (*p_arg)->size;
 	  size = (size < 4) ? 4 : size;	// pad
 	  /* Check if there is space left in the aligned register
@@ -226,7 +215,7 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
 	}
       /* Base case, arguments are passed on the stack */
       stack_used = 1;
-      argp = ffi_align (p_arg, argp);
+      argp = ffi_align (*p_arg, argp);
       argp += ffi_put_arg (p_arg, p_argv, argp);
     }
   /* Indicate the VFP registers used. */
@@ -440,7 +429,7 @@ ffi_prep_incoming_args_SYSV (char *stack, void **rvalue,
     {
       size_t z;
 
-      argp = ffi_align (p_arg, argp);
+      argp = ffi_align (*p_arg, argp);
 
       z = (*p_arg)->size;
 
@@ -495,7 +484,7 @@ ffi_prep_incoming_args_VFP (char *stack, void **rvalue,
 	}
       else if (!done_with_regs && !is_vfp_type)
 	{
-	  char *tregp = ffi_align (p_arg, regp);
+	  char *tregp = ffi_align (*p_arg, regp);
 
 	  z = (*p_arg)->size;
 	  z = (z < 4) ? 4 : z;	// pad
@@ -530,7 +519,7 @@ ffi_prep_incoming_args_VFP (char *stack, void **rvalue,
 	}
       stack_used = 1;
 
-      argp = ffi_align (p_arg, argp);
+      argp = ffi_align (*p_arg, argp);
 
       z = (*p_arg)->size;
 
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 04/10] arm: Rewrite vfp_type_p
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
  2014-10-29 20:06 ` [PATCH 07/10] arm: Remove internal FFI_TYPE constants Richard Henderson
  2014-10-29 20:06 ` [PATCH 03/10] arm: Deref ffi_put_arg arguments Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 05/10] arm: Rewrite ffi_call Richard Henderson
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

Do not modify the ffi_type.  Rearrange the tests so that we
quickly eliminate structures that cannot match.  Return an
encoded value of element count and base type.
---
 src/arm/ffi.c | 218 +++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 147 insertions(+), 71 deletions(-)

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index 5e5ad0a..d00ed89 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -34,7 +34,7 @@
 #include <stdlib.h>
 
 /* Forward declares. */
-static int vfp_type_p (ffi_type *);
+static int vfp_type_p (const ffi_type *);
 static void layout_vfp_args (ffi_cif *);
 
 int ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space);
@@ -141,7 +141,6 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
   register ffi_type **p_arg;
   char stack_used = 0;
   char done_with_regs = 0;
-  char is_vfp_type;
 
   /* Make sure we are using FFI_VFP.  */
   FFI_ASSERT (ecif->cif->abi == FFI_VFP);
@@ -164,7 +163,7 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
        (i != 0); i--, p_arg++, p_argv++)
     {
-      is_vfp_type = vfp_type_p (*p_arg);
+      int is_vfp_type = vfp_type_p (*p_arg);
 
       /* Allocated in VFP registers. */
       if (vi < ecif->cif->vfp_nargs && is_vfp_type)
@@ -214,7 +213,6 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
 ffi_status
 ffi_prep_cif_machdep (ffi_cif * cif)
 {
-  int type_code;
   /* Round the stack up to a multiple of 8 bytes.  This isn't needed
      everywhere, but it is on some platforms, and it doesn't harm anything
      when it isn't needed.  */
@@ -235,13 +233,25 @@ ffi_prep_cif_machdep (ffi_cif * cif)
       break;
 
     case FFI_TYPE_STRUCT:
-      if (cif->abi == FFI_VFP && (type_code = vfp_type_p (cif->rtype)) != 0)
+      if (cif->abi == FFI_VFP)
 	{
-	  /* A Composite Type passed in VFP registers, either
-	     FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
-	  cif->flags = (unsigned) type_code;
+	  int h = vfp_type_p (cif->rtype);
+	  if (h)
+	    {
+	      int ele_count = h >> 8;
+	      int type_code = h & 0xff;
+	      if (ele_count > 1)
+		{
+		  if (type_code == FFI_TYPE_FLOAT)
+		    type_code = FFI_TYPE_STRUCT_VFP_FLOAT;
+		  else
+		    type_code = FFI_TYPE_STRUCT_VFP_DOUBLE;
+		}
+	      cif->flags = type_code;
+	      break;
+	    }
 	}
-      else if (cif->rtype->size <= 4)
+      if (cif->rtype->size <= 4)
 	{
 	  /* A Composite Type not larger than 4 bytes is returned in r0.  */
 	  cif->flags = (unsigned) FFI_TYPE_INT;
@@ -446,7 +456,6 @@ ffi_prep_incoming_args_VFP (char *stack, void **rvalue,
   register ffi_type **p_arg;
   char done_with_regs = 0;
   char stack_used = 0;
-  char is_vfp_type;
 
   FFI_ASSERT (cif->abi == FFI_VFP);
   regp = stack;
@@ -462,8 +471,8 @@ ffi_prep_incoming_args_VFP (char *stack, void **rvalue,
 
   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
     {
+      int is_vfp_type = vfp_type_p (*p_arg);
       size_t z;
-      is_vfp_type = vfp_type_p (*p_arg);
 
       if (vi < cif->vfp_nargs && is_vfp_type)
 	{
@@ -820,81 +829,150 @@ ffi_prep_closure_loc (ffi_closure * closure,
 
 /* Below are routines for VFP hard-float support. */
 
+/* A subroutine of vfp_type_p.  Given a structure type, return the type code
+   of the first non-structure element.  Recurse for structure elements.
+   Return -1 if the structure is in fact empty, i.e. no nested elements.  */
+
 static int
-rec_vfp_type_p (ffi_type * t, int *elt, int *elnum)
+is_hfa0 (const ffi_type *ty)
 {
-  switch (t->type)
-    {
-    case FFI_TYPE_FLOAT:
-    case FFI_TYPE_DOUBLE:
-      *elt = (int) t->type;
-      *elnum = 1;
-      return 1;
+  ffi_type **elements = ty->elements;
+  int i, ret = -1;
 
-    case FFI_TYPE_STRUCT_VFP_FLOAT:
-      *elt = FFI_TYPE_FLOAT;
-      *elnum = t->size / sizeof (float);
-      return 1;
+  if (elements != NULL)
+    for (i = 0; elements[i]; ++i)
+      {
+        ret = elements[i]->type;
+        if (ret == FFI_TYPE_STRUCT)
+          {
+            ret = is_hfa0 (elements[i]);
+            if (ret < 0)
+              continue;
+          }
+        break;
+      }
 
-    case FFI_TYPE_STRUCT_VFP_DOUBLE:
-      *elt = FFI_TYPE_DOUBLE;
-      *elnum = t->size / sizeof (double);
-      return 1;
+  return ret;
+}
+
+/* A subroutine of vfp_type_p.  Given a structure type, return true if all
+   of the non-structure elements are the same as CANDIDATE.  */
+
+static int
+is_hfa1 (const ffi_type *ty, int candidate)
+{
+  ffi_type **elements = ty->elements;
+  int i;
 
-    case FFI_TYPE_STRUCT:;
+  if (elements != NULL)
+    for (i = 0; elements[i]; ++i)
       {
-	int base_elt = 0, total_elnum = 0;
-	ffi_type **el = t->elements;
-	while (*el)
-	  {
-	    int el_elt = 0, el_elnum = 0;
-	    if (!rec_vfp_type_p (*el, &el_elt, &el_elnum)
-		|| (base_elt && base_elt != el_elt)
-		|| total_elnum + el_elnum > 4)
-	      return 0;
-	    base_elt = el_elt;
-	    total_elnum += el_elnum;
-	    el++;
-	  }
-	*elnum = total_elnum;
-	*elt = base_elt;
-	return 1;
+        int t = elements[i]->type;
+        if (t == FFI_TYPE_STRUCT)
+          {
+            if (!is_hfa1 (elements[i], candidate))
+              return 0;
+          }
+        else if (t != candidate)
+          return 0;
       }
-    default:;
-    }
-  return 0;
+
+  return 1;
 }
 
+/* Determine if TY is an homogenous floating point aggregate (HFA).
+   That is, a structure consisting of 1 to 4 members of all the same type,
+   where that type is a floating point scalar.
+
+   Returns non-zero iff TY is an HFA.  The result is an encoded value where
+   bits 0-7 contain the type code, and bits 8-10 contain the element count.  */
+
 static int
-vfp_type_p (ffi_type * t)
+vfp_type_p (const ffi_type *ty)
 {
-  int elt, elnum;
-  if (rec_vfp_type_p (t, &elt, &elnum))
+  ffi_type **elements;
+  int candidate, i;
+  size_t size, ele_count;
+
+  /* Quickest tests first.  */
+  switch (ty->type)
     {
-      if (t->type == FFI_TYPE_STRUCT)
-	{
-	  if (elnum == 1)
-	    t->type = elt;
-	  else
-	    t->type = (elt == FFI_TYPE_FLOAT
-		       ? FFI_TYPE_STRUCT_VFP_FLOAT
-		       : FFI_TYPE_STRUCT_VFP_DOUBLE);
-	}
-      return (int) t->type;
+    default:
+      return 0;
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      return 0x100 + ty->type;
+    case FFI_TYPE_STRUCT:
+      break;
     }
-  return 0;
+
+  /* No HFA types are smaller than 4 bytes, or larger than 32 bytes.  */
+  size = ty->size;
+  if (size < 4 || size > 32)
+    return 0;
+
+  /* Find the type of the first non-structure member.  */
+  elements = ty->elements;
+  candidate = elements[0]->type;
+  if (candidate == FFI_TYPE_STRUCT)
+    {
+      for (i = 0; ; ++i)
+        {
+          candidate = is_hfa0 (elements[i]);
+          if (candidate >= 0)
+            break;
+        }
+    }
+
+  /* If the first member is not a floating point type, it's not an HFA.
+     Also quickly re-check the size of the structure.  */
+  switch (candidate)
+    {
+    case FFI_TYPE_FLOAT:
+      ele_count = size / sizeof(float);
+      if (size != ele_count * sizeof(float))
+        return 0;
+      break;
+    case FFI_TYPE_DOUBLE:
+      ele_count = size / sizeof(double);
+      if (size != ele_count * sizeof(double))
+        return 0;
+      break;
+    default:
+      return 0;
+    }
+  if (ele_count > 4)
+    return 0;
+
+  /* Finally, make sure that all scalar elements are the same type.  */
+  for (i = 0; elements[i]; ++i)
+    {
+      if (elements[i]->type == FFI_TYPE_STRUCT)
+        {
+          if (!is_hfa1 (elements[i], candidate))
+            return 0;
+        }
+      else if (elements[i]->type != candidate)
+        return 0;
+    }
+
+  /* All tests succeeded.  Encode the result.  */
+  return (ele_count << 8) | candidate;
 }
 
 static int
-place_vfp_arg (ffi_cif * cif, ffi_type * t)
+place_vfp_arg (ffi_cif *cif, int h)
 {
-  short reg = cif->vfp_reg_free;
-  int nregs = t->size / sizeof (float);
-  int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT
-		|| t->type == FFI_TYPE_FLOAT) ? 1 : 2);
+  unsigned short reg = cif->vfp_reg_free;
+  int align = 1, nregs = h >> 8;
+
+  if ((h & 0xff) == FFI_TYPE_DOUBLE)
+    align = 2, nregs *= 2;
+
   /* Align register number. */
   if ((reg & 1) && align == 2)
     reg++;
+
   while (reg + nregs <= 16)
     {
       int s, new_used = 0;
@@ -940,10 +1018,8 @@ layout_vfp_args (ffi_cif * cif)
 
   for (i = 0; i < cif->nargs; i++)
     {
-      ffi_type *t = cif->arg_types[i];
-      if (vfp_type_p (t) && place_vfp_arg (cif, t) == 1)
-	{
-	  break;
-	}
+      int h = vfp_type_p (cif->arg_types[i]);
+      if (h && place_vfp_arg (cif, h) == 1)
+	break;
     }
 }
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 05/10] arm: Rewrite ffi_call
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
                   ` (2 preceding siblings ...)
  2014-10-29 20:06 ` [PATCH 04/10] arm: Rewrite vfp_type_p Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 08/10] arm: Add support for complex types Richard Henderson
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

Use the trick to allocate the stack frame for ffi_call_SYSV
within ffi_call itself.
---
 src/arm/ffi.c       | 285 ++++++++++++++++++----------------
 src/arm/ffitarget.h |   2 +-
 src/arm/internal.h  |   7 +
 src/arm/sysv.S      | 440 ++++++++++++++++------------------------------------
 4 files changed, 294 insertions(+), 440 deletions(-)
 create mode 100644 src/arm/internal.h

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index d00ed89..c91b869 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -30,16 +30,13 @@
 
 #include <ffi.h>
 #include <ffi_common.h>
-
 #include <stdlib.h>
+#include "internal.h"
 
 /* Forward declares. */
 static int vfp_type_p (const ffi_type *);
 static void layout_vfp_args (ffi_cif *);
 
-int ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space);
-int ffi_prep_args_VFP (char *stack, extended_cif *ecif, float *vfp_space);
-
 static void *
 ffi_align (ffi_type *ty, void *p)
 {
@@ -98,53 +95,44 @@ ffi_put_arg (ffi_type *ty, void *src, void *dst)
   return ALIGN (z, 4);
 }
 
-/* ffi_prep_args is called by the assembly routine once stack space
-   has been allocated for the function's arguments
+/* ffi_prep_args is called once stack space has been allocated
+   for the function's arguments.
 
    The vfp_space parameter is the load area for VFP regs, the return
    value is cif->vfp_used (word bitset of VFP regs used for passing
    arguments). These are only used for the VFP hard-float ABI.
 */
-int
-ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space)
+static void
+ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
+		    void **avalue, char *argp)
 {
-  register unsigned int i;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-  argp = stack;
+  ffi_type **arg_types = cif->arg_types;
+  int i, n;
 
-  if (ecif->cif->flags == FFI_TYPE_STRUCT)
+  if (flags == ARM_TYPE_STRUCT)
     {
-      *(void **) argp = ecif->rvalue;
+      *(void **) argp = rvalue;
       argp += 4;
     }
 
-  p_argv = ecif->avalue;
-
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       (i != 0); i--, p_arg++, p_argv++)
+  for (i = 0, n = cif->nargs; i < n; i++)
     {
-      argp = ffi_align (*p_arg, argp);
-      argp += ffi_put_arg (*p_arg, *p_argv, argp);
+      ffi_type *ty = arg_types[i];
+      argp = ffi_align (ty, argp);
+      argp += ffi_put_arg (ty, avalue[i], argp);
     }
-
-  return 0;
 }
 
-int
-ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
+static void
+ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
+                   void **avalue, char *stack, char *vfp_space)
 {
-  register unsigned int i, vi = 0;
-  register void **p_argv;
-  register char *argp, *regp, *eo_regp;
-  register ffi_type **p_arg;
+  ffi_type **arg_types = cif->arg_types;
+  int i, n, vi = 0;
+  char *argp, *regp, *eo_regp;
   char stack_used = 0;
   char done_with_regs = 0;
 
-  /* Make sure we are using FFI_VFP.  */
-  FFI_ASSERT (ecif->cif->abi == FFI_VFP);
-
   /* The first 4 words on the stack are used for values
      passed in core registers.  */
   regp = stack;
@@ -152,37 +140,36 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
 
   /* If the function returns an FFI_TYPE_STRUCT in memory,
      that address is passed in r0 to the function.  */
-  if (ecif->cif->flags == FFI_TYPE_STRUCT)
+  if (flags == ARM_TYPE_STRUCT)
     {
-      *(void **) regp = ecif->rvalue;
+      *(void **) regp = rvalue;
       regp += 4;
     }
 
-  p_argv = ecif->avalue;
-
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       (i != 0); i--, p_arg++, p_argv++)
+  for (i = 0, n = cif->nargs; i < n; i++)
     {
-      int is_vfp_type = vfp_type_p (*p_arg);
+      ffi_type *ty = arg_types[i];
+      void *a = avalue[i];
+      int is_vfp_type = vfp_type_p (ty);
 
       /* Allocated in VFP registers. */
-      if (vi < ecif->cif->vfp_nargs && is_vfp_type)
+      if (vi < cif->vfp_nargs && is_vfp_type)
 	{
-	  char *vfp_slot = (char *) (vfp_space + ecif->cif->vfp_args[vi++]);
-	  ffi_put_arg (*p_arg, *p_argv, vfp_slot);
+	  char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4;
+	  ffi_put_arg (ty, a, vfp_slot);
 	  continue;
 	}
       /* Try allocating in core registers. */
       else if (!done_with_regs && !is_vfp_type)
 	{
-	  char *tregp = ffi_align (*p_arg, regp);
-	  size_t size = (*p_arg)->size;
+	  char *tregp = ffi_align (ty, regp);
+	  size_t size = ty->size;
 	  size = (size < 4) ? 4 : size;	// pad
 	  /* Check if there is space left in the aligned register
 	     area to place the argument.  */
 	  if (tregp + size <= eo_regp)
 	    {
-	      regp = tregp + ffi_put_arg (*p_arg, *p_argv, tregp);
+	      regp = tregp + ffi_put_arg (ty, a, tregp);
 	      done_with_regs = (regp == argp);
 	      // ensure we did not write into the stack area
 	      FFI_ASSERT (regp <= argp);
@@ -195,87 +182,97 @@ ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
 	    {
 	      stack_used = 1;
 	      done_with_regs = 1;
-	      argp = tregp + ffi_put_arg (*p_arg, *p_argv, tregp);
+	      argp = tregp + ffi_put_arg (ty, a, tregp);
 	      FFI_ASSERT (eo_regp < argp);
 	      continue;
 	    }
 	}
       /* Base case, arguments are passed on the stack */
       stack_used = 1;
-      argp = ffi_align (*p_arg, argp);
-      argp += ffi_put_arg (*p_arg, *p_argv, argp);
+      argp = ffi_align (ty, argp);
+      argp += ffi_put_arg (ty, a, argp);
     }
-  /* Indicate the VFP registers used. */
-  return ecif->cif->vfp_used;
 }
 
 /* Perform machine dependent cif processing */
 ffi_status
-ffi_prep_cif_machdep (ffi_cif * cif)
+ffi_prep_cif_machdep (ffi_cif *cif)
 {
+  int flags = 0, cabi = cif->abi;
+  size_t bytes;
+
   /* Round the stack up to a multiple of 8 bytes.  This isn't needed
      everywhere, but it is on some platforms, and it doesn't harm anything
      when it isn't needed.  */
-  cif->bytes = (cif->bytes + 7) & ~7;
+  bytes = ALIGN (cif->bytes, 8);
+
+  /* Minimum stack space is the 4 register arguments that we pop.  */
+  if (bytes < 4*4)
+    bytes = 4*4;
+  cif->bytes = bytes;
+
+  /* Map out the register placements of VFP register args.  The VFP
+     hard-float calling conventions are slightly more sophisticated
+     than the base calling conventions, so we do it here instead of
+     in ffi_prep_args(). */
+  if (cabi == FFI_VFP)
+    layout_vfp_args (cif);
 
   /* Set the return type flag */
   switch (cif->rtype->type)
     {
     case FFI_TYPE_VOID:
-    case FFI_TYPE_FLOAT:
-    case FFI_TYPE_DOUBLE:
-      cif->flags = (unsigned) cif->rtype->type;
+      flags = ARM_TYPE_VOID;
+      break;
+
+    case FFI_TYPE_INT:
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_POINTER:
+      flags = ARM_TYPE_INT;
       break;
 
     case FFI_TYPE_SINT64:
     case FFI_TYPE_UINT64:
-      cif->flags = (unsigned) FFI_TYPE_SINT64;
+      flags = ARM_TYPE_INT64;
+      break;
+
+    case FFI_TYPE_FLOAT:
+      flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT);
+      break;
+    case FFI_TYPE_DOUBLE:
+      flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64);
       break;
 
     case FFI_TYPE_STRUCT:
-      if (cif->abi == FFI_VFP)
+      if (cabi == FFI_VFP)
 	{
 	  int h = vfp_type_p (cif->rtype);
-	  if (h)
-	    {
-	      int ele_count = h >> 8;
-	      int type_code = h & 0xff;
-	      if (ele_count > 1)
-		{
-		  if (type_code == FFI_TYPE_FLOAT)
-		    type_code = FFI_TYPE_STRUCT_VFP_FLOAT;
-		  else
-		    type_code = FFI_TYPE_STRUCT_VFP_DOUBLE;
-		}
-	      cif->flags = type_code;
+
+	  flags = ARM_TYPE_VFP_N;
+	  if (h == 0x100 + FFI_TYPE_FLOAT)
+	    flags = ARM_TYPE_VFP_S;
+	  if (h == 0x100 + FFI_TYPE_DOUBLE)
+	    flags = ARM_TYPE_VFP_D;
+	  if (h != 0)
 	      break;
-	    }
-	}
-      if (cif->rtype->size <= 4)
-	{
-	  /* A Composite Type not larger than 4 bytes is returned in r0.  */
-	  cif->flags = (unsigned) FFI_TYPE_INT;
-	}
-      else
-	{
-	  /* A Composite Type larger than 4 bytes, or whose size cannot
-	     be determined statically ... is stored in memory at an
-	     address passed [in r0].  */
-	  cif->flags = (unsigned) FFI_TYPE_STRUCT;
 	}
+
+      /* A Composite Type not larger than 4 bytes is returned in r0.
+	 A Composite Type larger than 4 bytes, or whose size cannot
+	 be determined statically ... is stored in memory at an
+	 address passed [in r0].  */
+      flags = (cif->rtype->size <= 4 ? ARM_TYPE_INT : ARM_TYPE_STRUCT);
       break;
 
     default:
-      cif->flags = FFI_TYPE_INT;
-      break;
+      abort();
     }
-
-  /* Map out the register placements of VFP register args.  The VFP
-     hard-float calling conventions are slightly more sophisticated
-     than the base calling conventions, so we do it here instead of
-     in ffi_prep_args(). */
-  if (cif->abi == FFI_VFP)
-    layout_vfp_args (cif);
+  cif->flags = flags;
 
   return FFI_OK;
 }
@@ -293,69 +290,83 @@ ffi_prep_cif_machdep_var (ffi_cif * 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 *);
 
-void
-ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
+struct call_frame
 {
-  extended_cif ecif;
-
-  int small_struct = (cif->flags == FFI_TYPE_INT
-		      && cif->rtype->type == FFI_TYPE_STRUCT);
-  int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
-		    || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
-
-  unsigned int temp;
-
-  ecif.cif = cif;
-  ecif.avalue = avalue;
+  void *fp;
+  void *lr;
+  void *rvalue;
+  int flags;
+};
 
-  /* If the return value is a struct and we don't have a return
-     value address then we need to make one.  */
+extern void ffi_call_SYSV (void *stack, struct call_frame *,
+			   void (*fn) (void)) FFI_HIDDEN;
+extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
+			   void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
 
-  if ((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT))
+void
+ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
+{
+  int flags = cif->flags;
+  ffi_type *rtype = cif->rtype;
+  size_t bytes, rsize, vfp_size;
+  char *stack, *vfp_space, *new_rvalue;
+  struct call_frame *frame;
+
+  rsize = 0;
+  if (rvalue == NULL)
     {
-      ecif.rvalue = alloca (cif->rtype->size);
+      /* If the return value is a struct and we don't have a return
+	 value address then we need to make one.  Otherwise the return
+	 value is in registers and we can ignore them.  */
+      if (flags == ARM_TYPE_STRUCT)
+	rsize = rtype->size;
+      else
+	flags = ARM_TYPE_VOID;
     }
-  else if (small_struct)
-    ecif.rvalue = &temp;
-  else if (vfp_struct)
+  else if (flags == ARM_TYPE_VFP_N)
     {
       /* Largest case is double x 4. */
-      ecif.rvalue = alloca (32);
+      rsize = 32;
     }
-  else
-    ecif.rvalue = rvalue;
+  else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
+    rsize = 4;
 
-  switch (cif->abi)
-    {
-    case FFI_SYSV:
-      ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
-      break;
+  /* Largest case.  */
+  vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);
 
-    case FFI_VFP:
-#ifdef __ARM_EABI__
-      ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
-      break;
-#endif
+  bytes = cif->bytes;
+  stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
 
-    default:
-      FFI_ASSERT (0);
-      break;
+  vfp_space = NULL;
+  if (vfp_size)
+    {
+      vfp_space = stack;
+      stack += vfp_size;
     }
-  if (small_struct)
+
+  frame = (struct call_frame *)(stack + bytes);
+
+  new_rvalue = rvalue;
+  if (rsize)
+    new_rvalue = (void *)(frame + 1);
+
+  frame->rvalue = new_rvalue;
+  frame->flags = flags;
+
+  if (vfp_space)
     {
-      FFI_ASSERT (rvalue != NULL);
-      memcpy (rvalue, &temp, cif->rtype->size);
+      ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
+      ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
     }
-  else if (vfp_struct)
+  else
     {
-      FFI_ASSERT (rvalue != NULL);
-      memcpy (rvalue, ecif.rvalue, cif->rtype->size);
+      ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
+      ffi_call_SYSV (stack, frame, fn);
     }
+ 
+  if (rvalue && rvalue != new_rvalue)
+    memcpy (rvalue, new_rvalue, rtype->size);
 }
 
 /** private members **/
diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h
index 26d494d..6355904 100644
--- a/src/arm/ffitarget.h
+++ b/src/arm/ffitarget.h
@@ -53,7 +53,7 @@ typedef enum ffi_abi {
 
 #define FFI_EXTRA_CIF_FIELDS			\
   int vfp_used;					\
-  short vfp_reg_free, vfp_nargs;		\
+  unsigned short vfp_reg_free, vfp_nargs;	\
   signed char vfp_args[16]			\
 
 /* Internally used. */
diff --git a/src/arm/internal.h b/src/arm/internal.h
new file mode 100644
index 0000000..6cf0b2a
--- /dev/null
+++ b/src/arm/internal.h
@@ -0,0 +1,7 @@
+#define ARM_TYPE_VFP_S	0
+#define ARM_TYPE_VFP_D	1
+#define ARM_TYPE_VFP_N	2
+#define ARM_TYPE_INT64	3
+#define ARM_TYPE_INT	4
+#define ARM_TYPE_VOID	5
+#define ARM_TYPE_STRUCT	6
diff --git a/src/arm/sysv.S b/src/arm/sysv.S
index 541bbe9..b967d97 100644
--- a/src/arm/sysv.S
+++ b/src/arm/sysv.S
@@ -1,8 +1,8 @@
 /* -----------------------------------------------------------------------
    sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
 	    Copyright (c) 2011 Plausible Labs Cooperative, Inc.
-   
-   ARM Foreign Function Interface 
+
+   ARM Foreign Function Interface
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -28,219 +28,155 @@
 #define LIBFFI_ASM	
 #include <fficonfig.h>
 #include <ffi.h>
-#ifdef HAVE_MACHINE_ASM_H
-#include <machine/asm.h>
-#else
-#ifdef __USER_LABEL_PREFIX__
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
-
-/* Use the right prefix for global labels.  */
-#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-#else
-#define CNAME(x) x
-#endif
-#ifdef __APPLE__
-#define ENTRY(x) .globl _##x; _##x:
-#else
-#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
-#endif /* __APPLE__ */
-#endif
-
-#ifdef __ELF__
-#define LSYM(x) .x
-#else
-#define LSYM(x) x
-#endif
-
-/* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
-  Function Call Guide */
-#ifdef __APPLE__
-#define __SOFTFP__
-#endif
-
-/* We need a better way of testing for this, but for now, this is all 
-   we can do.  */
-@ This selects the minimum architecture level required.
-#define __ARM_ARCH__ 3
-
-#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 4
-#endif
-        
-#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
-	|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
-	|| defined(__ARM_ARCH_5TEJ__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 5
-#endif
-
-#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+#include <ffi_cfi.h>
+#include "internal.h"
+
+/* GCC 4.8 provides __ARM_ARCH; construct it otherwise.  */
+#ifndef __ARM_ARCH
+# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+     || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+     || defined(__ARM_ARCH_7EM__)
+#  define __ARM_ARCH 7
+# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
         || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
         || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
 	|| defined(__ARM_ARCH_6M__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 6
-#endif
-
-#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
-        || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
-	|| defined(__ARM_ARCH_7EM__)
-# undef __ARM_ARCH__
-# define __ARM_ARCH__ 7
-#endif
-
-#if __ARM_ARCH__ >= 5
-# define call_reg(x)	blx	x
-#elif defined (__ARM_ARCH_4T__)
-# define call_reg(x)	mov	lr, pc ; bx	x
-# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
-#  define __INTERWORKING__
+#  define __ARM_ARCH 6
+# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+	|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+	|| defined(__ARM_ARCH_5TEJ__)
+#  define __ARM_ARCH 5
+# else
+#  define __ARM_ARCH 4
 # endif
-#else
-# define call_reg(x)	mov	lr, pc ; mov	pc, x
 #endif
 
 /* Conditionally compile unwinder directives.  */
+.macro UNWIND text:vararg
 #ifdef __ARM_EABI__
-#define UNWIND
-#else
-#define UNWIND @
+	\text
 #endif	
+.endm
+#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
+	.cfi_sections	.debug_frame
+#endif
 
-.syntax unified
-
-#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
-#define ARM_FUNC_START(name) \
-	.text; \
-	.align 2; \
-	.thumb; \
-	.thumb_func; \
-	ENTRY(name); \
-	bx pc; \
-	nop; \
-	.arm; \
-	UNWIND .fnstart; \
-_L__##name:
+#define CONCAT(a, b)	CONCAT2(a, b)
+#define CONCAT2(a, b)	a ## b
+
+#ifdef __USER_LABEL_PREFIX__
+# define CNAME(X)	CONCAT (__USER_LABEL_PREFIX__, X)
 #else
-#define ARM_FUNC_START(name) \
-	.text; \
-	.align 2; \
-	.arm; \
-	ENTRY(name); \
-	UNWIND .fnstart
+# define CNAME(X)	X
 #endif
-
-.macro	RETLDM	regs=, cond=, dirn=ia
-#if defined (__INTERWORKING__)
-	.ifc "\regs",""
-	ldr\cond	lr, [sp], #4
-	.else
-	ldm\cond\dirn	sp!, {\regs, lr}
-	.endif
-	bx\cond	lr
+#ifdef __ELF__
+# define SIZE(X)	.size CNAME(X), . - CNAME(X)
+# define TYPE(X, Y)	.type CNAME(X), Y
 #else
-	.ifc "\regs",""
-	ldr\cond	pc, [sp], #4
-	.else
-	ldm\cond\dirn	sp!, {\regs, pc}
-	.endif
+# define SIZE(X)
+# define TYPE(X, Y)
 #endif
-.endm
-
-	@ r0:   ffi_prep_args
-	@ r1:   &ecif
-	@ r2:   cif->bytes
-	@ r3:   fig->flags
-	@ sp+0: ecif.rvalue
-
-	@ This assumes we are using gas.
-ARM_FUNC_START(ffi_call_SYSV)
-	@ Save registers
-        stmfd	sp!, {r0-r3, fp, lr}
-	UNWIND .save	{r0-r3, fp, lr}
-	mov	fp, sp
-
-	UNWIND .setfp	fp, sp
-
-	@ Make room for all of the new args.
-	sub	sp, fp, r2
-
-	@ Place all of the ffi_prep_args in position
-	mov	r0, sp
-	@     r1 already set
 
-	@ Call ffi_prep_args(stack, &ecif)
-	bl	CNAME(ffi_prep_args_SYSV)
+#define ARM_FUNC_START(name, gl) \
+	.align	3; \
+	.ifne gl; .globl CNAME(name); FFI_HIDDEN(CNAME(name)); .endif; \
+	TYPE(name, %function); \
+	CNAME(name):
 
-	@ move first 4 parameters in registers
-	ldmia	sp, {r0-r3}
+#define ARM_FUNC_END(name) \
+	SIZE(name)
 
-	@ and adjust stack
-	sub	lr, fp, sp	@ cif->bytes == fp - sp
-	ldr	ip, [fp]	@ load fn() in advance
-	cmp	lr, #16
-	movhs	lr, #16
-	add	sp, sp, lr
+/* Aid in defining a jump table with 8 bytes between entries.  */
+.macro E index
+	.if . - 0b - 8*\index
+	.error "type table out of sync"
+	.endif
+.endm
 
-	@ call (fn) (...)
-	call_reg(ip)
-	
-	@ Remove the space we pushed for the args
-	mov	sp, fp
+	.text
+	.syntax unified
+	.arm
+
+	/* We require interworking on LDM, which implies ARMv5T,
+	   which implies the existance of BLX.  */
+	.arch	armv5t
+
+	/* Note that we use STC and LDC to encode VFP instructions,
+	   so that we do not need ".fpu vfp", nor get that added to
+	   the object file attributes.  These will not be executed
+	   unless the FFI_VFP abi is used.  */
+
+	@ r0:   stack
+	@ r1:   frame
+	@ r2:   fn
+	@ r3:	vfp_used
+
+ARM_FUNC_START(ffi_call_VFP, 1)
+	UNWIND	.fnstart
+	cfi_startproc
+
+	cmp	r3, #3			@ load only d0 if possible
+	ldcle	p11, cr0, [r0]		@ vldrle d0, [sp]
+	ldcgt	p11, cr0, [r0], {16}	@ vldmgt sp, {d0-d7}
+	add	r0, r0, #64		@ discard the vfp register args
+	/* FALLTHRU */
+ARM_FUNC_END(ffi_call_VFP)
+
+ARM_FUNC_START(ffi_call_SYSV, 1)
+	stm	r1, {fp, lr}
+	mov	fp, r1
+
+	@ This is a bit of a lie wrt the origin of the unwind info, but
+	@ now we've got the usual frame pointer and two saved registers.
+	UNWIND	.save {fp,lr}
+	UNWIND	.setfp fp, sp
+	cfi_def_cfa(fp, 8)
+	cfi_rel_offset(fp, 0)
+	cfi_rel_offset(lr, 4)
+
+	mov	sp, r0		@ install the stack pointer
+	mov	lr, r2		@ move the fn pointer out of the way
+	ldmia	sp!, {r0-r3}	@ move first 4 parameters in registers.
+	blx	lr		@ call fn
 
 	@ Load r2 with the pointer to storage for the return value
-	ldr	r2, [sp, #24]
-
-	@ Load r3 with the return type code 
-	ldr	r3, [sp, #12]
-
-	@ If the return value pointer is NULL, assume no return value.
-	cmp	r2, #0
-	beq	LSYM(Lepilogue)
+	@ Load r3 with the return type code
+	ldr	r2, [fp, #8]
+	ldr	r3, [fp, #12]
 
-@ return INT
-	cmp	r3, #FFI_TYPE_INT
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	cmpne	r3, #FFI_TYPE_FLOAT
-#endif
-	streq	r0, [r2]
-	beq	LSYM(Lepilogue)
-
-	@ return INT64
-	cmp	r3, #FFI_TYPE_SINT64
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	cmpne	r3, #FFI_TYPE_DOUBLE
-#endif
-	stmiaeq	r2, {r0, r1}
-
-#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
-	beq	LSYM(Lepilogue)
-
-@ return FLOAT
-	cmp	r3, #FFI_TYPE_FLOAT
-	stfeqs	f0, [r2]
-	beq	LSYM(Lepilogue)
-
-@ return DOUBLE or LONGDOUBLE
-	cmp	r3, #FFI_TYPE_DOUBLE
-	stfeqd	f0, [r2]
-#endif
-
-LSYM(Lepilogue):
-#if defined (__INTERWORKING__)
-	ldmia   sp!, {r0-r3,fp, lr}
-	bx	lr
-#else
-	ldmia   sp!, {r0-r3,fp, pc}
-#endif
-
-.ffi_call_SYSV_end:
-	UNWIND .fnend
-#ifdef __ELF__
-        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
-#endif
+	@ Deallocate the stack with the arguments.
+	mov	sp, fp
+	cfi_def_cfa_register(sp)
+
+	@ Store values stored in registers.
+	.align	3
+	add	pc, pc, r3, lsl #3
+	nop
+0:
+E ARM_TYPE_VFP_S
+	stc	p10, cr0, [r2]		@ vstr s0, [r2]
+	pop	{fp,pc}
+E ARM_TYPE_VFP_D
+	stc	p11, cr0, [r2]		@ vstr d0, [r2]
+	pop	{fp,pc}
+E ARM_TYPE_VFP_N
+	stc	p11, cr0, [r2], {8}	@ vstm r2, {d0-d3}
+	pop	{fp,pc}
+E ARM_TYPE_INT64
+	str	r1, [r2, #4]
+	nop
+E ARM_TYPE_INT
+	str	r0, [r2]
+	pop	{fp,pc}
+E ARM_TYPE_VOID
+	pop	{fp,pc}
+	nop
+E ARM_TYPE_STRUCT
+	pop	{fp,pc}
+
+	cfi_endproc
+	UNWIND	.fnend
+ARM_FUNC_END(ffi_call_SYSV)
 
 
 /*
@@ -251,7 +187,8 @@ LSYM(Lepilogue):
   	     void *args;
 */
 
-ARM_FUNC_START(ffi_closure_SYSV)
+ARM_FUNC_START(ffi_closure_SYSV, 1)
+	UNWIND	.fnstart
 	UNWIND .pad #16
 	add	ip, sp, #16
 	stmfd	sp!, {ip, lr}
@@ -310,116 +247,16 @@ ARM_FUNC_START(ffi_closure_SYSV)
 	ldfd	f0, [sp]
 	b	.Lclosure_epilogue
 #endif
-
-.ffi_closure_SYSV_end:
 	UNWIND .fnend
-#ifdef __ELF__
-        .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
-#endif
+ARM_FUNC_END(ffi_closure_SYSV)
 
 
 /* Below are VFP hard-float ABI call and closure implementations.
    Add VFP FPU directive here. This is only compiled into the library
    under EABI.  */
 #ifdef __ARM_EABI__
-	.fpu	vfp
-
-	@ r0:   fn
-	@ r1:   &ecif
-	@ r2:   cif->bytes
-	@ r3:   fig->flags
-	@ sp+0: ecif.rvalue
-
-ARM_FUNC_START(ffi_call_VFP)
-	@ Save registers
-        stmfd	sp!, {r0-r3, fp, lr}
-	UNWIND .save	{r0-r3, fp, lr}
-	mov	fp, sp
-	UNWIND .setfp	fp, sp
-
-	@ Make room for all of the new args.
-	sub	sp, sp, r2
-
-	@ Make room for loading VFP args
-	sub	sp, sp, #64
-
-	@ Place all of the ffi_prep_args in position
-	mov	r0, sp
-	@     r1 already set
-	sub	r2, fp, #64   @ VFP scratch space
-
-	@ Call ffi_prep_args(stack, &ecif, vfp_space)
-	bl	CNAME(ffi_prep_args_VFP)
-
-	@ Load VFP register args if needed
-	cmp	r0, #0
-	mov	ip, fp
-	beq	LSYM(Lbase_args)
-
-	@ Load only d0 if possible
-	cmp	r0, #3
-	sub	ip, fp, #64
-	flddle	d0, [ip]
-	fldmiadgt	ip, {d0-d7}
-
-LSYM(Lbase_args):
-	@ move first 4 parameters in registers
-	ldmia	sp, {r0-r3}
-
-	@ and adjust stack
-	sub	lr, ip, sp	@ cif->bytes == (fp - 64) - sp
-	ldr	ip, [fp]	@ load fn() in advance
-        cmp	lr, #16
-	movhs	lr, #16
-        add	sp, sp, lr
-
-	@ call (fn) (...)
-	call_reg(ip)
-
-	@ Remove the space we pushed for the args
-	mov	sp, fp
-
-	@ Load r2 with the pointer to storage for
-	@ the return value
-	ldr	r2, [sp, #24]
-
-	@ Load r3 with the return type code 
-	ldr	r3, [sp, #12]
-
-	@ If the return value pointer is NULL,
-	@ assume no return value.
-	cmp	r2, #0
-	beq	LSYM(Lepilogue_vfp)
-
-	cmp	r3, #FFI_TYPE_INT
-	streq	r0, [r2]
-	beq	LSYM(Lepilogue_vfp)
-
-	cmp	r3, #FFI_TYPE_SINT64
-	stmeqia	r2, {r0, r1}
-	beq	LSYM(Lepilogue_vfp)
-
-	cmp	r3, #FFI_TYPE_FLOAT
-	fstseq	s0, [r2]
-	beq	LSYM(Lepilogue_vfp)
-	
-	cmp	r3, #FFI_TYPE_DOUBLE
-	fstdeq	d0, [r2]
-	beq	LSYM(Lepilogue_vfp)
-
-	cmp	r3, #FFI_TYPE_STRUCT_VFP_FLOAT
-	cmpne	r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
-	fstmiadeq	r2, {d0-d3}
-
-LSYM(Lepilogue_vfp):
-	RETLDM	"r0-r3,fp"
-
-.ffi_call_VFP_end:
-	UNWIND .fnend
-        .size    CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
-
-
-ARM_FUNC_START(ffi_closure_VFP)
+ARM_FUNC_START(ffi_closure_VFP, 1)
+	UNWIND	.fnstart
 	fstmfdd	sp!, {d0-d7}
 	@ r0-r3, then d0-d7
 	UNWIND .pad #80
@@ -475,16 +312,15 @@ ARM_FUNC_START(ffi_closure_VFP)
 .Lretdouble_struct_vfp:
 	fldmiad	sp, {d0-d3}
 	b	.Lclosure_epilogue_vfp
-
-.ffi_closure_VFP_end:
 	UNWIND .fnend
-        .size    CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
+ARM_FUNC_END(ffi_closure_VFP)
 #endif
 
-ENTRY(ffi_arm_trampoline)
+ARM_FUNC_START(ffi_arm_trampoline, 1)
 	stmfd sp!, {r0-r3}
 	ldr r0, [pc]
 	ldr pc, [pc]
+ARM_FUNC_END(ffi_arm_trampoline)
 
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",%progbits
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 08/10] arm: Add support for complex types
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
                   ` (3 preceding siblings ...)
  2014-10-29 20:06 ` [PATCH 05/10] arm: Rewrite ffi_call Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 02/10] arm: Deref ffi_align argument Richard Henderson
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

---
 src/arm/ffi.c                  | 28 +++++++++++++++++++++-------
 src/arm/ffitarget.h            |  1 +
 testsuite/libffi.call/call.exp | 10 +++-------
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index 395af97..9a11e8f 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -87,9 +87,12 @@ ffi_put_arg (ffi_type *ty, void *src, void *dst)
       break;
 
     case FFI_TYPE_STRUCT:
-    default:
+    case FFI_TYPE_COMPLEX:
       memcpy (dst, src, z);
       break;
+
+    default:
+      abort();
     }
 
   return ALIGN (z, 4);
@@ -249,6 +252,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
       break;
 
     case FFI_TYPE_STRUCT:
+    case FFI_TYPE_COMPLEX:
       if (cabi == FFI_VFP)
 	{
 	  int h = vfp_type_p (cif->rtype);
@@ -790,7 +794,7 @@ is_hfa0 (const ffi_type *ty)
     for (i = 0; elements[i]; ++i)
       {
         ret = elements[i]->type;
-        if (ret == FFI_TYPE_STRUCT)
+        if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
           {
             ret = is_hfa0 (elements[i]);
             if (ret < 0)
@@ -815,7 +819,7 @@ is_hfa1 (const ffi_type *ty, int candidate)
     for (i = 0; elements[i]; ++i)
       {
         int t = elements[i]->type;
-        if (t == FFI_TYPE_STRUCT)
+        if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
           {
             if (!is_hfa1 (elements[i], candidate))
               return 0;
@@ -842,13 +846,21 @@ vfp_type_p (const ffi_type *ty)
   size_t size, ele_count;
 
   /* Quickest tests first.  */
+  candidate = ty->type;
   switch (ty->type)
     {
     default:
       return 0;
     case FFI_TYPE_FLOAT:
     case FFI_TYPE_DOUBLE:
-      return 0x100 + ty->type;
+      ele_count = 1;
+      goto done;
+    case FFI_TYPE_COMPLEX:
+      candidate = ty->elements[0]->type;
+      if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE)
+	return 0;
+      ele_count = 2;
+      goto done;
     case FFI_TYPE_STRUCT:
       break;
     }
@@ -861,7 +873,7 @@ vfp_type_p (const ffi_type *ty)
   /* Find the type of the first non-structure member.  */
   elements = ty->elements;
   candidate = elements[0]->type;
-  if (candidate == FFI_TYPE_STRUCT)
+  if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
     {
       for (i = 0; ; ++i)
         {
@@ -894,16 +906,18 @@ vfp_type_p (const ffi_type *ty)
   /* Finally, make sure that all scalar elements are the same type.  */
   for (i = 0; elements[i]; ++i)
     {
-      if (elements[i]->type == FFI_TYPE_STRUCT)
+      int t = elements[i]->type;
+      if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
         {
           if (!is_hfa1 (elements[i], candidate))
             return 0;
         }
-      else if (elements[i]->type != candidate)
+      else if (t != candidate)
         return 0;
     }
 
   /* All tests succeeded.  Encode the result.  */
+ done:
   return (ele_count << 8) | candidate;
 }
 
diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h
index bf36750..744a1e1 100644
--- a/src/arm/ffitarget.h
+++ b/src/arm/ffitarget.h
@@ -57,6 +57,7 @@ typedef enum ffi_abi {
   signed char vfp_args[16]			\
 
 #define FFI_TARGET_SPECIFIC_VARIADIC
+#define FFI_TARGET_HAS_COMPLEX_TYPE
 
 /* ---- Definitions for closures ----------------------------------------- */
 
diff --git a/testsuite/libffi.call/call.exp b/testsuite/libffi.call/call.exp
index 5177f07..5864fc0 100644
--- a/testsuite/libffi.call/call.exp
+++ b/testsuite/libffi.call/call.exp
@@ -24,16 +24,12 @@ set ctlist [lsearch -inline -all -glob [lsort [glob -nocomplain -- $srcdir/$subd
 
 run-many-tests $tlist ""
 
-if { ![istarget s390*] } {
-
+if { [istarget s390*] || [istarget arm*] } {
+    run-many-tests $ctlist ""
+} else {
     foreach test $ctlist {
 	unsupported "$test"
     }
-
-} else {
-
-  run-many-tests $ctlist ""
-
 }
 
 dg-finish
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 10/10] arm: Add support for Go closures
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
                   ` (5 preceding siblings ...)
  2014-10-29 20:06 ` [PATCH 02/10] arm: Deref ffi_align argument Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 01/10] arm: Reindent arm/ffi.c Richard Henderson
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

---
 src/arm/ffi.c       | 76 ++++++++++++++++++++++++++++++++++++++++++++---------
 src/arm/ffitarget.h |  1 +
 src/arm/sysv.S      | 63 ++++++++++++++++++++++++++++----------------
 3 files changed, 105 insertions(+), 35 deletions(-)

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index eabab47..9c8732d 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -308,6 +308,7 @@ struct call_frame
   void *lr;
   void *rvalue;
   int flags;
+  void *closure;
 };
 
 extern void ffi_call_SYSV (void *stack, struct call_frame *,
@@ -315,8 +316,9 @@ extern void ffi_call_SYSV (void *stack, struct call_frame *,
 extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
 			   void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
 
-void
-ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
+static void
+ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
+	      void **avalue, void *closure)
 {
   int flags = cif->flags;
   ffi_type *rtype = cif->rtype;
@@ -364,6 +366,7 @@ ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
 
   frame->rvalue = new_rvalue;
   frame->flags = flags;
+  frame->closure = closure;
 
   if (vfp_space)
     {
@@ -380,6 +383,19 @@ ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
     memcpy (rvalue, new_rvalue, rtype->size);
 }
 
+void
+ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, NULL);
+}
+
+void
+ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
+	     void **avalue, void *closure)
+{
+  ffi_call_int (cif, fn, rvalue, avalue, closure);
+}
+
 static void *
 ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
 			     char *argp, void **avalue)
@@ -476,31 +492,43 @@ ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
   return rvalue;
 }
 
+struct closure_frame
+{
+  char vfp_space[8*8] __attribute__((aligned(8)));
+  char result[8*4];
+  char argp[];
+};
+
 int FFI_HIDDEN
-ffi_closure_inner_SYSV (ffi_closure *closure, void *rvalue, char *argp)
+ffi_closure_inner_SYSV (ffi_cif *cif,
+		        void (*fun) (ffi_cif *, void *, void **, void *),
+		        void *user_data,
+		        struct closure_frame *frame)
 {
-  ffi_cif *cif = closure->cif;
   void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
-
-  rvalue = ffi_prep_incoming_args_SYSV (cif, rvalue, argp, avalue);
-  closure->fun (cif, rvalue, avalue, closure->user_data);
+  void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
+					      frame->argp, avalue);
+  fun (cif, rvalue, avalue, user_data);
   return cif->flags;
 }
 
 int FFI_HIDDEN
-ffi_closure_inner_VFP (ffi_closure *closure, void *rvalue,
-		       char *argp, char *vfp_space)
+ffi_closure_inner_VFP (ffi_cif *cif,
+		       void (*fun) (ffi_cif *, void *, void **, void *),
+		       void *user_data,
+		       struct closure_frame *frame)
 {
-  ffi_cif *cif = closure->cif;
   void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
-
-  rvalue = ffi_prep_incoming_args_VFP (cif, rvalue, argp, vfp_space, avalue);
-  closure->fun (cif, rvalue, avalue, closure->user_data);
+  void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
+					     frame->vfp_space, avalue);
+  fun (cif, rvalue, avalue, user_data);
   return cif->flags;
 }
 
 void ffi_closure_SYSV (void) FFI_HIDDEN;
 void ffi_closure_VFP (void) FFI_HIDDEN;
+void ffi_go_closure_SYSV (void) FFI_HIDDEN;
+void ffi_go_closure_VFP (void) FFI_HIDDEN;
 
 #if FFI_EXEC_TRAMPOLINE_TABLE
 
@@ -785,6 +813,28 @@ ffi_prep_closure_loc (ffi_closure * closure,
   return FFI_OK;
 }
 
+ffi_status
+ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
+		     void (*fun) (ffi_cif *, void *, void **, void *))
+{
+  void (*closure_func) (void) = ffi_go_closure_SYSV;
+
+  if (cif->abi == FFI_VFP)
+    {
+      /* We only need take the vfp path if there are vfp arguments.  */
+      if (cif->vfp_used)
+	closure_func = ffi_go_closure_VFP;
+    }
+  else if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  closure->tramp = closure_func;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+
 /* Below are routines for VFP hard-float support. */
 
 /* A subroutine of vfp_type_p.  Given a structure type, return the type code
diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h
index 744a1e1..4f473f9 100644
--- a/src/arm/ffitarget.h
+++ b/src/arm/ffitarget.h
@@ -62,6 +62,7 @@ typedef enum ffi_abi {
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
+#define FFI_GO_CLOSURES 1
 #define FFI_TRAMPOLINE_SIZE 12
 #define FFI_NATIVE_RAW_API 0
 
diff --git a/src/arm/sysv.S b/src/arm/sysv.S
index ce5450d..fd16589 100644
--- a/src/arm/sysv.S
+++ b/src/arm/sysv.S
@@ -136,6 +136,7 @@ ARM_FUNC_START(ffi_call_SYSV, 1)
 
 	mov	sp, r0		@ install the stack pointer
 	mov	lr, r2		@ move the fn pointer out of the way
+	ldr	ip, [fp, #16]	@ install the static chain
 	ldmia	sp!, {r0-r3}	@ move first 4 parameters in registers.
 	blx	lr		@ call fn
 
@@ -180,22 +181,33 @@ ARM_FUNC_END(ffi_call_SYSV)
 
 
 /*
-	unsigned int FFI_HIDDEN
-	ffi_closure_inner (closure, respp, args)
-	     ffi_closure *closure;
-	     void **respp;
-  	     void *args;
+	int ffi_closure_inner_* (cif, fun, user_data, frame)
 */
 
+ARM_FUNC_START(ffi_go_closure_SYSV, 1)
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	ldr	r0, [ip, #4]			@ load cif
+	ldr	r1, [ip, #8]			@ load fun
+	mov	r2, ip				@ load user_data
+	b	0f
+	cfi_endproc
+ARM_FUNC_END(ffi_go_closure_SYSV)
+
 ARM_FUNC_START(ffi_closure_SYSV, 1)
 	UNWIND	.fnstart
 	cfi_startproc
 	stmdb	sp!, {r0-r3}			@ save argument regs
 	cfi_adjust_cfa_offset(16)
-	mov	r0, ip				@ load closure
+	ldr	r0, [ip, #FFI_TRAMPOLINE_SIZE]	  @ load cif
+	ldr	r1, [ip, #FFI_TRAMPOLINE_SIZE+4]  @ load fun
+	ldr	r2, [ip, #FFI_TRAMPOLINE_SIZE+8]  @ load user_data
+0:
 	add	ip, sp, #16			@ compute entry sp
-	sub	sp, sp, #32			@ allocate rvalue space
-	stmdb	sp!, {sp,lr}
+	sub	sp, sp, #64+32			@ allocate frame
+	cfi_adjust_cfa_offset(64+32)
+	stmdb	sp!, {ip,lr}
 
 	/* Remember that EABI unwind info only applies at call sites.
 	   We need do nothing except note the save of the stack pointer
@@ -204,46 +216,53 @@ ARM_FUNC_START(ffi_closure_SYSV, 1)
 	cfi_adjust_cfa_offset(8)
 	cfi_rel_offset(lr, 4)
 
-	add	r1, sp, #8			@ load respp
-	add	r2, sp, #8+32			@ load args
-	mov	r3, #0				@ load vfp_args
-
+	add	r3, sp, #8			@ load frame
 	bl	CNAME(ffi_closure_inner_SYSV)
 
 	@ Load values returned in registers.
-	add	r2, sp, #8			@ load respp
+	add	r2, sp, #8+64			@ load result
 	adr	r3, CNAME(ffi_closure_ret)
 	add	pc, r3, r0, lsl #3
 	cfi_endproc
 	UNWIND	.fnend
 ARM_FUNC_END(ffi_closure_SYSV)
 
+ARM_FUNC_START(ffi_go_closure_VFP, 1)
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	ldr	r0, [ip, #4]			@ load cif
+	ldr	r1, [ip, #8]			@ load fun
+	mov	r2, ip				@ load user_data
+	b	0f
+	cfi_endproc
+ARM_FUNC_END(ffi_go_closure_VFP)
+
 ARM_FUNC_START(ffi_closure_VFP, 1)
 	UNWIND	.fnstart
 	cfi_startproc
 	stmdb	sp!, {r0-r3}			@ save argument regs
 	cfi_adjust_cfa_offset(16)
-	sub	sp, sp, #64+32			@ allocate vfp+rvalue space
+	ldr	r0, [ip, #FFI_TRAMPOLINE_SIZE]	  @ load cif
+	ldr	r1, [ip, #FFI_TRAMPOLINE_SIZE+4]  @ load fun
+	ldr	r2, [ip, #FFI_TRAMPOLINE_SIZE+8]  @ load user_data
+0:
+	add	ip, sp, #16
+	sub	sp, sp, #64+32			@ allocate frame
 	cfi_adjust_cfa_offset(64+32)
 	stc	p11, cr0, [sp], {16}		@ vstm sp, {d0-d7}
-	mov	r0, ip				@ load closure
-	add	ip, sp, #16+64+32		@ compute entry sp
 	stmdb	sp!, {ip,lr}
 
 	/* See above.  */
 	UNWIND	.save {sp,lr}
 	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(sp, 0)
 	cfi_rel_offset(lr, 4)
 
-	add	r1, sp, #8+64			@ load respp
-	add	r2, sp, #8+64+32		@ load args
-	add	r3, sp, #8			@ load vfp_args
-
+	add	r3, sp, #8			@ load frame
 	bl	CNAME(ffi_closure_inner_VFP)
 
 	@ Load values returned in registers.
-	add	r2, sp, #8+64			@ load respp
+	add	r2, sp, #8+64			@ load result
 	adr	r3, CNAME(ffi_closure_ret)
 	add	pc, r3, r0, lsl #3
 	cfi_endproc
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 06/10] arm: Rewrite ffi_closure
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
                   ` (8 preceding siblings ...)
  2014-10-29 20:06 ` [PATCH 09/10] arm: Add argument space for the hidden struct return pointer Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

Move the push of the argument registers into ffi_closure_SYSV,
reducing the size of the trampoline.
---
 Makefile.am          |    7 +-
 src/arm/ffi.c        |  220 +--
 src/arm/ffitarget.h  |    2 +-
 src/arm/gentramp.sh  |  118 --
 src/arm/sysv.S       |  231 ++-
 src/arm/trampoline.S | 4450 --------------------------------------------------
 6 files changed, 191 insertions(+), 4837 deletions(-)
 delete mode 100755 src/arm/gentramp.sh
 delete mode 100644 src/arm/trampoline.S

diff --git a/Makefile.am b/Makefile.am
index 0e40451..18ab7cd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,9 +48,9 @@ EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj			\
 	 src/xtensa/ffitarget.h src/xtensa/ffi.c src/xtensa/sysv.S	\
 	 ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4		\
 	 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4			\
-	 m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh	\
+	 m4/ltversion.m4 src/debug.c msvcc.sh				\
 	 generate-darwin-source-and-headers.py				\
-	 libffi.xcodeproj/project.pbxproj src/arm/trampoline.S		\
+	 libffi.xcodeproj/project.pbxproj				\
 	 libtool-ldflags ChangeLog.libffi-3.1
 
 info_TEXINFOS = doc/libffi.texi
@@ -193,9 +193,6 @@ nodist_libffi_la_SOURCES += src/arc/arcompact.S src/arc/ffi.c
 endif
 if ARM
 nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
-if FFI_EXEC_TRAMPOLINE_TABLE
-nodist_libffi_la_SOURCES += src/arm/trampoline.S
-endif
 endif
 if AVR32
 nodist_libffi_la_SOURCES += src/avr32/sysv.S src/avr32/ffi.c
diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index c91b869..395af97 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -364,157 +364,87 @@ ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
       ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
       ffi_call_SYSV (stack, frame, fn);
     }
- 
+
   if (rvalue && rvalue != new_rvalue)
     memcpy (rvalue, new_rvalue, rtype->size);
 }
 
-/** private members **/
-
-static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
-					 void **args, ffi_cif *cif,
-					 float *vfp_stack);
-
-static void ffi_prep_incoming_args_VFP (char *stack, void **ret,
-					void **args, ffi_cif *cif,
-					float *vfp_stack);
-
-void ffi_closure_SYSV (ffi_closure *);
-
-void ffi_closure_VFP (ffi_closure *);
-
-/* This function is jumped to by the trampoline */
-
-unsigned int FFI_HIDDEN
-ffi_closure_inner (ffi_closure *closure,
-		   void **respp, void *args, void *vfp_args)
-{
-  // our various things...
-  ffi_cif *cif;
-  void **arg_area;
-
-  cif = closure->cif;
-  arg_area = (void **) alloca (cif->nargs * sizeof (void *));
-
-  /* this call will initialize ARG_AREA, such that each
-   * element in that array points to the corresponding
-   * value on the stack; and if the function returns
-   * a structure, it will re-set RESP to point to the
-   * structure return address.  */
-  if (cif->abi == FFI_VFP)
-    ffi_prep_incoming_args_VFP (args, respp, arg_area, cif, vfp_args);
-  else
-    ffi_prep_incoming_args_SYSV (args, respp, arg_area, cif, vfp_args);
-
-  (closure->fun) (cif, *respp, arg_area, closure->user_data);
-
-  return cif->flags;
-}
-
-/*@-exportheader@*/
-static void
-ffi_prep_incoming_args_SYSV (char *stack, void **rvalue,
-			     void **avalue, ffi_cif *cif,
-			     /* Used only under VFP hard-float ABI. */
-			     float *vfp_stack)
-/*@=exportheader@*/
+static void *
+ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
+			     char *argp, void **avalue)
 {
-  register unsigned int i;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-
-  argp = stack;
+  ffi_type **arg_types = cif->arg_types;
+  int i, n;
 
-  if (cif->flags == FFI_TYPE_STRUCT)
+  if (cif->flags == ARM_TYPE_STRUCT)
     {
-      *rvalue = *(void **) argp;
+      rvalue = *(void **) argp;
       argp += 4;
     }
 
-  p_argv = avalue;
-
-  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+  for (i = 0, n = cif->nargs; i < n; i++)
     {
-      size_t z;
-
-      argp = ffi_align (*p_arg, argp);
-
-      z = (*p_arg)->size;
-
-      /* because we're little endian, this is what it turns into.   */
-
-      *p_argv = (void *) argp;
+      ffi_type *ty = arg_types[i];
+      size_t z = ty->size;
 
-      p_argv++;
+      argp = ffi_align (ty, argp);
+      avalue[i] = (void *) argp;
       argp += z;
     }
 
-  return;
+  return rvalue;
 }
 
-/*@-exportheader@*/
-static void
-ffi_prep_incoming_args_VFP (char *stack, void **rvalue,
-			    void **avalue, ffi_cif * cif,
-			    /* Used only under VFP hard-float ABI. */
-			    float *vfp_stack)
-/*@=exportheader@*/
+static void *
+ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
+			    char *vfp_space, void **avalue)
 {
-  register unsigned int i, vi = 0;
-  register void **p_argv;
-  register char *argp, *regp, *eo_regp;
-  register ffi_type **p_arg;
+  ffi_type **arg_types = cif->arg_types;
+  int i, n, vi = 0;
+  char *argp, *regp, *eo_regp;
   char done_with_regs = 0;
   char stack_used = 0;
 
-  FFI_ASSERT (cif->abi == FFI_VFP);
   regp = stack;
   eo_regp = argp = regp + 16;
 
-  if (cif->flags == FFI_TYPE_STRUCT)
+  if (cif->flags == ARM_TYPE_STRUCT)
     {
-      *rvalue = *(void **) regp;
+      rvalue = *(void **) regp;
       regp += 4;
     }
 
-  p_argv = avalue;
-
-  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+  for (i = 0, n = cif->nargs; i < n; i++)
     {
-      int is_vfp_type = vfp_type_p (*p_arg);
-      size_t z;
+      ffi_type *ty = arg_types[i];
+      int is_vfp_type = vfp_type_p (ty);
+      size_t z = ty->size;
 
       if (vi < cif->vfp_nargs && is_vfp_type)
 	{
-	  *p_argv++ = (void *) (vfp_stack + cif->vfp_args[vi++]);
+	  avalue[i] = vfp_space + cif->vfp_args[vi++] * 4;
 	  continue;
 	}
       else if (!done_with_regs && !is_vfp_type)
 	{
-	  char *tregp = ffi_align (*p_arg, regp);
+	  char *tregp = ffi_align (ty, regp);
 
-	  z = (*p_arg)->size;
 	  z = (z < 4) ? 4 : z;	// pad
 
-	  /* if the arguments either fits into the registers or uses registers
-	   * and stack, while we haven't read other things from the stack */
+	  /* If the arguments either fits into the registers or uses registers
+	     and stack, while we haven't read other things from the stack */
 	  if (tregp + z <= eo_regp || !stack_used)
 	    {
-	      /* because we're little endian, this is what it turns into. */
-	      *p_argv = (void *) tregp;
-
-	      p_argv++;
+	      /* Because we're little endian, this is what it turns into.  */
+	      avalue[i] = (void *) tregp;
 	      regp = tregp + z;
-	      // if we read past the last core register, make sure we have not read
-	      // from the stack before and continue reading after regp
+
+	      /* If we read past the last core register, make sure we
+		 have not read from the stack before and continue
+		 reading after regp.  */
 	      if (regp > eo_regp)
 		{
-		  if (stack_used)
-		    {
-		      abort ();	// we should never read past the end of the register
-		      // are if the stack is already in use
-		    }
+		  FFI_ASSERT (!stack_used);
 		  argp = regp;
 		}
 	      if (regp >= eo_regp)
@@ -525,26 +455,41 @@ ffi_prep_incoming_args_VFP (char *stack, void **rvalue,
 	      continue;
 	    }
 	}
-      stack_used = 1;
 
-      argp = ffi_align (*p_arg, argp);
+      stack_used = 1;
+      argp = ffi_align (ty, argp);
+      avalue[i] = (void *) argp;
+      argp += z;
+    }
 
-      z = (*p_arg)->size;
+  return rvalue;
+}
 
-      /* because we're little endian, this is what it turns into.   */
+int FFI_HIDDEN
+ffi_closure_inner_SYSV (ffi_closure *closure, void *rvalue, char *argp)
+{
+  ffi_cif *cif = closure->cif;
+  void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
 
-      *p_argv = (void *) argp;
+  rvalue = ffi_prep_incoming_args_SYSV (cif, rvalue, argp, avalue);
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+  return cif->flags;
+}
 
-      p_argv++;
-      argp += z;
-    }
+int FFI_HIDDEN
+ffi_closure_inner_VFP (ffi_closure *closure, void *rvalue,
+		       char *argp, char *vfp_space)
+{
+  ffi_cif *cif = closure->cif;
+  void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
 
-  return;
+  rvalue = ffi_prep_incoming_args_VFP (cif, rvalue, argp, vfp_space, avalue);
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+  return cif->flags;
 }
 
-/* How to make a trampoline.  */
-
-extern unsigned int ffi_arm_trampoline[3];
+void ffi_closure_SYSV (void) FFI_HIDDEN;
+void ffi_closure_VFP (void) FFI_HIDDEN;
 
 #if FFI_EXEC_TRAMPOLINE_TABLE
 
@@ -788,19 +733,7 @@ ffi_closure_free (void *ptr)
 
 #else
 
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX)				\
-({ unsigned char *__tramp = (unsigned char*)(TRAMP);			\
-   unsigned int  __fun = (unsigned int)(FUN);				\
-   unsigned int  __ctx = (unsigned int)(CTX);				\
-   unsigned char *insns = (unsigned char *)(CTX);                       \
-   memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline);     \
-   *(unsigned int*) &__tramp[12] = __ctx;				\
-   *(unsigned int*) &__tramp[16] = __fun;				\
-   __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping.  */ \
-   __clear_cache(insns, insns + 3 * sizeof (unsigned int));             \
-                                                 /* Clear instruction   \
-                                                    mapping.  */        \
- })
+extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
 
 #endif
 
@@ -812,15 +745,15 @@ ffi_prep_closure_loc (ffi_closure * closure,
 		      void (*fun) (ffi_cif *, void *, void **, void *),
 		      void *user_data, void *codeloc)
 {
-  void (*closure_func) (ffi_closure *) = NULL;
+  void (*closure_func) (void) = ffi_closure_SYSV;
 
-  if (cif->abi == FFI_SYSV)
-    closure_func = &ffi_closure_SYSV;
-#ifdef __ARM_EABI__
-  else if (cif->abi == FFI_VFP)
-    closure_func = &ffi_closure_VFP;
-#endif
-  else
+  if (cif->abi == FFI_VFP)
+    {
+      /* We only need take the vfp path if there are vfp arguments.  */
+      if (cif->vfp_used)
+	closure_func = ffi_closure_VFP;
+    }
+  else if (cif->abi != FFI_SYSV)
     return FFI_BAD_ABI;
 
 #if FFI_EXEC_TRAMPOLINE_TABLE
@@ -828,12 +761,15 @@ ffi_prep_closure_loc (ffi_closure * closure,
   config[0] = closure;
   config[1] = closure_func;
 #else
-  FFI_INIT_TRAMPOLINE (&closure->tramp[0], closure_func, codeloc);
+  memcpy (closure->tramp, ffi_arm_trampoline, 8);
+  __clear_cache(closure->tramp, closure->tramp + 8);	/* clear data map */
+  __clear_cache(codeloc, codeloc + 8);			/* clear insn map */
+  *(void (**)(void))(closure->tramp + 8) = closure_func;
 #endif
 
   closure->cif = cif;
-  closure->user_data = user_data;
   closure->fun = fun;
+  closure->user_data = user_data;
 
   return FFI_OK;
 }
diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h
index 6355904..421bacf 100644
--- a/src/arm/ffitarget.h
+++ b/src/arm/ffitarget.h
@@ -65,7 +65,7 @@ typedef enum ffi_abi {
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
-#define FFI_TRAMPOLINE_SIZE 20
+#define FFI_TRAMPOLINE_SIZE 12
 #define FFI_NATIVE_RAW_API 0
 
 #endif
diff --git a/src/arm/gentramp.sh b/src/arm/gentramp.sh
deleted file mode 100755
index 05c43a3..0000000
--- a/src/arm/gentramp.sh
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/bin/sh
-
-# -----------------------------------------------------------------------
-#  gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc.
-#  
-#  ARM Trampoline Page Generator
-#
-#  Permission is hereby granted, free of charge, to any person obtaining
-#  a copy of this software and associated documentation files (the
-#  ``Software''), to deal in the Software without restriction, including
-#  without limitation the rights to use, copy, modify, merge, publish,
-#  distribute, sublicense, and/or sell copies of the Software, and to
-#  permit persons to whom the Software is furnished to do so, subject to
-#  the following conditions:
-#
-#  The above copyright notice and this permission notice shall be included
-#  in all copies or substantial portions of the Software.
-#
-#  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-#  DEALINGS IN THE SOFTWARE.
-#  -----------------------------------------------------------------------
-
-PROGNAME=$0
-
-# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change,
-# the entire arm trampoline implementation must be updated to match, too.
-
-# Size of an individual trampoline, in bytes
-TRAMPOLINE_SIZE=12
-
-# Page size, in bytes
-PAGE_SIZE=4096
-
-# Compute the size of the reachable config page; The first 16 bytes of the config page
-# are unreachable due to our maximum pc-relative ldr offset.
-PAGE_AVAIL=`expr $PAGE_SIZE - 16`
-
-# Compute the number of of available trampolines. 
-TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE`
-
-header () {
-    echo "# GENERATED CODE - DO NOT EDIT"
-    echo "# This file was generated by $PROGNAME"
-    echo ""
-
-    # Write out the license header
-cat << EOF
-#  Copyright (c) 2010, Plausible Labs Cooperative, Inc.
-#  
-#  Permission is hereby granted, free of charge, to any person obtaining
-#  a copy of this software and associated documentation files (the
-#  ``Software''), to deal in the Software without restriction, including
-#  without limitation the rights to use, copy, modify, merge, publish,
-#  distribute, sublicense, and/or sell copies of the Software, and to
-#  permit persons to whom the Software is furnished to do so, subject to
-#  the following conditions:
-#
-#  The above copyright notice and this permission notice shall be included
-#  in all copies or substantial portions of the Software.
-#
-#  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-#  NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-#  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-#  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-#  DEALINGS IN THE SOFTWARE.
-#  -----------------------------------------------------------------------
-
-EOF
-
-    # Write out the trampoline table, aligned to the page boundary
-    echo ".text"
-    echo ".align 12"
-    echo ".globl _ffi_closure_trampoline_table_page"
-    echo "_ffi_closure_trampoline_table_page:"
-}
-
-
-# WARNING - Don't modify the trampoline code size without also updating the relevant 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/src/arm/sysv.S b/src/arm/sysv.S
index b967d97..ce5450d 100644
--- a/src/arm/sysv.S
+++ b/src/arm/sysv.S
@@ -189,139 +189,128 @@ ARM_FUNC_END(ffi_call_SYSV)
 
 ARM_FUNC_START(ffi_closure_SYSV, 1)
 	UNWIND	.fnstart
-	UNWIND .pad #16
-	add	ip, sp, #16
-	stmfd	sp!, {ip, lr}
-	UNWIND .save	{r0, lr}
-	add	r2, sp, #8
-	UNWIND .pad #16
-	sub	sp, sp, #16
-	str	sp, [sp, #8]
-	add	r1, sp, #8
-	bl	CNAME(ffi_closure_inner)
-	cmp	r0, #FFI_TYPE_INT
-	beq	.Lretint
-
-	cmp	r0, #FFI_TYPE_FLOAT
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	beq	.Lretint
-#else
-	beq	.Lretfloat
-#endif
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	mov	r0, ip				@ load closure
+	add	ip, sp, #16			@ compute entry sp
+	sub	sp, sp, #32			@ allocate rvalue space
+	stmdb	sp!, {sp,lr}
+
+	/* Remember that EABI unwind info only applies at call sites.
+	   We need do nothing except note the save of the stack pointer
+	   and the link registers.  */
+	UNWIND	.save {sp,lr}
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(lr, 4)
 
-	cmp	r0, #FFI_TYPE_DOUBLE
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	beq	.Lretlonglong
-#else
-	beq	.Lretdouble
-#endif
+	add	r1, sp, #8			@ load respp
+	add	r2, sp, #8+32			@ load args
+	mov	r3, #0				@ load vfp_args
 
-	cmp	r0, #FFI_TYPE_LONGDOUBLE
-#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-	beq	.Lretlonglong
-#else
-	beq	.Lretlongdouble
-#endif
+	bl	CNAME(ffi_closure_inner_SYSV)
 
-	cmp	r0, #FFI_TYPE_SINT64
-	beq	.Lretlonglong
-.Lclosure_epilogue:
-	add	sp, sp, #16
-	ldmfd	sp, {sp, pc}
-.Lretint:
-	ldr	r0, [sp]
-	b	.Lclosure_epilogue
-.Lretlonglong:
-	ldr	r0, [sp]
-	ldr	r1, [sp, #4]
-	b	.Lclosure_epilogue
-
-#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
-.Lretfloat:
-	ldfs	f0, [sp]
-	b	.Lclosure_epilogue
-.Lretdouble:
-	ldfd	f0, [sp]
-	b	.Lclosure_epilogue
-.Lretlongdouble:
-	ldfd	f0, [sp]
-	b	.Lclosure_epilogue
-#endif
-	UNWIND .fnend
+	@ Load values returned in registers.
+	add	r2, sp, #8			@ load respp
+	adr	r3, CNAME(ffi_closure_ret)
+	add	pc, r3, r0, lsl #3
+	cfi_endproc
+	UNWIND	.fnend
 ARM_FUNC_END(ffi_closure_SYSV)
 
-
-/* Below are VFP hard-float ABI call and closure implementations.
-   Add VFP FPU directive here. This is only compiled into the library
-   under EABI.  */
-#ifdef __ARM_EABI__
 ARM_FUNC_START(ffi_closure_VFP, 1)
 	UNWIND	.fnstart
-	fstmfdd	sp!, {d0-d7}
-	@ r0-r3, then d0-d7
-	UNWIND .pad #80
-	add	ip, sp, #80
-	stmfd	sp!, {ip, lr}
-	UNWIND .save	{r0, lr}
-	add	r2, sp, #72
-	add	r3, sp, #8
-	UNWIND .pad #72
-	sub	sp, sp, #72
-	str	sp, [sp, #64]
-	add	r1, sp, #64
-	bl	CNAME(ffi_closure_inner)
-
-	cmp	r0, #FFI_TYPE_INT
-	beq	.Lretint_vfp
-
-	cmp	r0, #FFI_TYPE_FLOAT
-	beq	.Lretfloat_vfp
-
-	cmp	r0, #FFI_TYPE_DOUBLE
-	cmpne	r0, #FFI_TYPE_LONGDOUBLE
-	beq	.Lretdouble_vfp
-
-	cmp	r0, #FFI_TYPE_SINT64
-	beq	.Lretlonglong_vfp
-
-	cmp	r0, #FFI_TYPE_STRUCT_VFP_FLOAT
-	beq	.Lretfloat_struct_vfp
-
-	cmp	r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
-	beq	.Lretdouble_struct_vfp
-	
-.Lclosure_epilogue_vfp:
-	add	sp, sp, #72
-	ldmfd	sp, {sp, pc}
-
-.Lretfloat_vfp:
-	flds	s0, [sp]
-	b	.Lclosure_epilogue_vfp
-.Lretdouble_vfp:
-	fldd	d0, [sp]
-	b	.Lclosure_epilogue_vfp
-.Lretint_vfp:
-	ldr	r0, [sp]
-	b	.Lclosure_epilogue_vfp
-.Lretlonglong_vfp:
-	ldmia	sp, {r0, r1}
-	b	.Lclosure_epilogue_vfp
-.Lretfloat_struct_vfp:
-	fldmiad	sp, {d0-d1}
-	b	.Lclosure_epilogue_vfp
-.Lretdouble_struct_vfp:
-	fldmiad	sp, {d0-d3}
-	b	.Lclosure_epilogue_vfp
-	UNWIND .fnend
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	sub	sp, sp, #64+32			@ allocate vfp+rvalue space
+	cfi_adjust_cfa_offset(64+32)
+	stc	p11, cr0, [sp], {16}		@ vstm sp, {d0-d7}
+	mov	r0, ip				@ load closure
+	add	ip, sp, #16+64+32		@ compute entry sp
+	stmdb	sp!, {ip,lr}
+
+	/* See above.  */
+	UNWIND	.save {sp,lr}
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(sp, 0)
+	cfi_rel_offset(lr, 4)
+
+	add	r1, sp, #8+64			@ load respp
+	add	r2, sp, #8+64+32		@ load args
+	add	r3, sp, #8			@ load vfp_args
+
+	bl	CNAME(ffi_closure_inner_VFP)
+
+	@ Load values returned in registers.
+	add	r2, sp, #8+64			@ load respp
+	adr	r3, CNAME(ffi_closure_ret)
+	add	pc, r3, r0, lsl #3
+	cfi_endproc
+	UNWIND	.fnend
 ARM_FUNC_END(ffi_closure_VFP)
-#endif
+
+/* Load values returned in registers for both closure entry points.
+   Note that we use LDM with SP in the register set.  This is deprecated
+   by ARM, but not yet unpredictable.  */
+
+ARM_FUNC_START(ffi_closure_ret, 0)
+	cfi_startproc
+	cfi_rel_offset(sp, 0)
+	cfi_rel_offset(lr, 4)
+0:
+E ARM_TYPE_VFP_S
+	ldc	p10, cr0, [r2]			@ vldr s0, [r2]
+	ldm	sp, {sp,pc}
+E ARM_TYPE_VFP_D
+	ldc	p11, cr0, [r2]			@ vldr d0, [r2]
+	ldm	sp, {sp,pc}
+E ARM_TYPE_VFP_N
+	ldc	p11, cr0, [r2], {8}		@ vldm r2, {d0-d3}
+	ldm	sp, {sp,pc}
+E ARM_TYPE_INT64
+	ldr	r1, [r2, #4]
+	nop
+E ARM_TYPE_INT
+	ldr	r0, [r2]
+	ldm	sp, {sp,pc}
+E ARM_TYPE_VOID
+	ldm	sp, {sp,pc}
+	nop
+E ARM_TYPE_STRUCT
+	ldm	sp, {sp,pc}
+	cfi_endproc
+ARM_FUNC_END(ffi_closure_ret)
+
+#if FFI_EXEC_TRAMPOLINE_TABLE
+
+/* ??? The iOS support should be updated.  The first insn used to
+   be STMFD, but that's been moved into ffi_closure_SYSV.  If the
+   writable page is put after this one we can make use of the
+   pc+8 feature of the architecture.  We can also reduce the size
+   of the thunk to 8 and pack more of these into the page.
+
+   In the meantime, simply replace the STMFD with a NOP so as to
+   keep all the magic numbers the same within ffi.c.  */
+
+	.align	12
+ARM_FUNC_START(ffi_closure_trampoline_table_page)
+.rept	4096 / 12
+	nop
+	ldr	ip, [pc, #-4092]
+	ldr	pc, [pc, #-4092]
+.endr
+
+#else
 
 ARM_FUNC_START(ffi_arm_trampoline, 1)
-	stmfd sp!, {r0-r3}
-	ldr r0, [pc]
-	ldr pc, [pc]
+0:	adr	ip, 0b
+	ldr	pc, 1f
+1:	.long	0
 ARM_FUNC_END(ffi_arm_trampoline)
 
+#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
+
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",%progbits
 #endif
diff --git a/src/arm/trampoline.S b/src/arm/trampoline.S
deleted file mode 100644
index 935e8de..0000000
--- a/src/arm/trampoline.S
+++ /dev/null
@@ -1,4450 +0,0 @@
-# GENERATED CODE - DO NOT EDIT
-# This file was generated by src/arm/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]
-
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 01/10] arm: Reindent arm/ffi.c
  2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
                   ` (6 preceding siblings ...)
  2014-10-29 20:06 ` [PATCH 10/10] arm: Add support for Go closures Richard Henderson
@ 2014-10-29 20:06 ` Richard Henderson
  2014-10-29 20:06 ` [PATCH 09/10] arm: Add argument space for the hidden struct return pointer Richard Henderson
  2014-10-29 20:06 ` [PATCH 06/10] arm: Rewrite ffi_closure Richard Henderson
  9 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2014-10-29 20:06 UTC (permalink / raw)
  To: libffi-discuss

---
 src/arm/ffi.c | 743 +++++++++++++++++++++++++++++++---------------------------
 1 file changed, 392 insertions(+), 351 deletions(-)

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index 6691ab5..c5fd831 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -37,122 +37,126 @@
 static int vfp_type_p (ffi_type *);
 static void layout_vfp_args (ffi_cif *);
 
-int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space);
-int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space);
+int ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space);
+int ffi_prep_args_VFP (char *stack, extended_cif *ecif, float *vfp_space);
 
-static char* ffi_align(ffi_type **p_arg, char *argp)
+static char *
+ffi_align (ffi_type **p_arg, char *argp)
 {
   /* Align if necessary */
   register size_t alignment = (*p_arg)->alignment;
   if (alignment < 4)
-  {
-    alignment = 4;
-  }
+    {
+      alignment = 4;
+    }
 #ifdef _WIN32_WCE
   if (alignment > 4)
-  {
-    alignment = 4;
-  }
+    {
+      alignment = 4;
+    }
 #endif
   if ((alignment - 1) & (unsigned) argp)
-  {
-    argp = (char *) ALIGN(argp, alignment);
-  }
-
+    {
+      argp = (char *) ALIGN (argp, alignment);
+    }
   if ((*p_arg)->type == FFI_TYPE_STRUCT)
-  {
-    argp = (char *) ALIGN(argp, 4);
-  }
+    {
+      argp = (char *) ALIGN (argp, 4);
+    }
   return argp;
 }
 
-static size_t ffi_put_arg(ffi_type **arg_type, void **arg, char *stack)
+static size_t
+ffi_put_arg (ffi_type **arg_type, void **arg, char *stack)
 {
-	register char* argp = stack;
-	register ffi_type **p_arg = arg_type;
-	register void **p_argv = arg;
-	register size_t z = (*p_arg)->size;
-  if (z < sizeof(int))
+  register char *argp = stack;
+  register ffi_type **p_arg = arg_type;
+  register void **p_argv = arg;
+  register size_t z = (*p_arg)->size;
+
+  if (z < sizeof (int))
     {
-		z = sizeof(int);
-		switch ((*p_arg)->type)
-      {
-      case FFI_TYPE_SINT8:
-        *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
-        break;
-        
-      case FFI_TYPE_UINT8:
-        *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
-        break;
-        
-      case FFI_TYPE_SINT16:
-        *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
-        break;
-        
-      case FFI_TYPE_UINT16:
-        *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
-        break;
-        
-      case FFI_TYPE_STRUCT:
-        memcpy(argp, *p_argv, (*p_arg)->size);
-        break;
-
-      default:
-        FFI_ASSERT(0);
-      }
+      z = sizeof (int);
+      switch ((*p_arg)->type)
+	{
+	case FFI_TYPE_SINT8:
+	  *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT8:
+	  *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
+	  break;
+
+	case FFI_TYPE_SINT16:
+	  *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT16:
+	  *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  memcpy (argp, *p_argv, (*p_arg)->size);
+	  break;
+
+	default:
+	  FFI_ASSERT (0);
+	}
     }
-  else if (z == sizeof(int))
+  else if (z == sizeof (int))
     {
-		if ((*p_arg)->type == FFI_TYPE_FLOAT)
-			*(float *) argp = *(float *)(* p_argv);
-		else
-			*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+      if ((*p_arg)->type == FFI_TYPE_FLOAT)
+	*(float *) argp = *(float *) (*p_argv);
+      else
+	*(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
+    }
+  else if (z == sizeof (double) && (*p_arg)->type == FFI_TYPE_DOUBLE)
+    {
+      *(double *) argp = *(double *) (*p_argv);
     }
-	else if (z == sizeof(double) && (*p_arg)->type == FFI_TYPE_DOUBLE)
-		{
-			*(double *) argp = *(double *)(* p_argv);
-		}
   else
     {
-      memcpy(argp, *p_argv, z);
+      memcpy (argp, *p_argv, z);
     }
   return z;
 }
+
 /* ffi_prep_args is called by the assembly routine once stack space
    has been allocated for the function's arguments
-   
+
    The vfp_space parameter is the load area for VFP regs, the return
    value is cif->vfp_used (word bitset of VFP regs used for passing
    arguments). These are only used for the VFP hard-float ABI.
 */
-int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space)
+int
+ffi_prep_args_SYSV (char *stack, extended_cif *ecif, float *vfp_space)
 {
   register unsigned int i;
   register void **p_argv;
   register char *argp;
   register ffi_type **p_arg;
   argp = stack;
-  
 
-  if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
-    *(void **) argp = ecif->rvalue;
-    argp += 4;
-  }
+  if (ecif->cif->flags == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+    }
 
   p_argv = ecif->avalue;
 
   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       (i != 0);
-       i--, p_arg++, p_argv++)
+       (i != 0); i--, p_arg++, p_argv++)
     {
-    argp = ffi_align(p_arg, argp);
-    argp += ffi_put_arg(p_arg, p_argv, argp);
+      argp = ffi_align (p_arg, argp);
+      argp += ffi_put_arg (p_arg, p_argv, argp);
     }
 
   return 0;
 }
 
-int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space)
+int
+ffi_prep_args_VFP (char *stack, extended_cif * ecif, float *vfp_space)
 {
   register unsigned int i, vi = 0;
   register void **p_argv;
@@ -162,79 +166,79 @@ int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space)
   char done_with_regs = 0;
   char is_vfp_type;
 
-  // make sure we are using FFI_VFP
-  FFI_ASSERT(ecif->cif->abi == FFI_VFP);
+  /* Make sure we are using FFI_VFP.  */
+  FFI_ASSERT (ecif->cif->abi == FFI_VFP);
 
-  /* the first 4 words on the stack are used for values passed in core
-   * registers. */
+  /* The first 4 words on the stack are used for values
+     passed in core registers.  */
   regp = stack;
   eo_regp = argp = regp + 16;
-  
 
-  /* if the function returns an FFI_TYPE_STRUCT in memory, that address is
-   * passed in r0 to the function */
-  if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
-    *(void **) regp = ecif->rvalue;
-    regp += 4;
-  }
+  /* If the function returns an FFI_TYPE_STRUCT in memory,
+     that address is passed in r0 to the function.  */
+  if (ecif->cif->flags == FFI_TYPE_STRUCT)
+    {
+      *(void **) regp = ecif->rvalue;
+      regp += 4;
+    }
 
   p_argv = ecif->avalue;
 
   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       (i != 0);
-       i--, p_arg++, p_argv++)
+       (i != 0); i--, p_arg++, p_argv++)
     {
       is_vfp_type = vfp_type_p (*p_arg);
 
       /* Allocated in VFP registers. */
-      if(vi < ecif->cif->vfp_nargs && is_vfp_type)
-        {
-          char *vfp_slot = (char *)(vfp_space + ecif->cif->vfp_args[vi++]);
-          ffi_put_arg(p_arg, p_argv, vfp_slot);
-          continue;
-        }
+      if (vi < ecif->cif->vfp_nargs && is_vfp_type)
+	{
+	  char *vfp_slot = (char *) (vfp_space + ecif->cif->vfp_args[vi++]);
+	  ffi_put_arg (p_arg, p_argv, vfp_slot);
+	  continue;
+	}
       /* Try allocating in core registers. */
       else if (!done_with_regs && !is_vfp_type)
-        {
-          char *tregp = ffi_align(p_arg, regp);
-          size_t size = (*p_arg)->size; 
-          size = (size < 4)? 4 : size; // pad
-          /* Check if there is space left in the aligned register area to place
-           * the argument */
-          if(tregp + size <= eo_regp)
-            {
-              regp = tregp + ffi_put_arg(p_arg, p_argv, tregp);
-              done_with_regs = (regp == argp);
-              // ensure we did not write into the stack area
-              FFI_ASSERT(regp <= argp);
-              continue;
-            }
-          /* In case there are no arguments in the stack area yet, 
-          the argument is passed in the remaining core registers and on the
-          stack. */
-          else if (!stack_used) 
-            {
-              stack_used = 1;
-              done_with_regs = 1;
-              argp = tregp + ffi_put_arg(p_arg, p_argv, tregp);
-              FFI_ASSERT(eo_regp < argp);
-              continue;
-            }
-        }
+	{
+	  char *tregp = ffi_align (p_arg, regp);
+	  size_t size = (*p_arg)->size;
+	  size = (size < 4) ? 4 : size;	// pad
+	  /* Check if there is space left in the aligned register
+	     area to place the argument.  */
+	  if (tregp + size <= eo_regp)
+	    {
+	      regp = tregp + ffi_put_arg (p_arg, p_argv, tregp);
+	      done_with_regs = (regp == argp);
+	      // ensure we did not write into the stack area
+	      FFI_ASSERT (regp <= argp);
+	      continue;
+	    }
+	  /* In case there are no arguments in the stack area yet,
+	     the argument is passed in the remaining core registers
+	     and on the stack.  */
+	  else if (!stack_used)
+	    {
+	      stack_used = 1;
+	      done_with_regs = 1;
+	      argp = tregp + ffi_put_arg (p_arg, p_argv, tregp);
+	      FFI_ASSERT (eo_regp < argp);
+	      continue;
+	    }
+	}
       /* Base case, arguments are passed on the stack */
       stack_used = 1;
-      argp = ffi_align(p_arg, argp);
-      argp += ffi_put_arg(p_arg, p_argv, argp);
+      argp = ffi_align (p_arg, argp);
+      argp += ffi_put_arg (p_arg, p_argv, argp);
     }
   /* Indicate the VFP registers used. */
   return ecif->cif->vfp_used;
 }
 
 /* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+ffi_status
+ffi_prep_cif_machdep (ffi_cif * cif)
 {
   int type_code;
-  /* Round the stack up to a multiple of 8 bytes.  This isn't needed 
+  /* Round the stack up to a multiple of 8 bytes.  This isn't needed
      everywhere, but it is on some platforms, and it doesn't harm anything
      when it isn't needed.  */
   cif->bytes = (cif->bytes + 7) & ~7;
@@ -254,21 +258,24 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
       break;
 
     case FFI_TYPE_STRUCT:
-      if (cif->abi == FFI_VFP
-	  && (type_code = vfp_type_p (cif->rtype)) != 0)
+      if (cif->abi == FFI_VFP && (type_code = vfp_type_p (cif->rtype)) != 0)
 	{
 	  /* A Composite Type passed in VFP registers, either
 	     FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
 	  cif->flags = (unsigned) type_code;
 	}
       else if (cif->rtype->size <= 4)
-	/* A Composite Type not larger than 4 bytes is returned in r0.  */
-	cif->flags = (unsigned)FFI_TYPE_INT;
+	{
+	  /* A Composite Type not larger than 4 bytes is returned in r0.  */
+	  cif->flags = (unsigned) FFI_TYPE_INT;
+	}
       else
-	/* A Composite Type larger than 4 bytes, or whose size cannot
-	   be determined statically ... is stored in memory at an
-	   address passed [in r0].  */
-	cif->flags = (unsigned)FFI_TYPE_STRUCT;
+	{
+	  /* A Composite Type larger than 4 bytes, or whose size cannot
+	     be determined statically ... is stored in memory at an
+	     address passed [in r0].  */
+	  cif->flags = (unsigned) FFI_TYPE_STRUCT;
+	}
       break;
 
     default:
@@ -276,9 +283,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
       break;
     }
 
-  /* Map out the register placements of VFP register args.
-     The VFP hard-float calling conventions are slightly more sophisticated than
-     the base calling conventions, so we do it here instead of in ffi_prep_args(). */
+  /* Map out the register placements of VFP register args.  The VFP
+     hard-float calling conventions are slightly more sophisticated
+     than the base calling conventions, so we do it here instead of
+     in ffi_prep_args(). */
   if (cif->abi == FFI_VFP)
     layout_vfp_args (cif);
 
@@ -286,54 +294,56 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 }
 
 /* Perform machine dependent cif processing for variadic calls */
-ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
-				    unsigned int nfixedargs,
-				    unsigned int ntotalargs)
+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;
+    cif->abi = FFI_SYSV;
 
-  return ffi_prep_cif_machdep(cif);
+  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 *);
+/* 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 *);
 
-void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+void
+ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
 {
   extended_cif ecif;
 
-  int small_struct = (cif->flags == FFI_TYPE_INT 
+  int small_struct = (cif->flags == FFI_TYPE_INT
 		      && cif->rtype->type == FFI_TYPE_STRUCT);
   int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
 		    || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
 
   unsigned int temp;
-  
+
   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 the return value is a struct and we don't have a return
+     value address then we need to make one.  */
 
-  if ((rvalue == NULL) && 
-      (cif->flags == FFI_TYPE_STRUCT))
+  if ((rvalue == NULL) && (cif->flags == FFI_TYPE_STRUCT))
     {
-      ecif.rvalue = alloca(cif->rtype->size);
+      ecif.rvalue = alloca (cif->rtype->size);
     }
   else if (small_struct)
     ecif.rvalue = &temp;
   else if (vfp_struct)
     {
       /* Largest case is double x 4. */
-      ecif.rvalue = alloca(32);
+      ecif.rvalue = alloca (32);
     }
   else
     ecif.rvalue = rvalue;
 
-  switch (cif->abi) 
+  switch (cif->abi)
     {
     case FFI_SYSV:
       ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
@@ -346,30 +356,30 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 #endif
 
     default:
-      FFI_ASSERT(0);
+      FFI_ASSERT (0);
       break;
     }
   if (small_struct)
     {
-      FFI_ASSERT(rvalue != NULL);
+      FFI_ASSERT (rvalue != NULL);
       memcpy (rvalue, &temp, cif->rtype->size);
     }
-    
   else if (vfp_struct)
     {
-      FFI_ASSERT(rvalue != NULL);
+      FFI_ASSERT (rvalue != NULL);
       memcpy (rvalue, ecif.rvalue, cif->rtype->size);
     }
-    
 }
 
 /** private members **/
 
 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
-					 void** args, ffi_cif* cif, float *vfp_stack);
+					 void **args, ffi_cif *cif,
+					 float *vfp_stack);
 
 static void ffi_prep_incoming_args_VFP (char *stack, void **ret,
-					 void** args, ffi_cif* cif, float *vfp_stack);
+					void **args, ffi_cif *cif,
+					float *vfp_stack);
 
 void ffi_closure_SYSV (ffi_closure *);
 
@@ -378,25 +388,25 @@ void ffi_closure_VFP (ffi_closure *);
 /* This function is jumped to by the trampoline */
 
 unsigned int FFI_HIDDEN
-ffi_closure_inner (ffi_closure *closure, 
+ffi_closure_inner (ffi_closure *closure,
 		   void **respp, void *args, void *vfp_args)
 {
   // our various things...
-  ffi_cif       *cif;
-  void         **arg_area;
+  ffi_cif *cif;
+  void **arg_area;
 
-  cif         = closure->cif;
-  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+  cif = closure->cif;
+  arg_area = (void **) alloca (cif->nargs * sizeof (void *));
 
   /* this call will initialize ARG_AREA, such that each
-   * element in that array points to the corresponding 
+   * element in that array points to the corresponding
    * value on the stack; and if the function returns
    * a structure, it will re-set RESP to point to the
    * structure return address.  */
   if (cif->abi == FFI_VFP)
-    ffi_prep_incoming_args_VFP(args, respp, arg_area, cif, vfp_args);
+    ffi_prep_incoming_args_VFP (args, respp, arg_area, cif, vfp_args);
   else
-    ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
+    ffi_prep_incoming_args_SYSV (args, respp, arg_area, cif, vfp_args);
 
   (closure->fun) (cif, *respp, arg_area, closure->user_data);
 
@@ -404,11 +414,11 @@ ffi_closure_inner (ffi_closure *closure,
 }
 
 /*@-exportheader@*/
-static void 
-ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
-			    void **avalue, ffi_cif *cif,
-			    /* Used only under VFP hard-float ABI. */
-			    float *vfp_stack)
+static void
+ffi_prep_incoming_args_SYSV (char *stack, void **rvalue,
+			     void **avalue, ffi_cif *cif,
+			     /* Used only under VFP hard-float ABI. */
+			     float *vfp_stack)
 /*@=exportheader@*/
 {
   register unsigned int i;
@@ -418,10 +428,11 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
 
   argp = stack;
 
-  if ( cif->flags == FFI_TYPE_STRUCT ) {
-    *rvalue = *(void **) argp;
-    argp += 4;
-  }
+  if (cif->flags == FFI_TYPE_STRUCT)
+    {
+      *rvalue = *(void **) argp;
+      argp += 4;
+    }
 
   p_argv = avalue;
 
@@ -429,25 +440,25 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
     {
       size_t z;
 
-      argp = ffi_align(p_arg, argp);
+      argp = ffi_align (p_arg, argp);
 
       z = (*p_arg)->size;
 
       /* because we're little endian, this is what it turns into.   */
 
-      *p_argv = (void*) argp;
+      *p_argv = (void *) argp;
 
       p_argv++;
       argp += z;
     }
-  
+
   return;
 }
 
 /*@-exportheader@*/
-static void 
-ffi_prep_incoming_args_VFP(char *stack, void **rvalue,
-			    void **avalue, ffi_cif *cif,
+static void
+ffi_prep_incoming_args_VFP (char *stack, void **rvalue,
+			    void **avalue, ffi_cif * cif,
 			    /* Used only under VFP hard-float ABI. */
 			    float *vfp_stack)
 /*@=exportheader@*/
@@ -460,76 +471,77 @@ ffi_prep_incoming_args_VFP(char *stack, void **rvalue,
   char stack_used = 0;
   char is_vfp_type;
 
-  FFI_ASSERT(cif->abi == FFI_VFP);
+  FFI_ASSERT (cif->abi == FFI_VFP);
   regp = stack;
   eo_regp = argp = regp + 16;
 
-  if ( cif->flags == FFI_TYPE_STRUCT ) {
-    *rvalue = *(void **) regp;
-    regp += 4;
-  }
+  if (cif->flags == FFI_TYPE_STRUCT)
+    {
+      *rvalue = *(void **) regp;
+      regp += 4;
+    }
 
   p_argv = avalue;
 
   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
     {
-    size_t z;
-    is_vfp_type = vfp_type_p (*p_arg); 
+      size_t z;
+      is_vfp_type = vfp_type_p (*p_arg);
 
-    if(vi < cif->vfp_nargs && is_vfp_type)
-      {
-        *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
-        continue;
-      }
-    else if (!done_with_regs && !is_vfp_type)
-      {
-        char* tregp = ffi_align(p_arg, regp);
-
-        z = (*p_arg)->size; 
-        z = (z < 4)? 4 : z; // pad
-        
-        /* if the arguments either fits into the registers or uses registers
-         * and stack, while we haven't read other things from the stack */
-        if(tregp + z <= eo_regp || !stack_used) 
-          {
-          /* because we're little endian, this is what it turns into. */
-          *p_argv = (void*) tregp;
-
-          p_argv++;
-          regp = tregp + z;
-          // if we read past the last core register, make sure we have not read
-          // from the stack before and continue reading after regp
-          if(regp > eo_regp)
-            {
-            if(stack_used)
-              {
-                abort(); // we should never read past the end of the register
-                         // are if the stack is already in use
-              }
-            argp = regp;
-            }
-          if(regp >= eo_regp)
-            {
-            done_with_regs = 1;
-            stack_used = 1;
-            }
-          continue;
-          }
-      }
-    stack_used = 1;
+      if (vi < cif->vfp_nargs && is_vfp_type)
+	{
+	  *p_argv++ = (void *) (vfp_stack + cif->vfp_args[vi++]);
+	  continue;
+	}
+      else if (!done_with_regs && !is_vfp_type)
+	{
+	  char *tregp = ffi_align (p_arg, regp);
+
+	  z = (*p_arg)->size;
+	  z = (z < 4) ? 4 : z;	// pad
+
+	  /* if the arguments either fits into the registers or uses registers
+	   * and stack, while we haven't read other things from the stack */
+	  if (tregp + z <= eo_regp || !stack_used)
+	    {
+	      /* because we're little endian, this is what it turns into. */
+	      *p_argv = (void *) tregp;
+
+	      p_argv++;
+	      regp = tregp + z;
+	      // if we read past the last core register, make sure we have not read
+	      // from the stack before and continue reading after regp
+	      if (regp > eo_regp)
+		{
+		  if (stack_used)
+		    {
+		      abort ();	// we should never read past the end of the register
+		      // are if the stack is already in use
+		    }
+		  argp = regp;
+		}
+	      if (regp >= eo_regp)
+		{
+		  done_with_regs = 1;
+		  stack_used = 1;
+		}
+	      continue;
+	    }
+	}
+      stack_used = 1;
 
-    argp = ffi_align(p_arg, argp);
+      argp = ffi_align (p_arg, argp);
 
-    z = (*p_arg)->size;
+      z = (*p_arg)->size;
 
-    /* because we're little endian, this is what it turns into.   */
+      /* because we're little endian, this is what it turns into.   */
 
-    *p_argv = (void*) argp;
+      *p_argv = (void *) argp;
 
-    p_argv++;
-    argp += z;
+      p_argv++;
+      argp += z;
     }
-  
+
   return;
 }
 
@@ -549,7 +561,8 @@ 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 {
+struct ffi_trampoline_table
+{
   /* contiguous writable and executable pages */
   vm_address_t config_page;
   vm_address_t trampoline_page;
@@ -563,8 +576,9 @@ struct ffi_trampoline_table {
   ffi_trampoline_table *next;
 };
 
-struct ffi_trampoline_table_entry {
-  void *(*trampoline)();
+struct ffi_trampoline_table_entry
+{
+  void *(*trampoline) ();
   ffi_trampoline_table_entry *next;
 };
 
@@ -591,62 +605,79 @@ ffi_trampoline_table_alloc ()
   ffi_trampoline_table *table = NULL;
 
   /* Loop until we can allocate two contiguous 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;
-    }
+  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;
-    }
+      /* 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;
+      /* 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);
+      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__);
-      }
+      /* 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;
-    }
+	  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;
+      /* 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));
+      /* 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));
+      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];
-    }
+	  if (i < table->free_count - 1)
+	    entry->next = &table->free_list_pool[i + 1];
+	}
 
-    table->free_list = table->free_list_pool;
-  }
+      table->free_list = table->free_list_pool;
+    }
 
   return table;
 }
@@ -655,28 +686,30 @@ void *
 ffi_closure_alloc (size_t size, void **code)
 {
   /* Create the closure */
-  ffi_closure *closure = malloc(size);
+  ffi_closure *closure = malloc (size);
   if (closure == NULL)
     return NULL;
 
-  pthread_mutex_lock(&ffi_trampoline_lock);
+  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;
-    }
+  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;
+      /* 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;
-  }
+      ffi_trampoline_tables = table;
+    }
 
   /* Claim the free entry */
   ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
@@ -684,7 +717,7 @@ ffi_closure_alloc (size_t size, void **code)
   ffi_trampoline_tables->free_count--;
   entry->next = NULL;
 
-  pthread_mutex_unlock(&ffi_trampoline_lock);
+  pthread_mutex_unlock (&ffi_trampoline_lock);
 
   /* Initialize the return values */
   *code = entry->trampoline;
@@ -699,7 +732,7 @@ ffi_closure_free (void *ptr)
 {
   ffi_closure *closure = ptr;
 
-  pthread_mutex_lock(&ffi_trampoline_lock);
+  pthread_mutex_lock (&ffi_trampoline_lock);
 
   /* Fetch the table and entry references */
   ffi_trampoline_table *table = closure->trampoline_table;
@@ -712,36 +745,43 @@ ffi_closure_free (void *ptr)
 
   /* 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;
-  }
+  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);
 
@@ -770,13 +810,12 @@ ffi_closure_free (void *ptr)
 /* the cif must already be prep'ed */
 
 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_prep_closure_loc (ffi_closure * closure,
+		      ffi_cif * cif,
+		      void (*fun) (ffi_cif *, void *, void **, void *),
+		      void *user_data, void *codeloc)
 {
-  void (*closure_func)(ffi_closure*) = NULL;
+  void (*closure_func) (ffi_closure *) = NULL;
 
   if (cif->abi == FFI_SYSV)
     closure_func = &ffi_closure_SYSV;
@@ -788,25 +827,24 @@ ffi_prep_closure_loc (ffi_closure* closure,
     return FFI_BAD_ABI;
 
 #if FFI_EXEC_TRAMPOLINE_TABLE
-  void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
+  void **config = FFI_TRAMPOLINE_CODELOC_CONFIG (codeloc);
   config[0] = closure;
   config[1] = closure_func;
 #else
-  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
-		       closure_func,  \
-		       codeloc);
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], closure_func, codeloc);
 #endif
 
-  closure->cif  = cif;
+  closure->cif = cif;
   closure->user_data = user_data;
-  closure->fun  = fun;
+  closure->fun = fun;
 
   return FFI_OK;
 }
 
 /* Below are routines for VFP hard-float support. */
 
-static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
+static int
+rec_vfp_type_p (ffi_type * t, int *elt, int *elnum)
 {
   switch (t->type)
     {
@@ -833,7 +871,7 @@ static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
 	while (*el)
 	  {
 	    int el_elt = 0, el_elnum = 0;
-	    if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
+	    if (!rec_vfp_type_p (*el, &el_elt, &el_elnum)
 		|| (base_elt && base_elt != el_elt)
 		|| total_elnum + el_elnum > 4)
 	      return 0;
@@ -845,12 +883,13 @@ static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
 	*elt = base_elt;
 	return 1;
       }
-    default: ;
+    default:;
     }
   return 0;
 }
 
-static int vfp_type_p (ffi_type *t)
+static int
+vfp_type_p (ffi_type * t)
 {
   int elt, elnum;
   if (rec_vfp_type_p (t, &elt, &elnum))
@@ -869,7 +908,8 @@ static int vfp_type_p (ffi_type *t)
   return 0;
 }
 
-static int place_vfp_arg (ffi_cif *cif, ffi_type *t)
+static int
+place_vfp_arg (ffi_cif * cif, ffi_type * t)
 {
   short reg = cif->vfp_reg_free;
   int nregs = t->size / sizeof (float);
@@ -903,7 +943,7 @@ static int place_vfp_arg (ffi_cif *cif, ffi_type *t)
 	  cif->vfp_reg_free = reg;
 	}
       return 0;
-    next_reg: ;
+    next_reg:;
     }
   // done, mark all regs as used
   cif->vfp_reg_free = 16;
@@ -911,21 +951,22 @@ static int place_vfp_arg (ffi_cif *cif, ffi_type *t)
   return 1;
 }
 
-static void layout_vfp_args (ffi_cif *cif)
+static void
+layout_vfp_args (ffi_cif * cif)
 {
   int i;
   /* Init VFP fields */
   cif->vfp_used = 0;
   cif->vfp_nargs = 0;
   cif->vfp_reg_free = 0;
-  memset (cif->vfp_args, -1, 16); /* Init to -1. */
+  memset (cif->vfp_args, -1, 16);	/* Init to -1. */
 
   for (i = 0; i < cif->nargs; i++)
     {
       ffi_type *t = cif->arg_types[i];
       if (vfp_type_p (t) && place_vfp_arg (cif, t) == 1)
-        {
-          break;
-        }
+	{
+	  break;
+	}
     }
 }
-- 
1.9.3

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-10-29 20:06 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
2014-10-29 20:06 ` [PATCH 07/10] arm: Remove internal FFI_TYPE constants Richard Henderson
2014-10-29 20:06 ` [PATCH 03/10] arm: Deref ffi_put_arg arguments Richard Henderson
2014-10-29 20:06 ` [PATCH 04/10] arm: Rewrite vfp_type_p Richard Henderson
2014-10-29 20:06 ` [PATCH 05/10] arm: Rewrite ffi_call Richard Henderson
2014-10-29 20:06 ` [PATCH 08/10] arm: Add support for complex types Richard Henderson
2014-10-29 20:06 ` [PATCH 02/10] arm: Deref ffi_align argument Richard Henderson
2014-10-29 20:06 ` [PATCH 10/10] arm: Add support for Go closures Richard Henderson
2014-10-29 20:06 ` [PATCH 01/10] arm: Reindent arm/ffi.c Richard Henderson
2014-10-29 20:06 ` [PATCH 09/10] arm: Add argument space for the hidden struct return pointer Richard Henderson
2014-10-29 20:06 ` [PATCH 06/10] arm: Rewrite ffi_closure Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).