PageRenderTime 76ms CodeModel.GetById 7ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 0ms

/Modules/_ctypes/libffi/src/mips/ffi.c

http://unladen-swallow.googlecode.com/
C | 926 lines | 661 code | 126 blank | 139 comment | 115 complexity | c4b338c1c56fbe690ffd27d93d206de9 MD5 | raw file
  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 \
 51FFI_ASSERT(argp <= &stack[bytes]); \
 52if (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
 65static 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
207static unsigned
208calc_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
238static unsigned
239calc_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 */
290ffi_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 */
495extern 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 */
500extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 
501			extended_cif *, unsigned, 
502			unsigned, unsigned *, void (*)(void));
503
504void 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)
560extern void ffi_closure_O32(void);
561#else
562extern void ffi_closure_N32(void);
563#endif /* FFI_MIPS_O32 */
564
565ffi_status
566ffi_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 */
655int
656ffi_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
755static void
756copy_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 */
808int
809ffi_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 */