OSDN Git Service

Code drop from //branches/cupcake/...@124589
[android-x86/external-libffi.git] / src / mips / ffi.c
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 */