OSDN Git Service

2005-12-07 Thiemo Seufer <ths@networkno.de>
[pf3gnuchains/gcc-fork.git] / libffi / src / mips / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1996 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, EXPRESS
18    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20    IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23    OTHER DEALINGS IN THE SOFTWARE.
24    ----------------------------------------------------------------------- */
25
26 #include <ffi.h>
27 #include <ffi_common.h>
28
29 #include <stdlib.h>
30 #include <sys/cachectl.h>
31
32 #if _MIPS_SIM == _ABIN32
33 #define FIX_ARGP \
34 FFI_ASSERT(argp <= &stack[bytes]); \
35 if (argp == &stack[bytes]) \
36 { \
37   argp = stack; \
38   ffi_stop_here(); \
39 }
40 #else
41 #define FIX_ARGP 
42 #endif
43
44
45 /* ffi_prep_args is called by the assembly routine once stack space
46    has been allocated for the function's arguments */
47
48 static void ffi_prep_args(char *stack, 
49                           extended_cif *ecif,
50                           int bytes,
51                           int flags)
52 {
53   int i;
54   void **p_argv;
55   char *argp;
56   ffi_type **p_arg;
57
58 #if _MIPS_SIM == _ABIN32
59   /* If more than 8 double words are used, the remainder go
60      on the stack. We reorder stuff on the stack here to 
61      support this easily. */
62   if (bytes > 8 * sizeof(ffi_arg))
63     argp = &stack[bytes - (8 * sizeof(ffi_arg))];
64   else
65     argp = stack;
66 #else
67   argp = stack;
68 #endif
69
70   memset(stack, 0, bytes);
71
72 #if _MIPS_SIM == _ABIN32
73   if ( ecif->cif->rstruct_flag != 0 )
74 #else
75   if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
76 #endif  
77     {
78       *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
79       argp += sizeof(ffi_arg);
80       FIX_ARGP;
81     }
82
83   p_argv = ecif->avalue;
84
85   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
86     {
87       size_t z;
88       unsigned int a;
89
90       /* Align if necessary.  */
91       a = (*p_arg)->alignment;
92       if (a < sizeof(ffi_arg))
93         a = sizeof(ffi_arg);
94       
95       if ((a - 1) & (unsigned int) argp)
96         {
97           argp = (char *) ALIGN(argp, a);
98           FIX_ARGP;
99         }
100
101       z = (*p_arg)->size;
102       if (z <= sizeof(ffi_arg))
103         {
104           z = sizeof(ffi_arg);
105
106           switch ((*p_arg)->type)
107             {
108               case FFI_TYPE_SINT8:
109                 *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
110                 break;
111
112               case FFI_TYPE_UINT8:
113                 *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
114                 break;
115                   
116               case FFI_TYPE_SINT16:
117                 *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
118                 break;
119                   
120               case FFI_TYPE_UINT16:
121                 *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
122                 break;
123                   
124               case FFI_TYPE_SINT32:
125                 *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
126                 break;
127                   
128               case FFI_TYPE_UINT32:
129               case FFI_TYPE_POINTER:
130                 *(ffi_arg *)argp = *(UINT32 *)(* p_argv);
131                 break;
132
133               /* This can only happen with 64bit slots.  */
134               case FFI_TYPE_FLOAT:
135                 *(float *) argp = *(float *)(* p_argv);
136                 break;
137
138               /* Handle small structures.  */
139               case FFI_TYPE_STRUCT:
140               default:
141                 memcpy(argp, *p_argv, (*p_arg)->size);
142                 break;
143             }
144         }
145       else
146         {
147 #if _MIPS_SIM == _ABIO32
148           memcpy(argp, *p_argv, z);
149 #else
150           {
151             unsigned end = (unsigned) argp+z;
152             unsigned cap = (unsigned) stack+bytes;
153
154             /* Check if the data will fit within the register space.
155                Handle it if it doesn't.  */
156
157             if (end <= cap)
158               memcpy(argp, *p_argv, z);
159             else
160               {
161                 unsigned portion = end - cap;
162
163                 memcpy(argp, *p_argv, portion);
164                 argp = stack;
165                 memcpy(argp,
166                        (void*)((unsigned)(*p_argv)+portion), z - portion);
167               }
168           }
169 #endif
170       }
171       p_argv++;
172       argp += z;
173       FIX_ARGP;
174     }
175 }
176
177 #if _MIPS_SIM == _ABIN32
178
179 /* The n32 spec says that if "a chunk consists solely of a double 
180    float field (but not a double, which is part of a union), it
181    is passed in a floating point register. Any other chunk is
182    passed in an integer register". This code traverses structure
183    definitions and generates the appropriate flags. */
184
185 unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
186 {
187   unsigned flags = 0;
188   unsigned index = 0;
189
190   ffi_type *e;
191
192   while (e = arg->elements[index])
193     {
194       if (e->type == FFI_TYPE_DOUBLE)
195         {
196           flags += (FFI_TYPE_DOUBLE << *shift);
197           *shift += FFI_FLAG_BITS;
198         }
199       else if (e->type == FFI_TYPE_STRUCT)
200           flags += calc_n32_struct_flags(e, shift);
201       else
202         *shift += FFI_FLAG_BITS;
203
204       index++;
205     }
206
207   return flags;
208 }
209
210 unsigned calc_n32_return_struct_flags(ffi_type *arg)
211 {
212   unsigned flags = 0;
213   unsigned index = 0;
214   unsigned small = FFI_TYPE_SMALLSTRUCT;
215   ffi_type *e;
216
217   /* Returning structures under n32 is a tricky thing.
218      A struct with only one or two floating point fields 
219      is returned in $f0 (and $f2 if necessary). Any other
220      struct results at most 128 bits are returned in $2
221      (the first 64 bits) and $3 (remainder, if necessary).
222      Larger structs are handled normally. */
223   
224   if (arg->size > 16)
225     return 0;
226
227   if (arg->size > 8)
228     small = FFI_TYPE_SMALLSTRUCT2;
229
230   e = arg->elements[0];
231   if (e->type == FFI_TYPE_DOUBLE)
232     flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
233   else if (e->type == FFI_TYPE_FLOAT)
234     flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
235
236   if (flags && (e = arg->elements[1]))
237     {
238       if (e->type == FFI_TYPE_DOUBLE)
239         flags += FFI_TYPE_DOUBLE;
240       else if (e->type == FFI_TYPE_FLOAT)
241         flags += FFI_TYPE_FLOAT;
242       else 
243         return small;
244
245       if (flags && (arg->elements[2]))
246         {
247           /* There are three arguments and the first two are 
248              floats! This must be passed the old way. */
249           return small;
250         }
251     }
252   else
253     if (!flags)
254       return small;
255
256   return flags;
257 }
258
259 #endif
260
261 /* Perform machine dependent cif processing */
262 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
263 {
264   cif->flags = 0;
265
266 #if _MIPS_SIM == _ABIO32
267   /* Set the flags necessary for O32 processing.  FFI_O32_SOFT_FLOAT
268    * does not have special handling for floating point args.
269    */
270
271   if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
272     {
273       if (cif->nargs > 0)
274         {
275           switch ((cif->arg_types)[0]->type)
276             {
277             case FFI_TYPE_FLOAT:
278             case FFI_TYPE_DOUBLE:
279               cif->flags += (cif->arg_types)[0]->type;
280               break;
281               
282             default:
283               break;
284             }
285
286           if (cif->nargs > 1)
287             {
288               /* Only handle the second argument if the first
289                  is a float or double. */
290               if (cif->flags)
291                 {
292                   switch ((cif->arg_types)[1]->type)
293                     {
294                     case FFI_TYPE_FLOAT:
295                     case FFI_TYPE_DOUBLE:
296                       cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
297                       break;
298                       
299                     default:
300                       break;
301                     }
302                 }
303             }
304         }
305     }
306       
307   /* Set the return type flag */
308
309   if (cif->abi == FFI_O32_SOFT_FLOAT)
310     {
311       switch (cif->rtype->type)
312         {
313         case FFI_TYPE_VOID:
314         case FFI_TYPE_STRUCT:
315           cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
316           break;
317
318         case FFI_TYPE_SINT64:
319         case FFI_TYPE_UINT64:
320         case FFI_TYPE_DOUBLE:
321           cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
322           break;
323       
324         case FFI_TYPE_FLOAT:
325         default:
326           cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
327           break;
328         }
329     }
330   else
331     {
332       /* FFI_O32 */      
333       switch (cif->rtype->type)
334         {
335         case FFI_TYPE_VOID:
336         case FFI_TYPE_STRUCT:
337         case FFI_TYPE_FLOAT:
338         case FFI_TYPE_DOUBLE:
339           cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
340           break;
341
342         case FFI_TYPE_SINT64:
343         case FFI_TYPE_UINT64:
344           cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
345           break;
346       
347         default:
348           cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
349           break;
350         }
351     }
352 #endif
353
354 #if _MIPS_SIM == _ABIN32
355   /* Set the flags necessary for N32 processing */
356   {
357     unsigned shift = 0;
358     unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
359     unsigned index = 0;
360
361     unsigned struct_flags = 0;
362
363     if (cif->rtype->type == FFI_TYPE_STRUCT)
364       {
365         struct_flags = calc_n32_return_struct_flags(cif->rtype);
366
367         if (struct_flags == 0)
368           {
369             /* This means that the structure is being passed as
370                a hidden argument */
371
372             shift = FFI_FLAG_BITS;
373             count = (cif->nargs < 7) ? cif->nargs : 7;
374
375             cif->rstruct_flag = !0;
376           }
377         else
378             cif->rstruct_flag = 0;
379       }
380     else
381       cif->rstruct_flag = 0;
382
383     while (count-- > 0)
384       {
385         switch ((cif->arg_types)[index]->type)
386           {
387           case FFI_TYPE_FLOAT:
388           case FFI_TYPE_DOUBLE:
389             cif->flags += ((cif->arg_types)[index]->type << shift);
390             shift += FFI_FLAG_BITS;
391             break;
392
393           case FFI_TYPE_STRUCT:
394             cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
395                                                 &shift);
396             break;
397
398           default:
399             shift += FFI_FLAG_BITS;
400           }
401
402         index++;
403       }
404
405   /* Set the return type flag */
406     switch (cif->rtype->type)
407       {
408       case FFI_TYPE_STRUCT:
409         {
410           if (struct_flags == 0)
411             {
412               /* The structure is returned through a hidden
413                  first argument. Do nothing, 'cause FFI_TYPE_VOID 
414                  is 0 */
415             }
416           else
417             {
418               /* The structure is returned via some tricky
419                  mechanism */
420               cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
421               cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
422             }
423           break;
424         }
425       
426       case FFI_TYPE_VOID:
427         /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
428         break;
429         
430       case FFI_TYPE_FLOAT:
431       case FFI_TYPE_DOUBLE:
432         cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
433         break;
434         
435       default:
436         cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
437         break;
438       }
439   }
440 #endif
441   
442   return FFI_OK;
443 }
444
445 /* Low level routine for calling O32 functions */
446 extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), 
447                         extended_cif *, unsigned, 
448                         unsigned, unsigned *, void (*)());
449
450 /* Low level routine for calling N32 functions */
451 extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 
452                         extended_cif *, unsigned, 
453                         unsigned, unsigned *, void (*)());
454
455 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
456 {
457   extended_cif ecif;
458
459   ecif.cif = cif;
460   ecif.avalue = avalue;
461   
462   /* If the return value is a struct and we don't have a return */
463   /* value address then we need to make one                     */
464   
465   if ((rvalue == NULL) && 
466       (cif->rtype->type == FFI_TYPE_STRUCT))
467     ecif.rvalue = alloca(cif->rtype->size);
468   else
469     ecif.rvalue = rvalue;
470     
471   switch (cif->abi) 
472     {
473 #if _MIPS_SIM == _ABIO32
474     case FFI_O32:
475     case FFI_O32_SOFT_FLOAT:
476       ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
477                    cif->flags, ecif.rvalue, fn);
478       break;
479 #endif
480
481 #if _MIPS_SIM == _ABIN32
482     case FFI_N32:
483       ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, 
484                    cif->flags, ecif.rvalue, fn);
485       break;
486 #endif
487
488     default:
489       FFI_ASSERT(0);
490       break;
491     }
492 }
493
494 #if FFI_CLOSURES  /* N32 not implemented yet, FFI_CLOSURES not defined */
495 #if defined(FFI_MIPS_O32)
496 extern void ffi_closure_O32(void);
497 #endif /* FFI_MIPS_O32 */
498
499 ffi_status
500 ffi_prep_closure (ffi_closure *closure,
501                   ffi_cif *cif,
502                   void (*fun)(ffi_cif*,void*,void**,void*),
503                   void *user_data)
504 {
505   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
506   unsigned int fn;
507   unsigned int ctx = (unsigned int) closure;
508
509 #if defined(FFI_MIPS_O32)
510   FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
511   fn = (unsigned int) ffi_closure_O32;
512 #else /* FFI_MIPS_N32 */
513   FFI_ASSERT(cif->abi == FFI_N32);
514   FFI_ASSERT(!"not implemented");
515 #endif /* FFI_MIPS_O32 */
516
517   tramp[0] = 0x3c190000 | (fn >> 16);     /* lui  $25,high(fn) */
518   tramp[1] = 0x37390000 | (fn & 0xffff);  /* ori  $25,low(fn)  */
519   tramp[2] = 0x3c080000 | (ctx >> 16);    /* lui  $8,high(ctx) */
520   tramp[3] = 0x03200008;                  /* jr   $25          */
521   tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori  $8,low(ctx)  */
522
523   closure->cif = cif;
524   closure->fun = fun;
525   closure->user_data = user_data;
526
527   /* XXX this is available on Linux, but anything else? */
528   cacheflush (tramp, FFI_TRAMPOLINE_SIZE, ICACHE);
529
530   return FFI_OK;
531 }
532
533 /*
534  * Decodes the arguments to a function, which will be stored on the
535  * stack. AR is the pointer to the beginning of the integer arguments
536  * (and, depending upon the arguments, some floating-point arguments
537  * as well). FPR is a pointer to the area where floating point
538  * registers have been saved, if any.
539  *
540  * RVALUE is the location where the function return value will be
541  * stored. CLOSURE is the prepared closure to invoke.
542  *
543  * This function should only be called from assembly, which is in
544  * turn called from a trampoline.
545  *
546  * Returns the function return type.
547  *
548  * Based on the similar routine for sparc.
549  */
550 int
551 ffi_closure_mips_inner_O32 (ffi_closure *closure,
552                             void *rvalue, ffi_arg *ar,
553                             double *fpr)
554 {
555   ffi_cif *cif;
556   void **avaluep;
557   ffi_arg *avalue;
558   ffi_type **arg_types;
559   int i, avn, argn, seen_int;
560
561   cif = closure->cif;
562   avalue = alloca (cif->nargs * sizeof (ffi_arg));
563   avaluep = alloca (cif->nargs * sizeof (ffi_arg));
564
565   seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
566   argn = 0;
567
568   if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
569     {
570       rvalue = (void *) ar[0];
571       argn = 1;
572     }
573
574   i = 0;
575   avn = cif->nargs;
576   arg_types = cif->arg_types;
577
578   while (i < avn)
579     {
580       if (i < 2 && !seen_int &&
581           (arg_types[i]->type == FFI_TYPE_FLOAT ||
582            arg_types[i]->type == FFI_TYPE_DOUBLE))
583         {
584 #ifdef __MIPSEB__
585           if (arg_types[i]->type == FFI_TYPE_FLOAT)
586             avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
587           else
588 #endif
589             avaluep[i] = (char *) &fpr[i];
590         }
591       else
592         {
593           if (arg_types[i]->alignment == 8 && (argn & 0x1))
594             argn++;
595           switch (arg_types[i]->type)
596             {
597               case FFI_TYPE_SINT8:
598                 avaluep[i] = &avalue[i];
599                 *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
600                 break;
601
602               case FFI_TYPE_UINT8:
603                 avaluep[i] = &avalue[i];
604                 *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
605                 break;
606                   
607               case FFI_TYPE_SINT16:
608                 avaluep[i] = &avalue[i];
609                 *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
610                 break;
611                   
612               case FFI_TYPE_UINT16:
613                 avaluep[i] = &avalue[i];
614                 *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
615                 break;
616
617               default:
618                 avaluep[i] = (char *) &ar[argn];
619                 break;
620             }
621           seen_int = 1;
622         }
623       argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
624       i++;
625     }
626
627   /* Invoke the closure. */
628   (closure->fun) (cif, rvalue, avaluep, closure->user_data);
629
630   if (cif->abi == FFI_O32_SOFT_FLOAT)
631     {
632       switch (cif->rtype->type)
633         {
634         case FFI_TYPE_FLOAT:
635           return FFI_TYPE_INT;
636         case FFI_TYPE_DOUBLE:
637           return FFI_TYPE_UINT64;
638         default:
639           return cif->rtype->type;
640         }
641     }
642   else
643     {
644       return cif->rtype->type;
645     }
646 }
647
648 #endif /* FFI_CLOSURES */