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