(root)/
gcc-13.2.0/
libffi/
src/
arm/
ffi.c
       1  /* -----------------------------------------------------------------------
       2     ffi.c - Copyright (c) 2011 Timothy Wall
       3             Copyright (c) 2011 Plausible Labs Cooperative, Inc.
       4             Copyright (c) 2011 Anthony Green
       5  	   Copyright (c) 2011 Free Software Foundation
       6             Copyright (c) 1998, 2008, 2011  Red Hat, Inc.
       7  
       8     ARM Foreign Function Interface
       9  
      10     Permission is hereby granted, free of charge, to any person obtaining
      11     a copy of this software and associated documentation files (the
      12     ``Software''), to deal in the Software without restriction, including
      13     without limitation the rights to use, copy, modify, merge, publish,
      14     distribute, sublicense, and/or sell copies of the Software, and to
      15     permit persons to whom the Software is furnished to do so, subject to
      16     the following conditions:
      17  
      18     The above copyright notice and this permission notice shall be included
      19     in all copies or substantial portions of the Software.
      20  
      21     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
      22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      24     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      25     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      26     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      27     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28     DEALINGS IN THE SOFTWARE.
      29     ----------------------------------------------------------------------- */
      30  
      31  #if defined(__arm__) || defined(_M_ARM)
      32  #include <fficonfig.h>
      33  #include <ffi.h>
      34  #include <ffi_common.h>
      35  #include <stdint.h>
      36  #include <stdlib.h>
      37  #include <tramp.h>
      38  #include "internal.h"
      39  
      40  #if defined(_WIN32)
      41  #define WIN32_LEAN_AND_MEAN
      42  #include <windows.h>
      43  #endif
      44  
      45  #if FFI_EXEC_TRAMPOLINE_TABLE
      46  
      47  #ifdef __MACH__
      48  #include <mach/machine/vm_param.h>
      49  #endif
      50  
      51  #else
      52  #ifndef _WIN32
      53  extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
      54  #else
      55  // Declare this as an array of char, instead of array of int,
      56  // otherwise Clang optimizes out the "& 0xFFFFFFFE" for clearing
      57  // the thumb bit.
      58  extern unsigned char ffi_arm_trampoline[12] FFI_HIDDEN;
      59  #endif
      60  #endif
      61  
      62  #if defined(__FreeBSD__) && defined(__arm__)
      63  #include <sys/types.h>
      64  #include <machine/sysarch.h>
      65  #endif
      66  
      67  /* Forward declares. */
      68  static int vfp_type_p (const ffi_type *);
      69  static void layout_vfp_args (ffi_cif *);
      70  
      71  static void *
      72  ffi_align (ffi_type *ty, void *p)
      73  {
      74    /* Align if necessary */
      75    size_t alignment;
      76  #ifdef _WIN32_WCE
      77    alignment = 4;
      78  #else
      79    alignment = ty->alignment;
      80    if (alignment < 4)
      81      alignment = 4;
      82  #endif
      83    return (void *) FFI_ALIGN (p, alignment);
      84  }
      85  
      86  static size_t
      87  ffi_put_arg (ffi_type *ty, void *src, void *dst)
      88  {
      89    size_t z = ty->size;
      90  
      91    switch (ty->type)
      92      {
      93      case FFI_TYPE_SINT8:
      94        *(UINT32 *)dst = *(SINT8 *)src;
      95        break;
      96      case FFI_TYPE_UINT8:
      97        *(UINT32 *)dst = *(UINT8 *)src;
      98        break;
      99      case FFI_TYPE_SINT16:
     100        *(UINT32 *)dst = *(SINT16 *)src;
     101        break;
     102      case FFI_TYPE_UINT16:
     103        *(UINT32 *)dst = *(UINT16 *)src;
     104        break;
     105  
     106      case FFI_TYPE_INT:
     107      case FFI_TYPE_SINT32:
     108      case FFI_TYPE_UINT32:
     109      case FFI_TYPE_POINTER:
     110  #ifndef _WIN32
     111      case FFI_TYPE_FLOAT:
     112  #endif
     113        *(UINT32 *)dst = *(UINT32 *)src;
     114        break;
     115  
     116  #ifdef _WIN32
     117      // casting a float* to a UINT32* doesn't work on Windows
     118      case FFI_TYPE_FLOAT:
     119          *(uintptr_t *)dst = 0;
     120          *(float *)dst = *(float *)src;
     121          break;
     122  #endif
     123  
     124      case FFI_TYPE_SINT64:
     125      case FFI_TYPE_UINT64:
     126      case FFI_TYPE_DOUBLE:
     127        *(UINT64 *)dst = *(UINT64 *)src;
     128        break;
     129  
     130      case FFI_TYPE_STRUCT:
     131      case FFI_TYPE_COMPLEX:
     132        memcpy (dst, src, z);
     133        break;
     134  
     135      default:
     136        abort();
     137      }
     138  
     139    return FFI_ALIGN (z, 4);
     140  }
     141  
     142  /* ffi_prep_args is called once stack space has been allocated
     143     for the function's arguments.
     144  
     145     The vfp_space parameter is the load area for VFP regs, the return
     146     value is cif->vfp_used (word bitset of VFP regs used for passing
     147     arguments). These are only used for the VFP hard-float ABI.
     148  */
     149  static void
     150  ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
     151  		    void **avalue, char *argp)
     152  {
     153    ffi_type **arg_types = cif->arg_types;
     154    int i, n;
     155  
     156    if (flags == ARM_TYPE_STRUCT)
     157      {
     158        *(void **) argp = rvalue;
     159        argp += 4;
     160      }
     161  
     162    for (i = 0, n = cif->nargs; i < n; i++)
     163      {
     164        ffi_type *ty = arg_types[i];
     165        argp = ffi_align (ty, argp);
     166        argp += ffi_put_arg (ty, avalue[i], argp);
     167      }
     168  }
     169  
     170  static void
     171  ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
     172                     void **avalue, char *stack, char *vfp_space)
     173  {
     174    ffi_type **arg_types = cif->arg_types;
     175    int i, n, vi = 0;
     176    char *argp, *regp, *eo_regp;
     177    char stack_used = 0;
     178    char done_with_regs = 0;
     179  
     180    /* The first 4 words on the stack are used for values
     181       passed in core registers.  */
     182    regp = stack;
     183    eo_regp = argp = regp + 16;
     184  
     185    /* If the function returns an FFI_TYPE_STRUCT in memory,
     186       that address is passed in r0 to the function.  */
     187    if (flags == ARM_TYPE_STRUCT)
     188      {
     189        *(void **) regp = rvalue;
     190        regp += 4;
     191      }
     192  
     193    for (i = 0, n = cif->nargs; i < n; i++)
     194      {
     195        ffi_type *ty = arg_types[i];
     196        void *a = avalue[i];
     197        int is_vfp_type = vfp_type_p (ty);
     198  
     199        /* Allocated in VFP registers. */
     200        if (vi < cif->vfp_nargs && is_vfp_type)
     201  	{
     202  	  char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4;
     203  	  ffi_put_arg (ty, a, vfp_slot);
     204  	  continue;
     205  	}
     206        /* Try allocating in core registers. */
     207        else if (!done_with_regs && !is_vfp_type)
     208  	{
     209  	  char *tregp = ffi_align (ty, regp);
     210  	  size_t size = ty->size;
     211  	  size = (size < 4) ? 4 : size;	// pad
     212  	  /* Check if there is space left in the aligned register
     213  	     area to place the argument.  */
     214  	  if (tregp + size <= eo_regp)
     215  	    {
     216  	      regp = tregp + ffi_put_arg (ty, a, tregp);
     217  	      done_with_regs = (regp == argp);
     218  	      // ensure we did not write into the stack area
     219  	      FFI_ASSERT (regp <= argp);
     220  	      continue;
     221  	    }
     222  	  /* In case there are no arguments in the stack area yet,
     223  	     the argument is passed in the remaining core registers
     224  	     and on the stack.  */
     225  	  else if (!stack_used)
     226  	    {
     227  	      stack_used = 1;
     228  	      done_with_regs = 1;
     229  	      argp = tregp + ffi_put_arg (ty, a, tregp);
     230  	      FFI_ASSERT (eo_regp < argp);
     231  	      continue;
     232  	    }
     233  	}
     234        /* Base case, arguments are passed on the stack */
     235        stack_used = 1;
     236        argp = ffi_align (ty, argp);
     237        argp += ffi_put_arg (ty, a, argp);
     238      }
     239  }
     240  
     241  /* Perform machine dependent cif processing */
     242  ffi_status FFI_HIDDEN
     243  ffi_prep_cif_machdep (ffi_cif *cif)
     244  {
     245    int flags = 0, cabi = cif->abi;
     246    size_t bytes = cif->bytes;
     247  
     248    /* Map out the register placements of VFP register args.  The VFP
     249       hard-float calling conventions are slightly more sophisticated
     250       than the base calling conventions, so we do it here instead of
     251       in ffi_prep_args(). */
     252    if (cabi == FFI_VFP)
     253      layout_vfp_args (cif);
     254  
     255    /* Set the return type flag */
     256    switch (cif->rtype->type)
     257      {
     258      case FFI_TYPE_VOID:
     259        flags = ARM_TYPE_VOID;
     260        break;
     261  
     262      case FFI_TYPE_INT:
     263      case FFI_TYPE_UINT8:
     264      case FFI_TYPE_SINT8:
     265      case FFI_TYPE_UINT16:
     266      case FFI_TYPE_SINT16:
     267      case FFI_TYPE_UINT32:
     268      case FFI_TYPE_SINT32:
     269      case FFI_TYPE_POINTER:
     270        flags = ARM_TYPE_INT;
     271        break;
     272  
     273      case FFI_TYPE_SINT64:
     274      case FFI_TYPE_UINT64:
     275        flags = ARM_TYPE_INT64;
     276        break;
     277  
     278      case FFI_TYPE_FLOAT:
     279        flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT);
     280        break;
     281      case FFI_TYPE_DOUBLE:
     282        flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64);
     283        break;
     284  
     285      case FFI_TYPE_STRUCT:
     286      case FFI_TYPE_COMPLEX:
     287        if (cabi == FFI_VFP)
     288  	{
     289  	  int h = vfp_type_p (cif->rtype);
     290  
     291  	  flags = ARM_TYPE_VFP_N;
     292  	  if (h == 0x100 + FFI_TYPE_FLOAT)
     293  	    flags = ARM_TYPE_VFP_S;
     294  	  if (h == 0x100 + FFI_TYPE_DOUBLE)
     295  	    flags = ARM_TYPE_VFP_D;
     296  	  if (h != 0)
     297  	      break;
     298  	}
     299  
     300        /* A Composite Type not larger than 4 bytes is returned in r0.
     301  	 A Composite Type larger than 4 bytes, or whose size cannot
     302  	 be determined statically ... is stored in memory at an
     303  	 address passed [in r0].  */
     304        if (cif->rtype->size <= 4)
     305  	flags = ARM_TYPE_INT;
     306        else
     307  	{
     308  	  flags = ARM_TYPE_STRUCT;
     309  	  bytes += 4;
     310  	}
     311        break;
     312  
     313      default:
     314        abort();
     315      }
     316  
     317    /* Round the stack up to a multiple of 8 bytes.  This isn't needed
     318       everywhere, but it is on some platforms, and it doesn't harm anything
     319       when it isn't needed.  */
     320    bytes = FFI_ALIGN (bytes, 8);
     321  
     322    /* Minimum stack space is the 4 register arguments that we pop.  */
     323    if (bytes < 4*4)
     324      bytes = 4*4;
     325  
     326    cif->bytes = bytes;
     327    cif->flags = flags;
     328  
     329    return FFI_OK;
     330  }
     331  
     332  /* Perform machine dependent cif processing for variadic calls */
     333  ffi_status FFI_HIDDEN
     334  ffi_prep_cif_machdep_var (ffi_cif * cif,
     335  			  unsigned int nfixedargs, unsigned int ntotalargs)
     336  {
     337    /* VFP variadic calls actually use the SYSV ABI */
     338    if (cif->abi == FFI_VFP)
     339      cif->abi = FFI_SYSV;
     340  
     341    return ffi_prep_cif_machdep (cif);
     342  }
     343  
     344  /* Prototypes for assembly functions, in sysv.S.  */
     345  
     346  struct call_frame
     347  {
     348    void *fp;
     349    void *lr;
     350    void *rvalue;
     351    int flags;
     352    void *closure;
     353  };
     354  
     355  extern void ffi_call_SYSV (void *stack, struct call_frame *,
     356  			   void (*fn) (void)) FFI_HIDDEN;
     357  extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
     358  			   void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
     359  
     360  static void
     361  ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
     362  	      void **avalue, void *closure)
     363  {
     364    int flags = cif->flags;
     365    ffi_type *rtype = cif->rtype;
     366    size_t bytes, rsize, vfp_size;
     367    char *stack, *vfp_space, *new_rvalue;
     368    struct call_frame *frame;
     369  
     370    rsize = 0;
     371    if (rvalue == NULL)
     372      {
     373        /* If the return value is a struct and we don't have a return
     374  	 value address then we need to make one.  Otherwise the return
     375  	 value is in registers and we can ignore them.  */
     376        if (flags == ARM_TYPE_STRUCT)
     377  	rsize = rtype->size;
     378        else
     379  	flags = ARM_TYPE_VOID;
     380      }
     381    else if (flags == ARM_TYPE_VFP_N)
     382      {
     383        /* Largest case is double x 4. */
     384        rsize = 32;
     385      }
     386    else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
     387      rsize = 4;
     388  
     389    /* Largest case.  */
     390    vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);
     391  
     392    bytes = cif->bytes;
     393    stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
     394  
     395    vfp_space = NULL;
     396    if (vfp_size)
     397      {
     398        vfp_space = stack;
     399        stack += vfp_size;
     400      }
     401  
     402    frame = (struct call_frame *)(stack + bytes);
     403  
     404    new_rvalue = rvalue;
     405    if (rsize)
     406      new_rvalue = (void *)(frame + 1);
     407  
     408    frame->rvalue = new_rvalue;
     409    frame->flags = flags;
     410    frame->closure = closure;
     411  
     412    if (vfp_space)
     413      {
     414        ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
     415        ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
     416      }
     417    else
     418      {
     419        ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
     420        ffi_call_SYSV (stack, frame, fn);
     421      }
     422  
     423    if (rvalue && rvalue != new_rvalue)
     424      memcpy (rvalue, new_rvalue, rtype->size);
     425  }
     426  
     427  void
     428  ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
     429  {
     430    ffi_call_int (cif, fn, rvalue, avalue, NULL);
     431  }
     432  
     433  #ifdef FFI_GO_CLOSURES
     434  void
     435  ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
     436  	     void **avalue, void *closure)
     437  {
     438    ffi_call_int (cif, fn, rvalue, avalue, closure);
     439  }
     440  #endif
     441  
     442  static void *
     443  ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
     444  			     char *argp, void **avalue)
     445  {
     446    ffi_type **arg_types = cif->arg_types;
     447    int i, n;
     448  
     449    if (cif->flags == ARM_TYPE_STRUCT)
     450      {
     451        rvalue = *(void **) argp;
     452        argp += 4;
     453      }
     454    else
     455      {
     456        if (cif->rtype->size && cif->rtype->size < 4)
     457          *(uint32_t *) rvalue = 0;
     458      }
     459  
     460    for (i = 0, n = cif->nargs; i < n; i++)
     461      {
     462        ffi_type *ty = arg_types[i];
     463        size_t z = ty->size;
     464  
     465        argp = ffi_align (ty, argp);
     466        avalue[i] = (void *) argp;
     467        argp += z;
     468      }
     469  
     470    return rvalue;
     471  }
     472  
     473  static void *
     474  ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
     475  			    char *vfp_space, void **avalue)
     476  {
     477    ffi_type **arg_types = cif->arg_types;
     478    int i, n, vi = 0;
     479    char *argp, *regp, *eo_regp;
     480    char done_with_regs = 0;
     481    char stack_used = 0;
     482  
     483    regp = stack;
     484    eo_regp = argp = regp + 16;
     485  
     486    if (cif->flags == ARM_TYPE_STRUCT)
     487      {
     488        rvalue = *(void **) regp;
     489        regp += 4;
     490      }
     491  
     492    for (i = 0, n = cif->nargs; i < n; i++)
     493      {
     494        ffi_type *ty = arg_types[i];
     495        int is_vfp_type = vfp_type_p (ty);
     496        size_t z = ty->size;
     497  
     498        if (vi < cif->vfp_nargs && is_vfp_type)
     499  	{
     500  	  avalue[i] = vfp_space + cif->vfp_args[vi++] * 4;
     501  	  continue;
     502  	}
     503        else if (!done_with_regs && !is_vfp_type)
     504  	{
     505  	  char *tregp = ffi_align (ty, regp);
     506  
     507  	  z = (z < 4) ? 4 : z;	// pad
     508  
     509  	  /* If the arguments either fits into the registers or uses registers
     510  	     and stack, while we haven't read other things from the stack */
     511  	  if (tregp + z <= eo_regp || !stack_used)
     512  	    {
     513  	      /* Because we're little endian, this is what it turns into.  */
     514  	      avalue[i] = (void *) tregp;
     515  	      regp = tregp + z;
     516  
     517  	      /* If we read past the last core register, make sure we
     518  		 have not read from the stack before and continue
     519  		 reading after regp.  */
     520  	      if (regp > eo_regp)
     521  		{
     522  		  FFI_ASSERT (!stack_used);
     523  		  argp = regp;
     524  		}
     525  	      if (regp >= eo_regp)
     526  		{
     527  		  done_with_regs = 1;
     528  		  stack_used = 1;
     529  		}
     530  	      continue;
     531  	    }
     532  	}
     533  
     534        stack_used = 1;
     535        argp = ffi_align (ty, argp);
     536        avalue[i] = (void *) argp;
     537        argp += z;
     538      }
     539  
     540    return rvalue;
     541  }
     542  
     543  #if FFI_CLOSURES
     544  
     545  struct closure_frame
     546  {
     547    char vfp_space[8*8] __attribute__((aligned(8)));
     548    char result[8*4];
     549    char argp[];
     550  };
     551  
     552  int FFI_HIDDEN
     553  ffi_closure_inner_SYSV (ffi_cif *cif,
     554  		        void (*fun) (ffi_cif *, void *, void **, void *),
     555  		        void *user_data,
     556  		        struct closure_frame *frame)
     557  {
     558    void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
     559    void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
     560  					      frame->argp, avalue);
     561    fun (cif, rvalue, avalue, user_data);
     562    return cif->flags;
     563  }
     564  
     565  int FFI_HIDDEN
     566  ffi_closure_inner_VFP (ffi_cif *cif,
     567  		       void (*fun) (ffi_cif *, void *, void **, void *),
     568  		       void *user_data,
     569  		       struct closure_frame *frame)
     570  {
     571    void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
     572    void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
     573  					     frame->vfp_space, avalue);
     574    fun (cif, rvalue, avalue, user_data);
     575    return cif->flags;
     576  }
     577  
     578  void ffi_closure_SYSV (void) FFI_HIDDEN;
     579  void ffi_closure_VFP (void) FFI_HIDDEN;
     580  #if defined(FFI_EXEC_STATIC_TRAMP)
     581  void ffi_closure_SYSV_alt (void) FFI_HIDDEN;
     582  void ffi_closure_VFP_alt (void) FFI_HIDDEN;
     583  #endif
     584  
     585  #ifdef FFI_GO_CLOSURES
     586  void ffi_go_closure_SYSV (void) FFI_HIDDEN;
     587  void ffi_go_closure_VFP (void) FFI_HIDDEN;
     588  #endif
     589  
     590  /* the cif must already be prep'ed */
     591  
     592  #if defined(__FreeBSD__) && defined(__arm__)
     593  #define __clear_cache(start, end) do { \
     594  		struct arm_sync_icache_args ua; 		\
     595  								\
     596  		ua.addr = (uintptr_t)(start);			\
     597  		ua.len = (char *)(end) - (char *)start;		\
     598  		sysarch(ARM_SYNC_ICACHE, &ua);			\
     599  	} while (0);
     600  #endif
     601  
     602  ffi_status
     603  ffi_prep_closure_loc (ffi_closure * closure,
     604  		      ffi_cif * cif,
     605  		      void (*fun) (ffi_cif *, void *, void **, void *),
     606  		      void *user_data, void *codeloc)
     607  {
     608    void (*closure_func) (void) = ffi_closure_SYSV;
     609  
     610    if (cif->abi == FFI_VFP)
     611      {
     612        /* We only need take the vfp path if there are vfp arguments.  */
     613        if (cif->vfp_used)
     614  	closure_func = ffi_closure_VFP;
     615      }
     616    else if (cif->abi != FFI_SYSV)
     617      return FFI_BAD_ABI;
     618  
     619  #if FFI_EXEC_TRAMPOLINE_TABLE
     620    void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
     621    config[0] = closure;
     622    config[1] = closure_func;
     623  #else
     624  
     625  #if defined(FFI_EXEC_STATIC_TRAMP)
     626    if (ffi_tramp_is_present(closure))
     627      {
     628        /* Initialize the static trampoline's parameters. */
     629        if (closure_func == ffi_closure_SYSV)
     630          closure_func = ffi_closure_SYSV_alt;
     631        else
     632          closure_func = ffi_closure_VFP_alt;
     633        ffi_tramp_set_parms (closure->ftramp, closure_func, closure);
     634        goto out;
     635      }
     636  #endif
     637  
     638    /* Initialize the dynamic trampoline. */
     639  #ifndef _WIN32
     640    memcpy(closure->tramp, ffi_arm_trampoline, 8);
     641  #else
     642    // cast away function type so MSVC doesn't set the lower bit of the function pointer
     643    memcpy(closure->tramp, (void*)((uintptr_t)ffi_arm_trampoline & 0xFFFFFFFE), FFI_TRAMPOLINE_CLOSURE_OFFSET);
     644  #endif
     645  
     646  #if defined (__QNX__)
     647    msync(closure->tramp, 8, 0x1000000);	/* clear data map */
     648    msync(codeloc, 8, 0x1000000);	/* clear insn map */
     649  #elif defined(_WIN32)
     650    FlushInstructionCache(GetCurrentProcess(), closure->tramp, FFI_TRAMPOLINE_SIZE);
     651  #else
     652    __clear_cache(closure->tramp, closure->tramp + 8);	/* clear data map */
     653    __clear_cache(codeloc, codeloc + 8);			/* clear insn map */
     654  #endif
     655  #ifdef _WIN32
     656    *(void(**)(void))(closure->tramp + FFI_TRAMPOLINE_CLOSURE_FUNCTION) = closure_func;
     657  #else
     658    *(void (**)(void))(closure->tramp + 8) = closure_func;
     659  #endif
     660  out:
     661  #endif
     662  
     663    closure->cif = cif;
     664    closure->fun = fun;
     665    closure->user_data = user_data;
     666  
     667    return FFI_OK;
     668  }
     669  
     670  #ifdef FFI_GO_CLOSURES
     671  ffi_status
     672  ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
     673  		     void (*fun) (ffi_cif *, void *, void **, void *))
     674  {
     675    void (*closure_func) (void) = ffi_go_closure_SYSV;
     676  
     677    if (cif->abi == FFI_VFP)
     678      {
     679        /* We only need take the vfp path if there are vfp arguments.  */
     680        if (cif->vfp_used)
     681  	closure_func = ffi_go_closure_VFP;
     682      }
     683    else if (cif->abi != FFI_SYSV)
     684      return FFI_BAD_ABI;
     685  
     686    closure->tramp = closure_func;
     687    closure->cif = cif;
     688    closure->fun = fun;
     689  
     690    return FFI_OK;
     691  }
     692  #endif
     693  
     694  #endif /* FFI_CLOSURES */
     695  
     696  /* Below are routines for VFP hard-float support. */
     697  
     698  /* A subroutine of vfp_type_p.  Given a structure type, return the type code
     699     of the first non-structure element.  Recurse for structure elements.
     700     Return -1 if the structure is in fact empty, i.e. no nested elements.  */
     701  
     702  static int
     703  is_hfa0 (const ffi_type *ty)
     704  {
     705    ffi_type **elements = ty->elements;
     706    int i, ret = -1;
     707  
     708    if (elements != NULL)
     709      for (i = 0; elements[i]; ++i)
     710        {
     711          ret = elements[i]->type;
     712          if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
     713            {
     714              ret = is_hfa0 (elements[i]);
     715              if (ret < 0)
     716                continue;
     717            }
     718          break;
     719        }
     720  
     721    return ret;
     722  }
     723  
     724  /* A subroutine of vfp_type_p.  Given a structure type, return true if all
     725     of the non-structure elements are the same as CANDIDATE.  */
     726  
     727  static int
     728  is_hfa1 (const ffi_type *ty, int candidate)
     729  {
     730    ffi_type **elements = ty->elements;
     731    int i;
     732  
     733    if (elements != NULL)
     734      for (i = 0; elements[i]; ++i)
     735        {
     736          int t = elements[i]->type;
     737          if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
     738            {
     739              if (!is_hfa1 (elements[i], candidate))
     740                return 0;
     741            }
     742          else if (t != candidate)
     743            return 0;
     744        }
     745  
     746    return 1;
     747  }
     748  
     749  /* Determine if TY is an homogenous floating point aggregate (HFA).
     750     That is, a structure consisting of 1 to 4 members of all the same type,
     751     where that type is a floating point scalar.
     752  
     753     Returns non-zero iff TY is an HFA.  The result is an encoded value where
     754     bits 0-7 contain the type code, and bits 8-10 contain the element count.  */
     755  
     756  static int
     757  vfp_type_p (const ffi_type *ty)
     758  {
     759    ffi_type **elements;
     760    int candidate, i;
     761    size_t size, ele_count;
     762  
     763    /* Quickest tests first.  */
     764    candidate = ty->type;
     765    switch (ty->type)
     766      {
     767      default:
     768        return 0;
     769      case FFI_TYPE_FLOAT:
     770      case FFI_TYPE_DOUBLE:
     771        ele_count = 1;
     772        goto done;
     773      case FFI_TYPE_COMPLEX:
     774        candidate = ty->elements[0]->type;
     775        if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE)
     776  	return 0;
     777        ele_count = 2;
     778        goto done;
     779      case FFI_TYPE_STRUCT:
     780        break;
     781      }
     782  
     783    /* No HFA types are smaller than 4 bytes, or larger than 32 bytes.  */
     784    size = ty->size;
     785    if (size < 4 || size > 32)
     786      return 0;
     787  
     788    /* Find the type of the first non-structure member.  */
     789    elements = ty->elements;
     790    candidate = elements[0]->type;
     791    if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
     792      {
     793        for (i = 0; ; ++i)
     794          {
     795            candidate = is_hfa0 (elements[i]);
     796            if (candidate >= 0)
     797              break;
     798          }
     799      }
     800  
     801    /* If the first member is not a floating point type, it's not an HFA.
     802       Also quickly re-check the size of the structure.  */
     803    switch (candidate)
     804      {
     805      case FFI_TYPE_FLOAT:
     806        ele_count = size / sizeof(float);
     807        if (size != ele_count * sizeof(float))
     808          return 0;
     809        break;
     810      case FFI_TYPE_DOUBLE:
     811        ele_count = size / sizeof(double);
     812        if (size != ele_count * sizeof(double))
     813          return 0;
     814        break;
     815      default:
     816        return 0;
     817      }
     818    if (ele_count > 4)
     819      return 0;
     820  
     821    /* Finally, make sure that all scalar elements are the same type.  */
     822    for (i = 0; elements[i]; ++i)
     823      {
     824        int t = elements[i]->type;
     825        if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
     826          {
     827            if (!is_hfa1 (elements[i], candidate))
     828              return 0;
     829          }
     830        else if (t != candidate)
     831          return 0;
     832      }
     833  
     834    /* All tests succeeded.  Encode the result.  */
     835   done:
     836    return (ele_count << 8) | candidate;
     837  }
     838  
     839  static int
     840  place_vfp_arg (ffi_cif *cif, int h)
     841  {
     842    unsigned short reg = cif->vfp_reg_free;
     843    int align = 1, nregs = h >> 8;
     844  
     845    if ((h & 0xff) == FFI_TYPE_DOUBLE)
     846      align = 2, nregs *= 2;
     847  
     848    /* Align register number. */
     849    if ((reg & 1) && align == 2)
     850      reg++;
     851  
     852    while (reg + nregs <= 16)
     853      {
     854        int s, new_used = 0;
     855        for (s = reg; s < reg + nregs; s++)
     856  	{
     857  	  new_used |= (1 << s);
     858  	  if (cif->vfp_used & (1 << s))
     859  	    {
     860  	      reg += align;
     861  	      goto next_reg;
     862  	    }
     863  	}
     864        /* Found regs to allocate. */
     865        cif->vfp_used |= new_used;
     866        cif->vfp_args[cif->vfp_nargs++] = (signed char)reg;
     867  
     868        /* Update vfp_reg_free. */
     869        if (cif->vfp_used & (1 << cif->vfp_reg_free))
     870  	{
     871  	  reg += nregs;
     872  	  while (cif->vfp_used & (1 << reg))
     873  	    reg += 1;
     874  	  cif->vfp_reg_free = reg;
     875  	}
     876        return 0;
     877      next_reg:;
     878      }
     879    // done, mark all regs as used
     880    cif->vfp_reg_free = 16;
     881    cif->vfp_used = 0xFFFF;
     882    return 1;
     883  }
     884  
     885  static void
     886  layout_vfp_args (ffi_cif * cif)
     887  {
     888    unsigned int i;
     889    /* Init VFP fields */
     890    cif->vfp_used = 0;
     891    cif->vfp_nargs = 0;
     892    cif->vfp_reg_free = 0;
     893    memset (cif->vfp_args, -1, 16);	/* Init to -1. */
     894  
     895    for (i = 0; i < cif->nargs; i++)
     896      {
     897        int h = vfp_type_p (cif->arg_types[i]);
     898        if (h && place_vfp_arg (cif, h) == 1)
     899  	break;
     900      }
     901  }
     902  
     903  #if defined(FFI_EXEC_STATIC_TRAMP)
     904  void *
     905  ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
     906  {
     907    extern void *trampoline_code_table;
     908  
     909    *tramp_size = ARM_TRAMP_SIZE;
     910    *map_size = ARM_TRAMP_MAP_SIZE;
     911    return &trampoline_code_table;
     912  }
     913  #endif
     914  
     915  #endif /* __arm__ or _M_ARM */