OSDN Git Service

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