github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/mips/ffi.c (about)

     1  /* -----------------------------------------------------------------------
     2     ffi.c - Copyright (c) 2011  Anthony Green
     3             Copyright (c) 2008  David Daney
     4             Copyright (c) 1996, 2007, 2008, 2011  Red Hat, Inc.
     5     
     6     MIPS Foreign Function Interface 
     7  
     8     Permission is hereby granted, free of charge, to any person obtaining
     9     a copy of this software and associated documentation files (the
    10     ``Software''), to deal in the Software without restriction, including
    11     without limitation the rights to use, copy, modify, merge, publish,
    12     distribute, sublicense, and/or sell copies of the Software, and to
    13     permit persons to whom the Software is furnished to do so, subject to
    14     the following conditions:
    15  
    16     The above copyright notice and this permission notice shall be included
    17     in all copies or substantial portions of the Software.
    18  
    19     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
    20     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    21     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    22     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    23     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    24     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    25     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    26     DEALINGS IN THE SOFTWARE.
    27     ----------------------------------------------------------------------- */
    28  
    29  #include <ffi.h>
    30  #include <ffi_common.h>
    31  
    32  #include <stdlib.h>
    33  
    34  #ifdef __GNUC__
    35  #  if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
    36  #    define USE__BUILTIN___CLEAR_CACHE 1
    37  #  endif
    38  #endif
    39  
    40  #ifndef USE__BUILTIN___CLEAR_CACHE
    41  #  if defined(__OpenBSD__)
    42  #    include <mips64/sysarch.h>
    43  #  else
    44  #    include <sys/cachectl.h>
    45  #  endif
    46  #endif
    47  
    48  #ifdef FFI_DEBUG
    49  # define FFI_MIPS_STOP_HERE() ffi_stop_here()
    50  #else
    51  # define FFI_MIPS_STOP_HERE() do {} while(0)
    52  #endif
    53  
    54  #ifdef FFI_MIPS_N32
    55  #define FIX_ARGP \
    56  FFI_ASSERT(argp <= &stack[bytes]); \
    57  if (argp == &stack[bytes]) \
    58  { \
    59    argp = stack; \
    60    FFI_MIPS_STOP_HERE(); \
    61  }
    62  #else
    63  #define FIX_ARGP 
    64  #endif
    65  
    66  
    67  /* ffi_prep_args is called by the assembly routine once stack space
    68     has been allocated for the function's arguments */
    69  
    70  static void ffi_prep_args(char *stack, 
    71  			  extended_cif *ecif,
    72  			  int bytes,
    73  			  int flags)
    74  {
    75    int i;
    76    void **p_argv;
    77    char *argp;
    78    ffi_type **p_arg;
    79  
    80  #ifdef FFI_MIPS_N32
    81    /* If more than 8 double words are used, the remainder go
    82       on the stack. We reorder stuff on the stack here to 
    83       support this easily. */
    84    if (bytes > 8 * sizeof(ffi_arg))
    85      argp = &stack[bytes - (8 * sizeof(ffi_arg))];
    86    else
    87      argp = stack;
    88  #else
    89    argp = stack;
    90  #endif
    91  
    92    memset(stack, 0, bytes);
    93  
    94  #ifdef FFI_MIPS_N32
    95    if ( ecif->cif->rstruct_flag != 0 )
    96  #else
    97    if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
    98  #endif  
    99      {
   100        *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
   101        argp += sizeof(ffi_arg);
   102        FIX_ARGP;
   103      }
   104  
   105    p_argv = ecif->avalue;
   106  
   107    for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++)
   108      {
   109        size_t z;
   110        unsigned int a;
   111  
   112        /* Align if necessary.  */
   113        a = (*p_arg)->alignment;
   114        if (a < sizeof(ffi_arg))
   115          a = sizeof(ffi_arg);
   116        
   117        if ((a - 1) & (unsigned long) argp)
   118  	{
   119  	  argp = (char *) ALIGN(argp, a);
   120  	  FIX_ARGP;
   121  	}
   122  
   123        z = (*p_arg)->size;
   124        if (z <= sizeof(ffi_arg))
   125  	{
   126            int type = (*p_arg)->type;
   127  	  z = sizeof(ffi_arg);
   128  
   129            /* The size of a pointer depends on the ABI */
   130            if (type == FFI_TYPE_POINTER)
   131              type = (ecif->cif->abi == FFI_N64
   132  		    || ecif->cif->abi == FFI_N64_SOFT_FLOAT)
   133  	      ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
   134  
   135  	if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
   136  		      || ecif->cif->abi == FFI_N64_SOFT_FLOAT))
   137  	  {
   138  	    switch (type)
   139  	      {
   140  	      case FFI_TYPE_FLOAT:
   141  		type = FFI_TYPE_UINT32;
   142  		break;
   143  	      case FFI_TYPE_DOUBLE:
   144  		type = FFI_TYPE_UINT64;
   145  		break;
   146  	      default:
   147  		break;
   148  	      }
   149  	  }
   150  	  switch (type)
   151  	    {
   152  	      case FFI_TYPE_SINT8:
   153  		*(ffi_arg *)argp = *(SINT8 *)(* p_argv);
   154  		break;
   155  
   156  	      case FFI_TYPE_UINT8:
   157  		*(ffi_arg *)argp = *(UINT8 *)(* p_argv);
   158  		break;
   159  		  
   160  	      case FFI_TYPE_SINT16:
   161  		*(ffi_arg *)argp = *(SINT16 *)(* p_argv);
   162  		break;
   163  		  
   164  	      case FFI_TYPE_UINT16:
   165  		*(ffi_arg *)argp = *(UINT16 *)(* p_argv);
   166  		break;
   167  		  
   168  	      case FFI_TYPE_SINT32:
   169  		*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
   170  		break;
   171  		  
   172  	      case FFI_TYPE_UINT32:
   173  #ifdef FFI_MIPS_N32
   174  		/* The N32 ABI requires that 32-bit integers
   175  		   be sign-extended to 64-bits, regardless of
   176  		   whether they are signed or unsigned. */
   177  		*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
   178  #else
   179  		*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
   180  #endif
   181  		break;
   182  
   183  	      /* This can only happen with 64bit slots.  */
   184  	      case FFI_TYPE_FLOAT:
   185  		*(float *) argp = *(float *)(* p_argv);
   186  		break;
   187  
   188  	      /* Handle structures.  */
   189  	      default:
   190  		memcpy(argp, *p_argv, (*p_arg)->size);
   191  		break;
   192  	    }
   193  	}
   194        else
   195  	{
   196  #ifdef FFI_MIPS_O32
   197  	  memcpy(argp, *p_argv, z);
   198  #else
   199  	  {
   200  	    unsigned long end = (unsigned long) argp + z;
   201  	    unsigned long cap = (unsigned long) stack + bytes;
   202  
   203  	    /* Check if the data will fit within the register space.
   204  	       Handle it if it doesn't.  */
   205  
   206  	    if (end <= cap)
   207  	      memcpy(argp, *p_argv, z);
   208  	    else
   209  	      {
   210  		unsigned long portion = cap - (unsigned long)argp;
   211  
   212  		memcpy(argp, *p_argv, portion);
   213  		argp = stack;
   214                  z -= portion;
   215  		memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
   216                         z);
   217  	      }
   218  	  }
   219  #endif
   220        }
   221        p_argv++;
   222        argp += z;
   223        FIX_ARGP;
   224      }
   225  }
   226  
   227  #ifdef FFI_MIPS_N32
   228  
   229  /* The n32 spec says that if "a chunk consists solely of a double 
   230     float field (but not a double, which is part of a union), it
   231     is passed in a floating point register. Any other chunk is
   232     passed in an integer register". This code traverses structure
   233     definitions and generates the appropriate flags. */
   234  
   235  static unsigned
   236  calc_n32_struct_flags(int soft_float, ffi_type *arg,
   237  		      unsigned *loc, unsigned *arg_reg)
   238  {
   239    unsigned flags = 0;
   240    unsigned index = 0;
   241  
   242    ffi_type *e;
   243  
   244    if (soft_float)
   245      return 0;
   246  
   247    while ((e = arg->elements[index]))
   248      {
   249        /* Align this object.  */
   250        *loc = ALIGN(*loc, e->alignment);
   251        if (e->type == FFI_TYPE_DOUBLE)
   252  	{
   253            /* Already aligned to FFI_SIZEOF_ARG.  */
   254            *arg_reg = *loc / FFI_SIZEOF_ARG;
   255            if (*arg_reg > 7)
   256              break;
   257  	  flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
   258            *loc += e->size;
   259  	}
   260        else
   261          *loc += e->size;
   262        index++;
   263      }
   264    /* Next Argument register at alignment of FFI_SIZEOF_ARG.  */
   265    *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
   266  
   267    return flags;
   268  }
   269  
   270  static unsigned
   271  calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
   272  {
   273    unsigned flags = 0;
   274    unsigned small = FFI_TYPE_SMALLSTRUCT;
   275    ffi_type *e;
   276  
   277    /* Returning structures under n32 is a tricky thing.
   278       A struct with only one or two floating point fields 
   279       is returned in $f0 (and $f2 if necessary). Any other
   280       struct results at most 128 bits are returned in $2
   281       (the first 64 bits) and $3 (remainder, if necessary).
   282       Larger structs are handled normally. */
   283    
   284    if (arg->size > 16)
   285      return 0;
   286  
   287    if (arg->size > 8)
   288      small = FFI_TYPE_SMALLSTRUCT2;
   289  
   290    e = arg->elements[0];
   291  
   292    if (e->type == FFI_TYPE_DOUBLE)
   293      flags = FFI_TYPE_DOUBLE;
   294    else if (e->type == FFI_TYPE_FLOAT)
   295      flags = FFI_TYPE_FLOAT;
   296  
   297    if (flags && (e = arg->elements[1]))
   298      {
   299        if (e->type == FFI_TYPE_DOUBLE)
   300  	flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
   301        else if (e->type == FFI_TYPE_FLOAT)
   302  	flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
   303        else 
   304  	return small;
   305  
   306        if (flags && (arg->elements[2]))
   307  	{
   308  	  /* There are three arguments and the first two are 
   309  	     floats! This must be passed the old way. */
   310  	  return small;
   311  	}
   312        if (soft_float)
   313  	flags += FFI_TYPE_STRUCT_SOFT;
   314      }
   315    else
   316      if (!flags)
   317        return small;
   318  
   319    return flags;
   320  }
   321  
   322  #endif
   323  
   324  /* Perform machine dependent cif processing */
   325  ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
   326  {
   327    cif->flags = 0;
   328  
   329  #ifdef FFI_MIPS_O32
   330    /* Set the flags necessary for O32 processing.  FFI_O32_SOFT_FLOAT
   331     * does not have special handling for floating point args.
   332     */
   333  
   334    if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
   335      {
   336        if (cif->nargs > 0)
   337  	{
   338  	  switch ((cif->arg_types)[0]->type)
   339  	    {
   340  	    case FFI_TYPE_FLOAT:
   341  	    case FFI_TYPE_DOUBLE:
   342  	      cif->flags += (cif->arg_types)[0]->type;
   343  	      break;
   344  	      
   345  	    default:
   346  	      break;
   347  	    }
   348  
   349  	  if (cif->nargs > 1)
   350  	    {
   351  	      /* Only handle the second argument if the first
   352  		 is a float or double. */
   353  	      if (cif->flags)
   354  		{
   355  		  switch ((cif->arg_types)[1]->type)
   356  		    {
   357  		    case FFI_TYPE_FLOAT:
   358  		    case FFI_TYPE_DOUBLE:
   359  		      cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
   360  		      break;
   361  		      
   362  		    default:
   363  		      break;
   364  		    }
   365  		}
   366  	    }
   367  	}
   368      }
   369        
   370    /* Set the return type flag */
   371  
   372    if (cif->abi == FFI_O32_SOFT_FLOAT)
   373      {
   374        switch (cif->rtype->type)
   375          {
   376          case FFI_TYPE_VOID:
   377          case FFI_TYPE_STRUCT:
   378            cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
   379            break;
   380  
   381          case FFI_TYPE_SINT64:
   382          case FFI_TYPE_UINT64:
   383          case FFI_TYPE_DOUBLE:
   384            cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
   385            break;
   386        
   387          case FFI_TYPE_FLOAT:
   388          default:
   389            cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
   390            break;
   391          }
   392      }
   393    else
   394      {
   395        /* FFI_O32 */      
   396        switch (cif->rtype->type)
   397          {
   398          case FFI_TYPE_VOID:
   399          case FFI_TYPE_STRUCT:
   400          case FFI_TYPE_FLOAT:
   401          case FFI_TYPE_DOUBLE:
   402            cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
   403            break;
   404  
   405          case FFI_TYPE_SINT64:
   406          case FFI_TYPE_UINT64:
   407            cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
   408            break;
   409        
   410          default:
   411            cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
   412            break;
   413          }
   414      }
   415  #endif
   416  
   417  #ifdef FFI_MIPS_N32
   418    /* Set the flags necessary for N32 processing */
   419    {
   420      int type;
   421      unsigned arg_reg = 0;
   422      unsigned loc = 0;
   423      unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
   424      unsigned index = 0;
   425  
   426      unsigned struct_flags = 0;
   427      int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT
   428  		      || cif->abi == FFI_N64_SOFT_FLOAT);
   429  
   430      if (cif->rtype->type == FFI_TYPE_STRUCT)
   431        {
   432  	struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype);
   433  
   434  	if (struct_flags == 0)
   435  	  {
   436  	    /* This means that the structure is being passed as
   437  	       a hidden argument */
   438  
   439  	    arg_reg = 1;
   440  	    count = (cif->nargs < 7) ? cif->nargs : 7;
   441  
   442  	    cif->rstruct_flag = !0;
   443  	  }
   444  	else
   445  	    cif->rstruct_flag = 0;
   446        }
   447      else
   448        cif->rstruct_flag = 0;
   449  
   450      while (count-- > 0 && arg_reg < 8)
   451        {
   452  	type = (cif->arg_types)[index]->type;
   453  	if (soft_float)
   454  	  {
   455  	    switch (type)
   456  	      {
   457  	      case FFI_TYPE_FLOAT:
   458  		type = FFI_TYPE_UINT32;
   459  		break;
   460  	      case FFI_TYPE_DOUBLE:
   461  		type = FFI_TYPE_UINT64;
   462  		break;
   463  	      default:
   464  		break;
   465  	      }
   466  	  }
   467  	switch (type)
   468  	  {
   469  	  case FFI_TYPE_FLOAT:
   470  	  case FFI_TYPE_DOUBLE:
   471  	    cif->flags +=
   472                ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
   473  	    arg_reg++;
   474  	    break;
   475            case FFI_TYPE_LONGDOUBLE:
   476              /* Align it.  */
   477              arg_reg = ALIGN(arg_reg, 2);
   478              /* Treat it as two adjacent doubles.  */
   479  	    if (soft_float) 
   480  	      {
   481  		arg_reg += 2;
   482  	      }
   483  	    else
   484  	      {
   485  		cif->flags +=
   486  		  (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
   487  		arg_reg++;
   488  		cif->flags +=
   489  		  (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
   490  		arg_reg++;
   491  	      }
   492              break;
   493  
   494  	  case FFI_TYPE_STRUCT:
   495              loc = arg_reg * FFI_SIZEOF_ARG;
   496  	    cif->flags += calc_n32_struct_flags(soft_float,
   497  						(cif->arg_types)[index],
   498  						&loc, &arg_reg);
   499  	    break;
   500  
   501  	  default:
   502  	    arg_reg++;
   503              break;
   504  	  }
   505  
   506  	index++;
   507        }
   508  
   509    /* Set the return type flag */
   510      switch (cif->rtype->type)
   511        {
   512        case FFI_TYPE_STRUCT:
   513  	{
   514  	  if (struct_flags == 0)
   515  	    {
   516  	      /* The structure is returned through a hidden
   517  		 first argument. Do nothing, 'cause FFI_TYPE_VOID 
   518  		 is 0 */
   519  	    }
   520  	  else
   521  	    {
   522  	      /* The structure is returned via some tricky
   523  		 mechanism */
   524  	      cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
   525  	      cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
   526  	    }
   527  	  break;
   528  	}
   529        
   530        case FFI_TYPE_VOID:
   531  	/* Do nothing, 'cause FFI_TYPE_VOID is 0 */
   532  	break;
   533  
   534        case FFI_TYPE_POINTER:
   535  	if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
   536  	  cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
   537  	else
   538  	  cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
   539  	break;
   540  
   541        case FFI_TYPE_FLOAT:
   542  	if (soft_float)
   543  	  {
   544  	    cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
   545  	    break;
   546  	  }
   547  	/* else fall through */
   548        case FFI_TYPE_DOUBLE:
   549  	if (soft_float)
   550  	  cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
   551  	else
   552  	  cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
   553  	break;
   554  
   555        case FFI_TYPE_LONGDOUBLE:
   556  	/* Long double is returned as if it were a struct containing
   557  	   two doubles.  */
   558  	if (soft_float)
   559  	  {
   560  	    cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
   561  	    cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
   562   	  }
   563  	else
   564  	  {
   565  	    cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
   566  	    cif->flags += (FFI_TYPE_DOUBLE
   567  			   + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
   568  					      << (4 + (FFI_FLAG_BITS * 8));
   569  	  }
   570  	break;
   571        default:
   572  	cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
   573  	break;
   574        }
   575    }
   576  #endif
   577    
   578    return FFI_OK;
   579  }
   580  
   581  /* Low level routine for calling O32 functions */
   582  extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), 
   583  			extended_cif *, unsigned, 
   584  			unsigned, unsigned *, void (*)(void));
   585  
   586  /* Low level routine for calling N32 functions */
   587  extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 
   588  			extended_cif *, unsigned, 
   589  			unsigned, void *, void (*)(void));
   590  
   591  void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
   592  {
   593    extended_cif ecif;
   594  
   595    ecif.cif = cif;
   596    ecif.avalue = avalue;
   597    
   598    /* If the return value is a struct and we don't have a return	*/
   599    /* value address then we need to make one		        */
   600    
   601    if ((rvalue == NULL) && 
   602        (cif->rtype->type == FFI_TYPE_STRUCT))
   603      ecif.rvalue = alloca(cif->rtype->size);
   604    else
   605      ecif.rvalue = rvalue;
   606      
   607    switch (cif->abi) 
   608      {
   609  #ifdef FFI_MIPS_O32
   610      case FFI_O32:
   611      case FFI_O32_SOFT_FLOAT:
   612        ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
   613  		   cif->flags, ecif.rvalue, fn);
   614        break;
   615  #endif
   616  
   617  #ifdef FFI_MIPS_N32
   618      case FFI_N32:
   619      case FFI_N32_SOFT_FLOAT:
   620      case FFI_N64:
   621      case FFI_N64_SOFT_FLOAT:
   622        {
   623          int copy_rvalue = 0;
   624  	int copy_offset = 0;
   625          char *rvalue_copy = ecif.rvalue;
   626          if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
   627            {
   628              /* For structures smaller than 16 bytes we clobber memory
   629                 in 8 byte increments.  Make a copy so we don't clobber
   630                 the callers memory outside of the struct bounds.  */
   631              rvalue_copy = alloca(16);
   632              copy_rvalue = 1;
   633            }
   634  	else if (cif->rtype->type == FFI_TYPE_FLOAT
   635  		 && (cif->abi == FFI_N64_SOFT_FLOAT
   636  		     || cif->abi == FFI_N32_SOFT_FLOAT))
   637  	  {
   638  	    rvalue_copy = alloca (8);
   639  	    copy_rvalue = 1;
   640  #if defined(__MIPSEB__) || defined(_MIPSEB)
   641  	    copy_offset = 4;
   642  #endif
   643  	  }
   644          ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
   645                       cif->flags, rvalue_copy, fn);
   646          if (copy_rvalue)
   647            memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
   648        }
   649        break;
   650  #endif
   651  
   652      default:
   653        FFI_ASSERT(0);
   654        break;
   655      }
   656  }
   657  
   658  #if FFI_CLOSURES
   659  #if defined(FFI_MIPS_O32)
   660  extern void ffi_closure_O32(void);
   661  #else
   662  extern void ffi_closure_N32(void);
   663  #endif /* FFI_MIPS_O32 */
   664  
   665  ffi_status
   666  ffi_prep_closure_loc (ffi_closure *closure,
   667  		      ffi_cif *cif,
   668  		      void (*fun)(ffi_cif*,void*,void**,void*),
   669  		      void *user_data,
   670  		      void *codeloc)
   671  {
   672    unsigned int *tramp = (unsigned int *) &closure->tramp[0];
   673    void * fn;
   674    char *clear_location = (char *) codeloc;
   675  
   676  #if defined(FFI_MIPS_O32)
   677    if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
   678      return FFI_BAD_ABI;
   679    fn = ffi_closure_O32;
   680  #else
   681  #if _MIPS_SIM ==_ABIN32
   682    if (cif->abi != FFI_N32
   683        && cif->abi != FFI_N32_SOFT_FLOAT)
   684      return FFI_BAD_ABI;
   685  #else
   686    if (cif->abi != FFI_N64
   687        && cif->abi != FFI_N64_SOFT_FLOAT)
   688      return FFI_BAD_ABI;
   689  #endif
   690    fn = ffi_closure_N32;
   691  #endif /* FFI_MIPS_O32 */
   692  
   693  #if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
   694    /* lui  $25,high(fn) */
   695    tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
   696    /* ori  $25,low(fn)  */
   697    tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
   698    /* lui  $12,high(codeloc) */
   699    tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
   700    /* jr   $25          */
   701    tramp[3] = 0x03200008;
   702    /* ori  $12,low(codeloc)  */
   703    tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
   704  #else
   705    /* N64 has a somewhat larger trampoline.  */
   706    /* lui  $25,high(fn) */
   707    tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
   708    /* lui  $12,high(codeloc) */
   709    tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
   710    /* ori  $25,mid-high(fn)  */
   711    tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
   712    /* ori  $12,mid-high(codeloc)  */
   713    tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
   714    /* dsll $25,$25,16 */
   715    tramp[4] = 0x0019cc38;
   716    /* dsll $12,$12,16 */
   717    tramp[5] = 0x000c6438;
   718    /* ori  $25,mid-low(fn)  */
   719    tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
   720    /* ori  $12,mid-low(codeloc)  */
   721    tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
   722    /* dsll $25,$25,16 */
   723    tramp[8] = 0x0019cc38;
   724    /* dsll $12,$12,16 */
   725    tramp[9] = 0x000c6438;
   726    /* ori  $25,low(fn)  */
   727    tramp[10] = 0x37390000 | ((unsigned long)fn  & 0xffff);
   728    /* jr   $25          */
   729    tramp[11] = 0x03200008;
   730    /* ori  $12,low(codeloc)  */
   731    tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
   732  
   733  #endif
   734  
   735    closure->cif = cif;
   736    closure->fun = fun;
   737    closure->user_data = user_data;
   738  
   739  #ifdef USE__BUILTIN___CLEAR_CACHE
   740    __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
   741  #else
   742    cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
   743  #endif
   744    return FFI_OK;
   745  }
   746  
   747  /*
   748   * Decodes the arguments to a function, which will be stored on the
   749   * stack. AR is the pointer to the beginning of the integer arguments
   750   * (and, depending upon the arguments, some floating-point arguments
   751   * as well). FPR is a pointer to the area where floating point
   752   * registers have been saved, if any.
   753   *
   754   * RVALUE is the location where the function return value will be
   755   * stored. CLOSURE is the prepared closure to invoke.
   756   *
   757   * This function should only be called from assembly, which is in
   758   * turn called from a trampoline.
   759   *
   760   * Returns the function return type.
   761   *
   762   * Based on the similar routine for sparc.
   763   */
   764  int
   765  ffi_closure_mips_inner_O32 (ffi_closure *closure,
   766  			    void *rvalue, ffi_arg *ar,
   767  			    double *fpr)
   768  {
   769    ffi_cif *cif;
   770    void **avaluep;
   771    ffi_arg *avalue;
   772    ffi_type **arg_types;
   773    int i, avn, argn, seen_int;
   774  
   775    cif = closure->cif;
   776    avalue = alloca (cif->nargs * sizeof (ffi_arg));
   777    avaluep = alloca (cif->nargs * sizeof (ffi_arg));
   778  
   779    seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
   780    argn = 0;
   781  
   782    if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
   783      {
   784        rvalue = (void *)(UINT32)ar[0];
   785        argn = 1;
   786      }
   787  
   788    i = 0;
   789    avn = cif->nargs;
   790    arg_types = cif->arg_types;
   791  
   792    while (i < avn)
   793      {
   794        if (i < 2 && !seen_int &&
   795  	  (arg_types[i]->type == FFI_TYPE_FLOAT ||
   796  	   arg_types[i]->type == FFI_TYPE_DOUBLE ||
   797  	   arg_types[i]->type == FFI_TYPE_LONGDOUBLE))
   798  	{
   799  #if defined(__MIPSEB__) || defined(_MIPSEB)
   800  	  if (arg_types[i]->type == FFI_TYPE_FLOAT)
   801  	    avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
   802  	  else
   803  #endif
   804  	    avaluep[i] = (char *) &fpr[i];
   805  	}
   806        else
   807  	{
   808  	  if (arg_types[i]->alignment == 8 && (argn & 0x1))
   809  	    argn++;
   810  	  switch (arg_types[i]->type)
   811  	    {
   812  	      case FFI_TYPE_SINT8:
   813  		avaluep[i] = &avalue[i];
   814  		*(SINT8 *) &avalue[i] = (SINT8) ar[argn];
   815  		break;
   816  
   817  	      case FFI_TYPE_UINT8:
   818  		avaluep[i] = &avalue[i];
   819  		*(UINT8 *) &avalue[i] = (UINT8) ar[argn];
   820  		break;
   821  		  
   822  	      case FFI_TYPE_SINT16:
   823  		avaluep[i] = &avalue[i];
   824  		*(SINT16 *) &avalue[i] = (SINT16) ar[argn];
   825  		break;
   826  		  
   827  	      case FFI_TYPE_UINT16:
   828  		avaluep[i] = &avalue[i];
   829  		*(UINT16 *) &avalue[i] = (UINT16) ar[argn];
   830  		break;
   831  
   832  	      default:
   833  		avaluep[i] = (char *) &ar[argn];
   834  		break;
   835  	    }
   836  	  seen_int = 1;
   837  	}
   838        argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
   839        i++;
   840      }
   841  
   842    /* Invoke the closure. */
   843    (closure->fun) (cif, rvalue, avaluep, closure->user_data);
   844  
   845    if (cif->abi == FFI_O32_SOFT_FLOAT)
   846      {
   847        switch (cif->rtype->type)
   848          {
   849          case FFI_TYPE_FLOAT:
   850            return FFI_TYPE_INT;
   851          case FFI_TYPE_DOUBLE:
   852            return FFI_TYPE_UINT64;
   853          default:
   854            return cif->rtype->type;
   855          }
   856      }
   857    else
   858      {
   859        return cif->rtype->type;
   860      }
   861  }
   862  
   863  #if defined(FFI_MIPS_N32)
   864  
   865  static void
   866  copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
   867                  int argn, unsigned arg_offset, ffi_arg *ar,
   868                  ffi_arg *fpr, int soft_float)
   869  {
   870    ffi_type **elt_typep = type->elements;
   871    while(*elt_typep)
   872      {
   873        ffi_type *elt_type = *elt_typep;
   874        unsigned o;
   875        char *tp;
   876        char *argp;
   877        char *fpp;
   878  
   879        o = ALIGN(offset, elt_type->alignment);
   880        arg_offset += o - offset;
   881        offset = o;
   882        argn += arg_offset / sizeof(ffi_arg);
   883        arg_offset = arg_offset % sizeof(ffi_arg);
   884  
   885        argp = (char *)(ar + argn);
   886        fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
   887  
   888        tp = target + offset;
   889  
   890        if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float)
   891          *(double *)tp = *(double *)fpp;
   892        else
   893          memcpy(tp, argp + arg_offset, elt_type->size);
   894  
   895        offset += elt_type->size;
   896        arg_offset += elt_type->size;
   897        elt_typep++;
   898        argn += arg_offset / sizeof(ffi_arg);
   899        arg_offset = arg_offset % sizeof(ffi_arg);
   900      }
   901  }
   902  
   903  /*
   904   * Decodes the arguments to a function, which will be stored on the
   905   * stack. AR is the pointer to the beginning of the integer
   906   * arguments. FPR is a pointer to the area where floating point
   907   * registers have been saved.
   908   *
   909   * RVALUE is the location where the function return value will be
   910   * stored. CLOSURE is the prepared closure to invoke.
   911   *
   912   * This function should only be called from assembly, which is in
   913   * turn called from a trampoline.
   914   *
   915   * Returns the function return flags.
   916   *
   917   */
   918  int
   919  ffi_closure_mips_inner_N32 (ffi_closure *closure,
   920  			    void *rvalue, ffi_arg *ar,
   921  			    ffi_arg *fpr)
   922  {
   923    ffi_cif *cif;
   924    void **avaluep;
   925    ffi_arg *avalue;
   926    ffi_type **arg_types;
   927    int i, avn, argn;
   928    int soft_float;
   929    ffi_arg *argp;
   930  
   931    cif = closure->cif;
   932    soft_float = cif->abi == FFI_N64_SOFT_FLOAT
   933      || cif->abi == FFI_N32_SOFT_FLOAT;
   934    avalue = alloca (cif->nargs * sizeof (ffi_arg));
   935    avaluep = alloca (cif->nargs * sizeof (ffi_arg));
   936  
   937    argn = 0;
   938  
   939    if (cif->rstruct_flag)
   940      {
   941  #if _MIPS_SIM==_ABIN32
   942        rvalue = (void *)(UINT32)ar[0];
   943  #else /* N64 */
   944        rvalue = (void *)ar[0];
   945  #endif
   946        argn = 1;
   947      }
   948  
   949    i = 0;
   950    avn = cif->nargs;
   951    arg_types = cif->arg_types;
   952  
   953    while (i < avn)
   954      {
   955        if (arg_types[i]->type == FFI_TYPE_FLOAT
   956  	  || arg_types[i]->type == FFI_TYPE_DOUBLE
   957  	  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE)
   958          {
   959            argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn;
   960            if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((unsigned)argp & (arg_types[i]->alignment-1)))
   961              {
   962                argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment);
   963                argn++;
   964              }
   965  #if defined(__MIPSEB__) || defined(_MIPSEB)
   966            if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
   967              avaluep[i] = ((char *) argp) + sizeof (float);
   968            else
   969  #endif
   970              avaluep[i] = (char *) argp;
   971          }
   972        else
   973          {
   974            unsigned type = arg_types[i]->type;
   975  
   976            if (arg_types[i]->alignment > sizeof(ffi_arg))
   977              argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
   978  
   979            argp = ar + argn;
   980  
   981            /* The size of a pointer depends on the ABI */
   982            if (type == FFI_TYPE_POINTER)
   983              type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
   984  	      ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
   985  
   986  	  if (soft_float && type ==  FFI_TYPE_FLOAT)
   987  	    type = FFI_TYPE_UINT32;
   988  
   989            switch (type)
   990              {
   991              case FFI_TYPE_SINT8:
   992                avaluep[i] = &avalue[i];
   993                *(SINT8 *) &avalue[i] = (SINT8) *argp;
   994                break;
   995  
   996              case FFI_TYPE_UINT8:
   997                avaluep[i] = &avalue[i];
   998                *(UINT8 *) &avalue[i] = (UINT8) *argp;
   999                break;
  1000  
  1001              case FFI_TYPE_SINT16:
  1002                avaluep[i] = &avalue[i];
  1003                *(SINT16 *) &avalue[i] = (SINT16) *argp;
  1004                break;
  1005  
  1006              case FFI_TYPE_UINT16:
  1007                avaluep[i] = &avalue[i];
  1008                *(UINT16 *) &avalue[i] = (UINT16) *argp;
  1009                break;
  1010  
  1011              case FFI_TYPE_SINT32:
  1012                avaluep[i] = &avalue[i];
  1013                *(SINT32 *) &avalue[i] = (SINT32) *argp;
  1014                break;
  1015  
  1016              case FFI_TYPE_UINT32:
  1017                avaluep[i] = &avalue[i];
  1018                *(UINT32 *) &avalue[i] = (UINT32) *argp;
  1019                break;
  1020  
  1021              case FFI_TYPE_STRUCT:
  1022                if (argn < 8)
  1023                  {
  1024                    /* Allocate space for the struct as at least part of
  1025                       it was passed in registers.  */
  1026                    avaluep[i] = alloca(arg_types[i]->size);
  1027                    copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
  1028                                    argn, 0, ar, fpr, soft_float);
  1029  
  1030                    break;
  1031                  }
  1032                /* Else fall through.  */
  1033              default:
  1034                avaluep[i] = (char *) argp;
  1035                break;
  1036              }
  1037          }
  1038        argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
  1039        i++;
  1040      }
  1041  
  1042    /* Invoke the closure. */
  1043    (closure->fun) (cif, rvalue, avaluep, closure->user_data);
  1044  
  1045    return cif->flags >> (FFI_FLAG_BITS * 8);
  1046  }
  1047  
  1048  #endif /* FFI_MIPS_N32 */
  1049  
  1050  #endif /* FFI_CLOSURES */