OSDN Git Service

2004-08-22 Matthias Klose <doko@debian.org>
[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   register int i;
54   register void **p_argv;
55   register char *argp;
56   register 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 * FFI_SIZEOF_ARG)
63     argp = &stack[bytes - (8 * FFI_SIZEOF_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
89       /* Align if necessary */
90       if (((*p_arg)->alignment - 1) & (unsigned) argp) {
91         argp = (char *) ALIGN(argp, (*p_arg)->alignment);
92         FIX_ARGP;
93       }
94
95 #if _MIPS_SIM == _ABIO32
96 #define OFFSET 0
97 #else
98 #define OFFSET sizeof(int)
99 #endif      
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                   *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT8 *)(* p_argv);
110                   break;
111                   
112                 case FFI_TYPE_UINT8:
113                   *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT8 *)(* p_argv);
114                   break;
115                   
116                 case FFI_TYPE_SINT16:
117                   *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT16 *)(* p_argv);
118                   break;
119                   
120                 case FFI_TYPE_UINT16:
121                   *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT16 *)(* p_argv);
122                   break;
123                   
124                 case FFI_TYPE_SINT32:
125                   *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT32 *)(* p_argv);
126                   break;
127                   
128                 case FFI_TYPE_UINT32:
129                 case FFI_TYPE_POINTER:
130                   *(UINT32 *) &argp[OFFSET] = (UINT32)*(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                   memcpy(argp, *p_argv, (*p_arg)->size);
141                   break;
142
143                 default:
144                   FFI_ASSERT(0);
145                 }
146             }
147           else
148             {
149 #if _MIPS_SIM == _ABIO32              
150               memcpy(argp, *p_argv, z);
151 #else
152               {
153                 unsigned end = (unsigned) argp+z;
154                 unsigned cap = (unsigned) stack+bytes;
155
156                 /* Check if the data will fit within the register
157                    space. Handle it if it doesn't. */
158
159                 if (end <= cap)
160                   memcpy(argp, *p_argv, z);
161                 else
162                   {
163                     unsigned portion = end - cap;
164
165                     memcpy(argp, *p_argv, portion);
166                     argp = stack;
167                     memcpy(argp, 
168                            (void*)((unsigned)(*p_argv)+portion), z - portion);
169                   }
170               }
171 #endif
172             }
173           p_argv++;
174           argp += z;
175           FIX_ARGP;
176     }
177   
178   return;
179 }
180
181 #if _MIPS_SIM == _ABIN32
182
183 /* The n32 spec says that if "a chunk consists solely of a double 
184    float field (but not a double, which is part of a union), it
185    is passed in a floating point register. Any other chunk is
186    passed in an integer register". This code traverses structure
187    definitions and generates the appropriate flags. */
188
189 unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
190 {
191   unsigned flags = 0;
192   unsigned index = 0;
193
194   ffi_type *e;
195
196   while (e = arg->elements[index])
197     {
198       if (e->type == FFI_TYPE_DOUBLE)
199         {
200           flags += (FFI_TYPE_DOUBLE << *shift);
201           *shift += FFI_FLAG_BITS;
202         }
203       else if (e->type == FFI_TYPE_STRUCT)
204           flags += calc_n32_struct_flags(e, shift);
205       else
206         *shift += FFI_FLAG_BITS;
207
208       index++;
209     }
210
211   return flags;
212 }
213
214 unsigned calc_n32_return_struct_flags(ffi_type *arg)
215 {
216   unsigned flags = 0;
217   unsigned index = 0;
218   unsigned small = FFI_TYPE_SMALLSTRUCT;
219   ffi_type *e;
220
221   /* Returning structures under n32 is a tricky thing.
222      A struct with only one or two floating point fields 
223      is returned in $f0 (and $f2 if necessary). Any other
224      struct results at most 128 bits are returned in $2
225      (the first 64 bits) and $3 (remainder, if necessary).
226      Larger structs are handled normally. */
227   
228   if (arg->size > 16)
229     return 0;
230
231   if (arg->size > 8)
232     small = FFI_TYPE_SMALLSTRUCT2;
233
234   e = arg->elements[0];
235   if (e->type == FFI_TYPE_DOUBLE)
236     flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
237   else if (e->type == FFI_TYPE_FLOAT)
238     flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
239
240   if (flags && (e = arg->elements[1]))
241     {
242       if (e->type == FFI_TYPE_DOUBLE)
243         flags += FFI_TYPE_DOUBLE;
244       else if (e->type == FFI_TYPE_FLOAT)
245         flags += FFI_TYPE_FLOAT;
246       else 
247         return small;
248
249       if (flags && (arg->elements[2]))
250         {
251           /* There are three arguments and the first two are 
252              floats! This must be passed the old way. */
253           return small;
254         }
255     }
256   else
257     if (!flags)
258       return small;
259
260   return flags;
261 }
262
263 #endif
264
265 /* Perform machine dependent cif processing */
266 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
267 {
268   cif->flags = 0;
269
270 #if _MIPS_SIM == _ABIO32
271   /* Set the flags necessary for O32 processing */
272
273   if (cif->rtype->type != FFI_TYPE_STRUCT)
274     {
275       if (cif->nargs > 0)
276         {
277           switch ((cif->arg_types)[0]->type)
278             {
279             case FFI_TYPE_FLOAT:
280             case FFI_TYPE_DOUBLE:
281               cif->flags += (cif->arg_types)[0]->type;
282               break;
283               
284             default:
285               break;
286             }
287
288           if (cif->nargs > 1)
289             {
290               /* Only handle the second argument if the first
291                  is a float or double. */
292               if (cif->flags)
293                 {
294                   switch ((cif->arg_types)[1]->type)
295                     {
296                     case FFI_TYPE_FLOAT:
297                     case FFI_TYPE_DOUBLE:
298                       cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
299                       break;
300                       
301                     default:
302                       break;
303                     }
304                 }
305             }
306         }
307     }
308       
309   /* Set the return type flag */
310   switch (cif->rtype->type)
311     {
312     case FFI_TYPE_VOID:
313     case FFI_TYPE_STRUCT:
314     case FFI_TYPE_FLOAT:
315     case FFI_TYPE_DOUBLE:
316       cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
317       break;
318
319     case FFI_TYPE_SINT64:
320     case FFI_TYPE_UINT64:
321       cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
322       break;
323       
324     default:
325       cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
326       break;
327     }
328 #endif
329
330 #if _MIPS_SIM == _ABIN32
331   /* Set the flags necessary for N32 processing */
332   {
333     unsigned shift = 0;
334     unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
335     unsigned index = 0;
336
337     unsigned struct_flags = 0;
338
339     if (cif->rtype->type == FFI_TYPE_STRUCT)
340       {
341         struct_flags = calc_n32_return_struct_flags(cif->rtype);
342
343         if (struct_flags == 0)
344           {
345             /* This means that the structure is being passed as
346                a hidden argument */
347
348             shift = FFI_FLAG_BITS;
349             count = (cif->nargs < 7) ? cif->nargs : 7;
350
351             cif->rstruct_flag = !0;
352           }
353         else
354             cif->rstruct_flag = 0;
355       }
356     else
357       cif->rstruct_flag = 0;
358
359     while (count-- > 0)
360       {
361         switch ((cif->arg_types)[index]->type)
362           {
363           case FFI_TYPE_FLOAT:
364           case FFI_TYPE_DOUBLE:
365             cif->flags += ((cif->arg_types)[index]->type << shift);
366             shift += FFI_FLAG_BITS;
367             break;
368
369           case FFI_TYPE_STRUCT:
370             cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
371                                                 &shift);
372             break;
373
374           default:
375             shift += FFI_FLAG_BITS;
376           }
377
378         index++;
379       }
380
381   /* Set the return type flag */
382     switch (cif->rtype->type)
383       {
384       case FFI_TYPE_STRUCT:
385         {
386           if (struct_flags == 0)
387             {
388               /* The structure is returned through a hidden
389                  first argument. Do nothing, 'cause FFI_TYPE_VOID 
390                  is 0 */
391             }
392           else
393             {
394               /* The structure is returned via some tricky
395                  mechanism */
396               cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
397               cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
398             }
399           break;
400         }
401       
402       case FFI_TYPE_VOID:
403         /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
404         break;
405         
406       case FFI_TYPE_FLOAT:
407       case FFI_TYPE_DOUBLE:
408         cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
409         break;
410         
411       default:
412         cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
413         break;
414       }
415   }
416 #endif
417   
418   return FFI_OK;
419 }
420
421 /* Low level routine for calling O32 functions */
422 extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), 
423                         extended_cif *, unsigned, 
424                         unsigned, unsigned *, void (*)());
425
426 /* Low level routine for calling N32 functions */
427 extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 
428                         extended_cif *, unsigned, 
429                         unsigned, unsigned *, void (*)());
430
431 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
432 {
433   extended_cif ecif;
434
435   ecif.cif = cif;
436   ecif.avalue = avalue;
437   
438   /* If the return value is a struct and we don't have a return */
439   /* value address then we need to make one                     */
440   
441   if ((rvalue == NULL) && 
442       (cif->rtype->type == FFI_TYPE_STRUCT))
443     ecif.rvalue = alloca(cif->rtype->size);
444   else
445     ecif.rvalue = rvalue;
446     
447   switch (cif->abi) 
448     {
449 #if _MIPS_SIM == _ABIO32
450     case FFI_O32:
451       ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
452                    cif->flags, ecif.rvalue, fn);
453       break;
454 #endif
455
456 #if _MIPS_SIM == _ABIN32
457     case FFI_N32:
458       ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, 
459                    cif->flags, ecif.rvalue, fn);
460       break;
461 #endif
462
463     default:
464       FFI_ASSERT(0);
465       break;
466     }
467 }
468
469 #if FFI_CLOSURES  /* N32 not implemented yet, FFI_CLOSURES not defined */
470 #if defined(FFI_MIPS_O32)
471 extern void ffi_closure_O32(void);
472 #endif /* FFI_MIPS_O32 */
473
474 ffi_status
475 ffi_prep_closure (ffi_closure *closure,
476                   ffi_cif *cif,
477                   void (*fun)(ffi_cif*,void*,void**,void*),
478                   void *user_data)
479 {
480   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
481   unsigned int fn;
482   unsigned int ctx = (unsigned int) closure;
483
484 #if defined(FFI_MIPS_O32)
485   FFI_ASSERT(cif->abi == FFI_O32);
486   fn = (unsigned int) ffi_closure_O32;
487 #else /* FFI_MIPS_N32 */
488   FFI_ASSERT(cif->abi == FFI_N32);
489   FFI_ASSERT(!"not implemented");
490 #endif /* FFI_MIPS_O32 */
491
492   tramp[0] = 0x3c190000 | (fn >> 16);     /* lui  $25,high(fn) */
493   tramp[1] = 0x3c080000 | (ctx >> 16);    /* lui  $8,high(ctx) */
494   tramp[2] = 0x37390000 | (fn & 0xffff);  /* ori  $25,low(fn)  */
495   tramp[3] = 0x03200008;                  /* jr   $25          */
496   tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori  $8,low(ctx)  */
497
498   closure->cif = cif;
499   closure->fun = fun;
500   closure->user_data = user_data;
501
502   /* XXX this is available on Linux, but anything else? */
503   cacheflush (tramp, FFI_TRAMPOLINE_SIZE, ICACHE);
504
505   return FFI_OK;
506 }
507
508 /*
509  * Decodes the arguments to a function, which will be stored on the
510  * stack. AR is the pointer to the beginning of the integer arguments
511  * (and, depending upon the arguments, some floating-point arguments
512  * as well). FPR is a pointer to the area where floating point
513  * registers have been saved, if any.
514  *
515  * RVALUE is the location where the function return value will be
516  * stored. CLOSURE is the prepared closure to invoke.
517  *
518  * This function should only be called from assembly, which is in
519  * turn called from a trampoline.
520  *
521  * Returns the function return type.
522  *
523  * Based on the similar routine for sparc.
524  */
525 int
526 ffi_closure_mips_inner_O32 (ffi_closure *closure,
527                             void *rvalue, unsigned long *ar,
528                             double *fpr)
529 {
530   ffi_cif *cif;
531   void **avalue;
532   ffi_type **arg_types;
533   int i, avn, argn, seen_int;
534
535   cif = closure->cif;
536   avalue = alloca (cif->nargs * sizeof (void *));
537
538   seen_int = 0;
539   argn = 0;
540
541   if (cif->flags == FFI_TYPE_STRUCT)
542     {
543       rvalue = (void *) ar[0];
544       argn = 1;
545     }
546
547   i = 0;
548   avn = cif->nargs;
549   arg_types = cif->arg_types;
550
551   while (i < avn)
552     {
553       if (i < 2 && !seen_int &&
554           (arg_types[i]->type == FFI_TYPE_FLOAT ||
555            arg_types[i]->type == FFI_TYPE_DOUBLE))
556         {
557           avalue[i] = ((char *) &fpr[i]);
558         }
559       else
560         {
561           /* 8-byte arguments are always 8-byte aligned. */
562           if (arg_types[i]->size == 8 && (argn & 0x1))
563             argn++;
564           /* Float arguments take up two register slots. The float word
565              is the upper one. */
566           if (argn == 2 && arg_types[i]->type == FFI_TYPE_FLOAT)
567             argn++;
568           avalue[i] = ((char *) &ar[argn]);
569           seen_int = 1;
570         }
571       argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
572       i++;
573     }
574
575   /* Invoke the closure. */
576   (closure->fun) (cif, rvalue, avalue, closure->user_data);
577
578   return cif->rtype->type;
579 }
580
581 #endif /* FFI_CLOSURES */