OSDN Git Service

6c41603d703522a5933694686b7f0b0d22a0564f
[pf3gnuchains/gcc-fork.git] / libffi / src / mips / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1996 Cygnus Solutions
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 <sgidefs.h>
27 #include <ffi.h>
28 #include <ffi_common.h>
29
30 #include <stdlib.h>
31
32 #if _MIPS_SIM == _MIPS_SIM_NABI32
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 int avn;
55   register void **p_argv;
56   register char *argp;
57   register ffi_type **p_arg;
58
59 #if _MIPS_SIM == _MIPS_SIM_NABI32
60   /* If more than 8 double words are used, the remainder go
61      on the stack. We reorder stuff on the stack here to 
62      support this easily. */
63   if (bytes > 8 * SIZEOF_ARG)
64     argp = &stack[bytes - (8 * SIZEOF_ARG)];
65   else
66     argp = stack;
67 #else
68   argp = stack;
69 #endif
70
71   memset(stack, 0, bytes);
72
73 #if _MIPS_SIM == _MIPS_SIM_NABI32
74   if ( ecif->cif->rstruct_flag != 0 )
75 #else
76   if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
77 #endif  
78     {
79       *(SLOT_TYPE_UNSIGNED *) argp = (SLOT_TYPE_UNSIGNED) ecif->rvalue;
80       argp += sizeof(SLOT_TYPE_UNSIGNED);
81       FIX_ARGP;
82     }
83
84   avn = ecif->cif->nargs;
85   p_argv = ecif->avalue;
86
87   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
88        i && avn;
89        i--, p_arg++)
90     {
91       size_t z;
92
93       /* Align if necessary */
94       if (((*p_arg)->alignment - 1) & (unsigned) argp) {
95         argp = (char *) ALIGN(argp, (*p_arg)->alignment);
96         FIX_ARGP;
97       }
98
99 #if _MIPS_SIM == _MIPS_SIM_ABI32
100 #define OFFSET 0
101 #else
102 #define OFFSET sizeof(int)
103 #endif      
104
105       if (avn) 
106         {
107           avn--;
108           z = (*p_arg)->size;
109           if (z < sizeof(SLOT_TYPE_UNSIGNED))
110             {
111               z = sizeof(SLOT_TYPE_UNSIGNED);
112
113               switch ((*p_arg)->type)
114                 {
115                 case FFI_TYPE_SINT8:
116                   *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT8 *)(* p_argv);
117                   break;
118                   
119                 case FFI_TYPE_UINT8:
120                   *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT8 *)(* p_argv);
121                   break;
122                   
123                 case FFI_TYPE_SINT16:
124                   *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT16 *)(* p_argv);
125                   break;
126                   
127                 case FFI_TYPE_UINT16:
128                   *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT16 *)(* p_argv);
129                   break;
130                   
131                 case FFI_TYPE_SINT32:
132                   *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT32 *)(* p_argv);
133                   break;
134                   
135                 case FFI_TYPE_UINT32:
136                 case FFI_TYPE_POINTER:
137                   *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT32 *)(* p_argv);
138                   break;
139
140                   /* This can only happen with 64bit slots */
141                 case FFI_TYPE_FLOAT:
142                   *(float *) argp = *(float *)(* p_argv);
143                   break;
144
145                   /* Handle small structures */
146                 case FFI_TYPE_STRUCT:
147                   memcpy(argp, *p_argv, (*p_arg)->size);
148                   break;
149
150                 default:
151                   FFI_ASSERT(0);
152                 }
153             }
154           else
155             {
156 #if _MIPS_SIM == _MIPS_SIM_ABI32              
157               memcpy(argp, *p_argv, z);
158 #else
159               {
160                 unsigned end = (unsigned) argp+z;
161                 unsigned cap = (unsigned) stack+bytes;
162
163                 /* Check if the data will fit within the register
164                    space. Handle it if it doesn't. */
165
166                 if (end <= cap)
167                   memcpy(argp, *p_argv, z);
168                 else
169                   {
170                     unsigned portion = end - cap;
171
172                     memcpy(argp, *p_argv, portion);
173                     argp = stack;
174                     memcpy(argp, 
175                            (void*)((unsigned)(*p_argv)+portion), z - portion);
176                   }
177               }
178 #endif
179             }
180           p_argv++;
181           argp += z;
182           FIX_ARGP;
183         }
184     }
185   
186   return;
187 }
188
189 #if _MIPS_SIM == _MIPS_SIM_NABI32
190
191 /* The n32 spec says that if "a chunk consists solely of a double 
192    float field (but not a double, which is part of a union), it
193    is passed in a floating point register. Any other chunk is
194    passed in an integer register". This code traverses structure
195    definitions and generates the appropriate flags. */
196
197 unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
198 {
199   unsigned flags = 0;
200   unsigned index = 0;
201
202   ffi_type *e;
203
204   while (e = arg->elements[index])
205     {
206       if (e->type == FFI_TYPE_DOUBLE)
207         {
208           flags += (FFI_TYPE_DOUBLE << *shift);
209           *shift += FFI_FLAG_BITS;
210         }
211       else if (e->type == FFI_TYPE_STRUCT)
212           flags += calc_n32_struct_flags(e, shift);
213       else
214         *shift += FFI_FLAG_BITS;
215
216       index++;
217     }
218
219   return flags;
220 }
221
222 unsigned calc_n32_return_struct_flags(ffi_type *arg)
223 {
224   unsigned flags = 0;
225   unsigned index = 0;
226   unsigned small = FFI_TYPE_SMALLSTRUCT;
227   ffi_type *e;
228
229   /* Returning structures under n32 is a tricky thing.
230      A struct with only one or two floating point fields 
231      is returned in $f0 (and $f2 if necessary). Any other
232      struct results at most 128 bits are returned in $2
233      (the first 64 bits) and $3 (remainder, if necessary).
234      Larger structs are handled normally. */
235   
236   if (arg->size > 16)
237     return 0;
238
239   if (arg->size > 8)
240     small = FFI_TYPE_SMALLSTRUCT2;
241
242   e = arg->elements[0];
243   if (e->type == FFI_TYPE_DOUBLE)
244     flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
245   else if (e->type == FFI_TYPE_FLOAT)
246     flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
247
248   if (flags && (e = arg->elements[1]))
249     {
250       if (e->type == FFI_TYPE_DOUBLE)
251         flags += FFI_TYPE_DOUBLE;
252       else if (e->type == FFI_TYPE_FLOAT)
253         flags += FFI_TYPE_FLOAT;
254       else 
255         return small;
256
257       if (flags && (arg->elements[2]))
258         {
259           /* There are three arguments and the first two are 
260              floats! This must be passed the old way. */
261           return small;
262         }
263     }
264   else
265     if (!flags)
266       return small;
267
268   return flags;
269 }
270
271 #endif
272
273 /* Perform machine dependent cif processing */
274 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
275 {
276   cif->flags = 0;
277
278 #if _MIPS_SIM == _MIPS_SIM_ABI32
279   /* Set the flags necessary for O32 processing */
280
281   if (cif->rtype->type != FFI_TYPE_STRUCT)
282     {
283       if (cif->nargs > 0)
284         {
285           switch ((cif->arg_types)[0]->type)
286             {
287             case FFI_TYPE_FLOAT:
288             case FFI_TYPE_DOUBLE:
289               cif->flags += (cif->arg_types)[0]->type;
290               break;
291               
292             default:
293               break;
294             }
295
296           if (cif->nargs > 1)
297             {
298               /* Only handle the second argument if the first
299                  is a float or double. */
300               if (cif->flags)
301                 {
302                   switch ((cif->arg_types)[1]->type)
303                     {
304                     case FFI_TYPE_FLOAT:
305                     case FFI_TYPE_DOUBLE:
306                       cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
307                       break;
308                       
309                     default:
310                       break;
311                     }
312                 }
313             }
314         }
315     }
316       
317   /* Set the return type flag */
318   switch (cif->rtype->type)
319     {
320     case FFI_TYPE_VOID:
321     case FFI_TYPE_STRUCT:
322     case FFI_TYPE_FLOAT:
323     case FFI_TYPE_DOUBLE:
324       cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
325       break;
326       
327     default:
328       cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
329       break;
330     }
331 #endif
332
333 #if _MIPS_SIM == _MIPS_SIM_NABI32
334   /* Set the flags necessary for N32 processing */
335   {
336     unsigned shift = 0;
337     unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
338     unsigned index = 0;
339
340     unsigned struct_flags = 0;
341
342     if (cif->rtype->type == FFI_TYPE_STRUCT)
343       {
344         struct_flags = calc_n32_return_struct_flags(cif->rtype);
345
346         if (struct_flags == 0)
347           {
348             /* This means that the structure is being passed as
349                a hidden argument */
350
351             shift = FFI_FLAG_BITS;
352             count = (cif->nargs < 7) ? cif->nargs : 7;
353
354             cif->rstruct_flag = !0;
355           }
356         else
357             cif->rstruct_flag = 0;
358       }
359     else
360       cif->rstruct_flag = 0;
361
362     while (count-- > 0)
363       {
364         switch ((cif->arg_types)[index]->type)
365           {
366           case FFI_TYPE_FLOAT:
367           case FFI_TYPE_DOUBLE:
368             cif->flags += ((cif->arg_types)[index]->type << shift);
369             shift += FFI_FLAG_BITS;
370             break;
371
372           case FFI_TYPE_STRUCT:
373             cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
374                                                 &shift);
375             break;
376
377           default:
378             shift += FFI_FLAG_BITS;
379           }
380
381         index++;
382       }
383
384   /* Set the return type flag */
385     switch (cif->rtype->type)
386       {
387       case FFI_TYPE_STRUCT:
388         {
389           if (struct_flags == 0)
390             {
391               /* The structure is returned through a hidden
392                  first argument. Do nothing, 'cause FFI_TYPE_VOID 
393                  is 0 */
394             }
395           else
396             {
397               /* The structure is returned via some tricky
398                  mechanism */
399               cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
400               cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
401             }
402           break;
403         }
404       
405       case FFI_TYPE_VOID:
406         /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
407         break;
408         
409       case FFI_TYPE_FLOAT:
410       case FFI_TYPE_DOUBLE:
411         cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
412         break;
413         
414       default:
415         cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
416         break;
417       }
418   }
419 #endif
420   
421   return FFI_OK;
422 }
423
424 /* Low level routine for calling O32 functions */
425 extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), 
426                         extended_cif *, unsigned, 
427                         unsigned, unsigned *, void (*)());
428
429 /* Low level routine for calling N32 functions */
430 extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 
431                         extended_cif *, unsigned, 
432                         unsigned, unsigned *, void (*)());
433
434 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
435 {
436   extended_cif ecif;
437
438   ecif.cif = cif;
439   ecif.avalue = avalue;
440   
441   /* If the return value is a struct and we don't have a return */
442   /* value address then we need to make one                     */
443   
444   if ((rvalue == NULL) && 
445       (cif->rtype->type == FFI_TYPE_STRUCT))
446     ecif.rvalue = alloca(cif->rtype->size);
447   else
448     ecif.rvalue = rvalue;
449     
450   switch (cif->abi) 
451     {
452 #if _MIPS_SIM == _MIPS_SIM_ABI32
453     case FFI_O32:
454       ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
455                    cif->flags, ecif.rvalue, fn);
456       break;
457 #endif
458
459 #if _MIPS_SIM == _MIPS_SIM_NABI32
460     case FFI_N32:
461       ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, 
462                    cif->flags, ecif.rvalue, fn);
463       break;
464 #endif
465
466     default:
467       FFI_ASSERT(0);
468       break;
469     }
470 }