OSDN Git Service

* src/sparc/ffi.c (ffi_closure_sparc_inner_v9): Properly align 'long
[pf3gnuchains/gcc-fork.git] / libffi / src / sparc / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1996, 2003, 2004, 2007, 2008 Red Hat, Inc.
3    
4    SPARC 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
33 /* ffi_prep_args is called by the assembly routine once stack space
34    has been allocated for the function's arguments */
35
36 void ffi_prep_args_v8(char *stack, extended_cif *ecif)
37 {
38   int i;
39   void **p_argv;
40   char *argp;
41   ffi_type **p_arg;
42
43   /* Skip 16 words for the window save area */
44   argp = stack + 16*sizeof(int);
45
46   /* This should only really be done when we are returning a structure,
47      however, it's faster just to do it all the time...
48
49   if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
50   *(int *) argp = (long)ecif->rvalue;
51
52   /* And 1 word for the  structure return value. */
53   argp += sizeof(int);
54
55 #ifdef USING_PURIFY
56   /* Purify will probably complain in our assembly routine, unless we
57      zero out this memory. */
58
59   ((int*)argp)[0] = 0;
60   ((int*)argp)[1] = 0;
61   ((int*)argp)[2] = 0;
62   ((int*)argp)[3] = 0;
63   ((int*)argp)[4] = 0;
64   ((int*)argp)[5] = 0;
65 #endif
66
67   p_argv = ecif->avalue;
68
69   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
70     {
71       size_t z;
72
73           if ((*p_arg)->type == FFI_TYPE_STRUCT
74 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
75               || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
76 #endif
77               )
78             {
79               *(unsigned int *) argp = (unsigned long)(* p_argv);
80               z = sizeof(int);
81             }
82           else
83             {
84               z = (*p_arg)->size;
85               if (z < sizeof(int))
86                 {
87                   z = sizeof(int);
88                   switch ((*p_arg)->type)
89                     {
90                     case FFI_TYPE_SINT8:
91                       *(signed int *) argp = *(SINT8 *)(* p_argv);
92                       break;
93                       
94                     case FFI_TYPE_UINT8:
95                       *(unsigned int *) argp = *(UINT8 *)(* p_argv);
96                       break;
97                       
98                     case FFI_TYPE_SINT16:
99                       *(signed int *) argp = *(SINT16 *)(* p_argv);
100                       break;
101                       
102                     case FFI_TYPE_UINT16:
103                       *(unsigned int *) argp = *(UINT16 *)(* p_argv);
104                       break;
105
106                     default:
107                       FFI_ASSERT(0);
108                     }
109                 }
110               else
111                 {
112                   memcpy(argp, *p_argv, z);
113                 }
114             }
115           p_argv++;
116           argp += z;
117     }
118   
119   return;
120 }
121
122 int ffi_prep_args_v9(char *stack, extended_cif *ecif)
123 {
124   int i, ret = 0;
125   int tmp;
126   void **p_argv;
127   char *argp;
128   ffi_type **p_arg;
129
130   tmp = 0;
131
132   /* Skip 16 words for the window save area */
133   argp = stack + 16*sizeof(long long);
134
135 #ifdef USING_PURIFY
136   /* Purify will probably complain in our assembly routine, unless we
137      zero out this memory. */
138
139   ((long long*)argp)[0] = 0;
140   ((long long*)argp)[1] = 0;
141   ((long long*)argp)[2] = 0;
142   ((long long*)argp)[3] = 0;
143   ((long long*)argp)[4] = 0;
144   ((long long*)argp)[5] = 0;
145 #endif
146
147   p_argv = ecif->avalue;
148
149   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
150       ecif->cif->rtype->size > 32)
151     {
152       *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
153       argp += sizeof(long long);
154       tmp = 1;
155     }
156
157   for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
158        i++, p_arg++)
159     {
160       size_t z;
161
162       z = (*p_arg)->size;
163       switch ((*p_arg)->type)
164         {
165         case FFI_TYPE_STRUCT:
166           if (z > 16)
167             {
168               /* For structures larger than 16 bytes we pass reference.  */
169               *(unsigned long long *) argp = (unsigned long)* p_argv;
170               argp += sizeof(long long);
171               tmp++;
172               p_argv++;
173               continue;
174             }
175           /* FALLTHROUGH */
176         case FFI_TYPE_FLOAT:
177         case FFI_TYPE_DOUBLE:
178 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
179         case FFI_TYPE_LONGDOUBLE:
180 #endif
181           ret = 1; /* We should promote into FP regs as well as integer.  */
182           break;
183         }
184       if (z < sizeof(long long))
185         {
186           switch ((*p_arg)->type)
187             {
188             case FFI_TYPE_SINT8:
189               *(signed long long *) argp = *(SINT8 *)(* p_argv);
190               break;
191
192             case FFI_TYPE_UINT8:
193               *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
194               break;
195
196             case FFI_TYPE_SINT16:
197               *(signed long long *) argp = *(SINT16 *)(* p_argv);
198               break;
199
200             case FFI_TYPE_UINT16:
201               *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
202               break;
203
204             case FFI_TYPE_SINT32:
205               *(signed long long *) argp = *(SINT32 *)(* p_argv);
206               break;
207
208             case FFI_TYPE_UINT32:
209               *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
210               break;
211
212             case FFI_TYPE_FLOAT:
213               *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
214               break;
215
216             case FFI_TYPE_STRUCT:
217               memcpy(argp, *p_argv, z);
218               break;
219
220             default:
221               FFI_ASSERT(0);
222             }
223           z = sizeof(long long);
224           tmp++;
225         }
226       else if (z == sizeof(long long))
227         {
228           memcpy(argp, *p_argv, z);
229           z = sizeof(long long);
230           tmp++;
231         }
232       else
233         {
234           if ((tmp & 1) && (*p_arg)->alignment > 8)
235             {
236               tmp++;
237               argp += sizeof(long long);
238             }
239           memcpy(argp, *p_argv, z);
240           z = 2 * sizeof(long long);
241           tmp += 2;
242         }
243       p_argv++;
244       argp += z;
245     }
246
247   return ret;
248 }
249
250 /* Perform machine dependent cif processing */
251 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
252 {
253   int wordsize;
254
255   if (cif->abi != FFI_V9)
256     {
257       wordsize = 4;
258
259       /* If we are returning a struct, this will already have been added.
260          Otherwise we need to add it because it's always got to be there! */
261
262       if (cif->rtype->type != FFI_TYPE_STRUCT)
263         cif->bytes += wordsize;
264
265       /* sparc call frames require that space is allocated for 6 args,
266          even if they aren't used. Make that space if necessary. */
267   
268       if (cif->bytes < 4*6+4)
269         cif->bytes = 4*6+4;
270     }
271   else
272     {
273       wordsize = 8;
274
275       /* sparc call frames require that space is allocated for 6 args,
276          even if they aren't used. Make that space if necessary. */
277   
278       if (cif->bytes < 8*6)
279         cif->bytes = 8*6;
280     }
281
282   /* Adjust cif->bytes. to include 16 words for the window save area,
283      and maybe the struct/union return pointer area, */
284
285   cif->bytes += 16 * wordsize;
286
287   /* The stack must be 2 word aligned, so round bytes up
288      appropriately. */
289
290   cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
291
292   /* Set the return type flag */
293   switch (cif->rtype->type)
294     {
295     case FFI_TYPE_VOID:
296     case FFI_TYPE_FLOAT:
297     case FFI_TYPE_DOUBLE:
298 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
299     case FFI_TYPE_LONGDOUBLE:
300 #endif
301       cif->flags = cif->rtype->type;
302       break;
303
304     case FFI_TYPE_STRUCT:
305       if (cif->abi == FFI_V9 && cif->rtype->size > 32)
306         cif->flags = FFI_TYPE_VOID;
307       else
308         cif->flags = FFI_TYPE_STRUCT;
309       break;
310
311     case FFI_TYPE_SINT8:
312     case FFI_TYPE_UINT8:
313     case FFI_TYPE_SINT16:
314     case FFI_TYPE_UINT16:
315       if (cif->abi == FFI_V9)
316         cif->flags = FFI_TYPE_INT;
317       else
318         cif->flags = cif->rtype->type;
319       break;
320
321     case FFI_TYPE_SINT64:
322     case FFI_TYPE_UINT64:
323       if (cif->abi == FFI_V9)
324         cif->flags = FFI_TYPE_INT;
325       else
326         cif->flags = FFI_TYPE_SINT64;
327       break;
328
329     default:
330       cif->flags = FFI_TYPE_INT;
331       break;
332     }
333   return FFI_OK;
334 }
335
336 int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
337 {
338   ffi_type **ptr = &arg->elements[0];
339
340   while (*ptr != NULL)
341     {
342       if (off & ((*ptr)->alignment - 1))
343         off = ALIGN(off, (*ptr)->alignment);
344
345       switch ((*ptr)->type)
346         {
347         case FFI_TYPE_STRUCT:
348           off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
349           off = ALIGN(off, FFI_SIZEOF_ARG);
350           break;
351         case FFI_TYPE_FLOAT:
352         case FFI_TYPE_DOUBLE:
353 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
354         case FFI_TYPE_LONGDOUBLE:
355 #endif
356           memmove(ret + off, flt + off, (*ptr)->size);
357           off += (*ptr)->size;
358           break;
359         default:
360           memmove(ret + off, intg + off, (*ptr)->size);
361           off += (*ptr)->size;
362           break;
363         }
364       ptr++;
365     }
366   return off;
367 }
368
369
370 #ifdef SPARC64
371 extern int ffi_call_v9(void *, extended_cif *, unsigned, 
372                        unsigned, unsigned *, void (*fn)(void));
373 #else
374 extern int ffi_call_v8(void *, extended_cif *, unsigned, 
375                        unsigned, unsigned *, void (*fn)(void));
376 #endif
377
378 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
379 {
380   extended_cif ecif;
381   void *rval = rvalue;
382
383   ecif.cif = cif;
384   ecif.avalue = avalue;
385
386   /* If the return value is a struct and we don't have a return */
387   /* value address then we need to make one                     */
388
389   ecif.rvalue = rvalue;
390   if (cif->rtype->type == FFI_TYPE_STRUCT)
391     {
392       if (cif->rtype->size <= 32)
393         rval = alloca(64);
394       else
395         {
396           rval = NULL;
397           if (rvalue == NULL)
398             ecif.rvalue = alloca(cif->rtype->size);
399         }
400     }
401
402   switch (cif->abi) 
403     {
404     case FFI_V8:
405 #ifdef SPARC64
406       /* We don't yet support calling 32bit code from 64bit */
407       FFI_ASSERT(0);
408 #else
409       ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, 
410                   cif->flags, rvalue, fn);
411 #endif
412       break;
413     case FFI_V9:
414 #ifdef SPARC64
415       ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
416                   cif->flags, rval, fn);
417       if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
418         ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
419 #else
420       /* And vice versa */
421       FFI_ASSERT(0);
422 #endif
423       break;
424     default:
425       FFI_ASSERT(0);
426       break;
427     }
428
429 }
430
431
432 #ifdef SPARC64
433 extern void ffi_closure_v9(void);
434 #else
435 extern void ffi_closure_v8(void);
436 #endif
437
438 ffi_status
439 ffi_prep_closure_loc (ffi_closure* closure,
440                       ffi_cif* cif,
441                       void (*fun)(ffi_cif*, void*, void**, void*),
442                       void *user_data,
443                       void *codeloc)
444 {
445   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
446   unsigned long fn;
447 #ifdef SPARC64
448   /* Trampoline address is equal to the closure address.  We take advantage
449      of that to reduce the trampoline size by 8 bytes. */
450   FFI_ASSERT (cif->abi == FFI_V9);
451   fn = (unsigned long) ffi_closure_v9;
452   tramp[0] = 0x83414000;        /* rd   %pc, %g1        */
453   tramp[1] = 0xca586010;        /* ldx  [%g1+16], %g5   */
454   tramp[2] = 0x81c14000;        /* jmp  %g5             */
455   tramp[3] = 0x01000000;        /* nop                  */
456   *((unsigned long *) &tramp[4]) = fn;
457 #else
458   unsigned long ctx = (unsigned long) codeloc;
459   FFI_ASSERT (cif->abi == FFI_V8);
460   fn = (unsigned long) ffi_closure_v8;
461   tramp[0] = 0x03000000 | fn >> 10;     /* sethi %hi(fn), %g1   */
462   tramp[1] = 0x05000000 | ctx >> 10;    /* sethi %hi(ctx), %g2  */
463   tramp[2] = 0x81c06000 | (fn & 0x3ff); /* jmp   %g1+%lo(fn)    */
464   tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or    %g2, %lo(ctx)  */
465 #endif
466
467   closure->cif = cif;
468   closure->fun = fun;
469   closure->user_data = user_data;
470
471   /* Flush the Icache.  FIXME: alignment isn't certain, assume 8 bytes */
472 #ifdef SPARC64
473   asm volatile ("flush  %0" : : "r" (closure) : "memory");
474   asm volatile ("flush  %0" : : "r" (((char *) closure) + 8) : "memory");
475 #else
476   asm volatile ("iflush %0" : : "r" (closure) : "memory");
477   asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory");
478 #endif
479
480   return FFI_OK;
481 }
482
483 int
484 ffi_closure_sparc_inner_v8(ffi_closure *closure,
485   void *rvalue, unsigned long *gpr, unsigned long *scratch)
486 {
487   ffi_cif *cif;
488   ffi_type **arg_types;
489   void **avalue;
490   int i, argn;
491
492   cif = closure->cif;
493   arg_types = cif->arg_types;
494   avalue = alloca(cif->nargs * sizeof(void *));
495
496   /* Copy the caller's structure return address so that the closure
497      returns the data directly to the caller.  */
498   if (cif->flags == FFI_TYPE_STRUCT
499 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE  
500       || cif->flags == FFI_TYPE_LONGDOUBLE
501 #endif
502      )
503     rvalue = (void *) gpr[0];
504
505   /* Always skip the structure return address.  */
506   argn = 1;
507
508   /* Grab the addresses of the arguments from the stack frame.  */
509   for (i = 0; i < cif->nargs; i++)
510     {
511       if (arg_types[i]->type == FFI_TYPE_STRUCT
512 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
513           || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
514 #endif
515          )
516         {
517           /* Straight copy of invisible reference.  */
518           avalue[i] = (void *)gpr[argn++];
519         }
520       else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
521                || arg_types[i]->type == FFI_TYPE_SINT64
522                || arg_types[i]->type == FFI_TYPE_UINT64)
523                /* gpr is 8-byte aligned.  */
524                && (argn % 2) != 0)
525         {
526           /* Align on a 8-byte boundary.  */
527           scratch[0] = gpr[argn];
528           scratch[1] = gpr[argn+1];
529           avalue[i] = scratch;
530           scratch -= 2;
531           argn += 2;
532         }
533       else
534         {
535           /* Always right-justify.  */
536           argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
537           avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
538         }
539     }
540
541   /* Invoke the closure.  */
542   (closure->fun) (cif, rvalue, avalue, closure->user_data);
543
544   /* Tell ffi_closure_sparc how to perform return type promotions.  */
545   return cif->rtype->type;
546 }
547
548 int
549 ffi_closure_sparc_inner_v9(ffi_closure *closure,
550   void *rvalue, unsigned long *gpr, double *fpr)
551 {
552   ffi_cif *cif;
553   ffi_type **arg_types;
554   void **avalue;
555   int i, argn, fp_slot_max;
556
557   cif = closure->cif;
558   arg_types = cif->arg_types;
559   avalue = alloca(cif->nargs * sizeof(void *));
560
561   /* Copy the caller's structure return address so that the closure
562      returns the data directly to the caller.  */
563   if (cif->flags == FFI_TYPE_VOID
564       && cif->rtype->type == FFI_TYPE_STRUCT)
565     {
566       rvalue = (void *) gpr[0];
567       /* Skip the structure return address.  */
568       argn = 1;
569     }
570   else
571     argn = 0;
572
573   fp_slot_max = 16 - argn;
574
575   /* Grab the addresses of the arguments from the stack frame.  */
576   for (i = 0; i < cif->nargs; i++)
577     {
578       if (arg_types[i]->type == FFI_TYPE_STRUCT)
579         {
580           if (arg_types[i]->size > 16)
581             {
582               /* Straight copy of invisible reference.  */
583               avalue[i] = (void *)gpr[argn++];
584             }
585           else
586             {
587               /* Left-justify.  */
588               ffi_v9_layout_struct(arg_types[i],
589                                    0,
590                                    (char *) &gpr[argn],
591                                    (char *) &gpr[argn],
592                                    (char *) &fpr[argn]);
593               avalue[i] = &gpr[argn];
594               argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
595             }
596         }
597       else
598         {
599           /* Right-justify.  */
600           argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
601
602           /* Align on a 16-byte boundary.  */
603 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
604           if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
605             argn++;
606 #endif
607           if (i < fp_slot_max
608               && (arg_types[i]->type == FFI_TYPE_FLOAT
609                   || arg_types[i]->type == FFI_TYPE_DOUBLE
610 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
611                   || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
612 #endif
613                   ))
614             avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
615           else
616             avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
617         }
618     }
619
620   /* Invoke the closure.  */
621   (closure->fun) (cif, rvalue, avalue, closure->user_data);
622
623   /* Tell ffi_closure_sparc how to perform return type promotions.  */
624   return cif->rtype->type;
625 }