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