OSDN Git Service

Code drop from //branches/cupcake/...@124589
[android-x86/external-libffi.git] / src / sh / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Kaz Kojima
3            Copyright (c) 2008 Red Hat, Inc.
4    
5    SuperH 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 #define NGREGARG 4
34 #if defined(__SH4__)
35 #define NFREGARG 8
36 #endif
37
38 #if defined(__HITACHI__)
39 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
40 #else
41 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
42 #endif
43
44 /* If the structure has essentialy an unique element, return its type.  */
45 static int
46 simple_type (ffi_type *arg)
47 {
48   if (arg->type != FFI_TYPE_STRUCT)
49     return arg->type;
50   else if (arg->elements[1])
51     return FFI_TYPE_STRUCT;
52
53   return simple_type (arg->elements[0]);
54 }
55
56 static int
57 return_type (ffi_type *arg)
58 {
59   unsigned short type;
60
61   if (arg->type != FFI_TYPE_STRUCT)
62     return arg->type;
63
64   type = simple_type (arg->elements[0]);
65   if (! arg->elements[1])
66     {
67       switch (type)
68         {
69         case FFI_TYPE_SINT8:
70         case FFI_TYPE_UINT8:
71         case FFI_TYPE_SINT16:
72         case FFI_TYPE_UINT16:
73         case FFI_TYPE_SINT32:
74         case FFI_TYPE_UINT32:
75           return FFI_TYPE_INT;
76
77         default:
78           return type;
79         }
80     }
81
82   /* gcc uses r0/r1 pair for some kind of structures.  */
83   if (arg->size <= 2 * sizeof (int))
84     {
85       int i = 0;
86       ffi_type *e;
87
88       while ((e = arg->elements[i++]))
89         {
90           type = simple_type (e);
91           switch (type)
92             {
93             case FFI_TYPE_SINT32:
94             case FFI_TYPE_UINT32:
95             case FFI_TYPE_INT:
96             case FFI_TYPE_FLOAT:
97               return FFI_TYPE_UINT64;
98
99             default:
100               break;
101             }
102         }
103     }
104
105   return FFI_TYPE_STRUCT;
106 }
107
108 /* ffi_prep_args is called by the assembly routine once stack space
109    has been allocated for the function's arguments */
110
111 void ffi_prep_args(char *stack, extended_cif *ecif)
112 {
113   register unsigned int i;
114   register int tmp;
115   register unsigned int avn;
116   register void **p_argv;
117   register char *argp;
118   register ffi_type **p_arg;
119   int greg, ireg;
120 #if defined(__SH4__)
121   int freg = 0;
122 #endif
123
124   tmp = 0;
125   argp = stack;
126
127   if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
128     {
129       *(void **) argp = ecif->rvalue;
130       argp += 4;
131       ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
132     }
133   else
134     ireg = 0;
135
136   /* Set arguments for registers.  */
137   greg = ireg;
138   avn = ecif->cif->nargs;
139   p_argv = ecif->avalue;
140
141   for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
142     {
143       size_t z;
144
145       z = (*p_arg)->size;
146       if (z < sizeof(int))
147         {
148           if (greg++ >= NGREGARG)
149             continue;
150
151           z = sizeof(int);
152           switch ((*p_arg)->type)
153             {
154             case FFI_TYPE_SINT8:
155               *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
156               break;
157   
158             case FFI_TYPE_UINT8:
159               *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
160               break;
161   
162             case FFI_TYPE_SINT16:
163               *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
164               break;
165   
166             case FFI_TYPE_UINT16:
167               *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
168               break;
169   
170             case FFI_TYPE_STRUCT:
171               *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
172               break;
173
174             default:
175               FFI_ASSERT(0);
176             }
177           argp += z;
178         }
179       else if (z == sizeof(int))
180         {
181 #if defined(__SH4__)
182           if ((*p_arg)->type == FFI_TYPE_FLOAT)
183             {
184               if (freg++ >= NFREGARG)
185                 continue;
186             }
187           else
188 #endif
189             {
190               if (greg++ >= NGREGARG)
191                 continue;
192             }
193           *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
194           argp += z;
195         }
196 #if defined(__SH4__)
197       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
198         {
199           if (freg + 1 >= NFREGARG)
200             continue;
201           freg = (freg + 1) & ~1;
202           freg += 2;
203           memcpy (argp, *p_argv, z);
204           argp += z;
205         }
206 #endif
207       else
208         {
209           int n = (z + sizeof (int) - 1) / sizeof (int);
210 #if defined(__SH4__)
211           if (greg + n - 1 >= NGREGARG)
212             continue;
213 #else
214           if (greg >= NGREGARG)
215             continue;
216 #endif
217           greg += n;
218           memcpy (argp, *p_argv, z);
219           argp += n * sizeof (int);
220         }
221     }
222
223   /* Set arguments on stack.  */
224   greg = ireg;
225 #if defined(__SH4__)
226   freg = 0;
227 #endif
228   p_argv = ecif->avalue;
229
230   for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
231     {
232       size_t z;
233
234       z = (*p_arg)->size;
235       if (z < sizeof(int))
236         {
237           if (greg++ < NGREGARG)
238             continue;
239
240           z = sizeof(int);
241           switch ((*p_arg)->type)
242             {
243             case FFI_TYPE_SINT8:
244               *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
245               break;
246   
247             case FFI_TYPE_UINT8:
248               *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
249               break;
250   
251             case FFI_TYPE_SINT16:
252               *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
253               break;
254   
255             case FFI_TYPE_UINT16:
256               *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
257               break;
258   
259             case FFI_TYPE_STRUCT:
260               *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
261               break;
262
263             default:
264               FFI_ASSERT(0);
265             }
266           argp += z;
267         }
268       else if (z == sizeof(int))
269         {
270 #if defined(__SH4__)
271           if ((*p_arg)->type == FFI_TYPE_FLOAT)
272             {
273               if (freg++ < NFREGARG)
274                 continue;
275             }
276           else
277 #endif
278             {
279               if (greg++ < NGREGARG)
280                 continue;
281             }
282           *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
283           argp += z;
284         }
285 #if defined(__SH4__)
286       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
287         {
288           if (freg + 1 < NFREGARG)
289             {
290               freg = (freg + 1) & ~1;
291               freg += 2;
292               continue;
293             }
294           memcpy (argp, *p_argv, z);
295           argp += z;
296         }
297 #endif
298       else
299         {
300           int n = (z + sizeof (int) - 1) / sizeof (int);
301           if (greg + n - 1 < NGREGARG)
302             {
303               greg += n;
304               continue;
305             }
306 #if (! defined(__SH4__))
307           else if (greg < NGREGARG)
308             {
309               greg = NGREGARG;
310               continue;
311             }
312 #endif
313           memcpy (argp, *p_argv, z);
314           argp += n * sizeof (int);
315         }
316     }
317
318   return;
319 }
320
321 /* Perform machine dependent cif processing */
322 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
323 {
324   int i, j;
325   int size, type;
326   int n, m;
327   int greg;
328 #if defined(__SH4__)
329   int freg = 0;
330 #endif
331
332   cif->flags = 0;
333
334   greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
335           STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
336
337 #if defined(__SH4__)
338   for (i = j = 0; i < cif->nargs && j < 12; i++)
339     {
340       type = (cif->arg_types)[i]->type;
341       switch (type)
342         {
343         case FFI_TYPE_FLOAT:
344           if (freg >= NFREGARG)
345             continue;
346           freg++;
347           cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
348           j++;
349           break;
350
351         case FFI_TYPE_DOUBLE:
352           if ((freg + 1) >= NFREGARG)
353             continue;
354           freg = (freg + 1) & ~1;
355           freg += 2;
356           cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
357           j++;
358           break;
359               
360         default:
361           size = (cif->arg_types)[i]->size;
362           n = (size + sizeof (int) - 1) / sizeof (int);
363           if (greg + n - 1 >= NGREGARG)
364                 continue;
365           greg += n;
366           for (m = 0; m < n; m++)
367             cif->flags += FFI_TYPE_INT << (2 * j++);
368           break;
369         }
370     }
371 #else
372   for (i = j = 0; i < cif->nargs && j < 4; i++)
373     {
374       size = (cif->arg_types)[i]->size;
375       n = (size + sizeof (int) - 1) / sizeof (int);
376       if (greg >= NGREGARG)
377         continue;
378       else if (greg + n - 1 >= NGREGARG)
379         n = NGREGARG - greg;
380       greg += n;
381       for (m = 0; m < n; m++)
382         cif->flags += FFI_TYPE_INT << (2 * j++);
383     }
384 #endif
385
386   /* Set the return type flag */
387   switch (cif->rtype->type)
388     {
389     case FFI_TYPE_STRUCT:
390       cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
391       break;
392
393     case FFI_TYPE_VOID:
394     case FFI_TYPE_FLOAT:
395     case FFI_TYPE_DOUBLE:
396     case FFI_TYPE_SINT64:
397     case FFI_TYPE_UINT64:
398       cif->flags += (unsigned) cif->rtype->type << 24;
399       break;
400
401     default:
402       cif->flags += FFI_TYPE_INT << 24;
403       break;
404     }
405
406   return FFI_OK;
407 }
408
409 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
410                           unsigned, unsigned, unsigned *, void (*fn)(void));
411
412 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
413 {
414   extended_cif ecif;
415   UINT64 trvalue;
416
417   ecif.cif = cif;
418   ecif.avalue = avalue;
419   
420   /* If the return value is a struct and we don't have a return */
421   /* value address then we need to make one                     */
422
423   if (cif->rtype->type == FFI_TYPE_STRUCT
424       && return_type (cif->rtype) != FFI_TYPE_STRUCT)
425     ecif.rvalue = &trvalue;
426   else if ((rvalue == NULL) && 
427       (cif->rtype->type == FFI_TYPE_STRUCT))
428     {
429       ecif.rvalue = alloca(cif->rtype->size);
430     }
431   else
432     ecif.rvalue = rvalue;
433
434   switch (cif->abi) 
435     {
436     case FFI_SYSV:
437       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
438                     fn);
439       break;
440     default:
441       FFI_ASSERT(0);
442       break;
443     }
444
445   if (rvalue
446       && cif->rtype->type == FFI_TYPE_STRUCT
447       && return_type (cif->rtype) != FFI_TYPE_STRUCT)
448     memcpy (rvalue, &trvalue, cif->rtype->size);
449 }
450
451 extern void ffi_closure_SYSV (void);
452 #if defined(__SH4__)
453 extern void __ic_invalidate (void *line);
454 #endif
455
456 ffi_status
457 ffi_prep_closure_loc (ffi_closure* closure,
458                       ffi_cif* cif,
459                       void (*fun)(ffi_cif*, void*, void**, void*),
460                       void *user_data,
461                       void *codeloc)
462 {
463   unsigned int *tramp;
464   unsigned int insn;
465
466   FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
467
468   tramp = (unsigned int *) &closure->tramp[0];
469   /* Set T bit if the function returns a struct pointed with R2.  */
470   insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
471           ? 0x0018 /* sett */
472           : 0x0008 /* clrt */);
473
474 #ifdef __LITTLE_ENDIAN__
475   tramp[0] = 0xd301d102;
476   tramp[1] = 0x0000412b | (insn << 16);
477 #else
478   tramp[0] = 0xd102d301;
479   tramp[1] = 0x412b0000 | insn;
480 #endif
481   *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
482   *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
483
484   closure->cif = cif;
485   closure->fun = fun;
486   closure->user_data = user_data;
487
488 #if defined(__SH4__)
489   /* Flush the icache.  */
490   __ic_invalidate(codeloc);
491 #endif
492
493   return FFI_OK;
494 }
495
496 /* Basically the trampoline invokes ffi_closure_SYSV, and on 
497  * entry, r3 holds the address of the closure.
498  * After storing the registers that could possibly contain
499  * parameters to be passed into the stack frame and setting
500  * up space for a return value, ffi_closure_SYSV invokes the 
501  * following helper function to do most of the work.
502  */
503
504 #ifdef __LITTLE_ENDIAN__
505 #define OFS_INT8        0
506 #define OFS_INT16       0
507 #else
508 #define OFS_INT8        3
509 #define OFS_INT16       2
510 #endif
511
512 int
513 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, 
514                          unsigned long *pgr, unsigned long *pfr, 
515                          unsigned long *pst)
516 {
517   void **avalue;
518   ffi_type **p_arg;
519   int i, avn;
520   int ireg, greg = 0;
521 #if defined(__SH4__)
522   int freg = 0;
523 #endif
524   ffi_cif *cif; 
525
526   cif = closure->cif;
527   avalue = alloca(cif->nargs * sizeof(void *));
528
529   /* Copy the caller's structure return value address so that the closure
530      returns the data directly to the caller.  */
531   if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
532     {
533       rvalue = (void *) *pgr++;
534       ireg = 1;
535     }
536   else
537     ireg = 0;
538
539   cif = closure->cif;
540   greg = ireg;
541   avn = cif->nargs;
542
543   /* Grab the addresses of the arguments from the stack frame.  */
544   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
545     {
546       size_t z;
547
548       z = (*p_arg)->size;
549       if (z < sizeof(int))
550         {
551           if (greg++ >= NGREGARG)
552             continue;
553
554           z = sizeof(int);
555           switch ((*p_arg)->type)
556             {
557             case FFI_TYPE_SINT8:
558             case FFI_TYPE_UINT8:
559               avalue[i] = (((char *)pgr) + OFS_INT8);
560               break;
561   
562             case FFI_TYPE_SINT16:
563             case FFI_TYPE_UINT16:
564               avalue[i] = (((char *)pgr) + OFS_INT16);
565               break;
566   
567             case FFI_TYPE_STRUCT:
568               avalue[i] = pgr;
569               break;
570
571             default:
572               FFI_ASSERT(0);
573             }
574           pgr++;
575         }
576       else if (z == sizeof(int))
577         {
578 #if defined(__SH4__)
579           if ((*p_arg)->type == FFI_TYPE_FLOAT)
580             {
581               if (freg++ >= NFREGARG)
582                 continue;
583               avalue[i] = pfr;
584               pfr++;
585             }
586           else
587 #endif
588             {
589               if (greg++ >= NGREGARG)
590                 continue;
591               avalue[i] = pgr;
592               pgr++;
593             }
594         }
595 #if defined(__SH4__)
596       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
597         {
598           if (freg + 1 >= NFREGARG)
599             continue;
600           if (freg & 1)
601             pfr++;
602           freg = (freg + 1) & ~1;
603           freg += 2;
604           avalue[i] = pfr;
605           pfr += 2;
606         }
607 #endif
608       else
609         {
610           int n = (z + sizeof (int) - 1) / sizeof (int);
611 #if defined(__SH4__)
612           if (greg + n - 1 >= NGREGARG)
613             continue;
614 #else
615           if (greg >= NGREGARG)
616             continue;
617 #endif
618           greg += n;
619           avalue[i] = pgr;
620           pgr += n;
621         }
622     }
623
624   greg = ireg;
625 #if defined(__SH4__)
626   freg = 0;
627 #endif
628
629   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
630     {
631       size_t z;
632
633       z = (*p_arg)->size;
634       if (z < sizeof(int))
635         {
636           if (greg++ < NGREGARG)
637             continue;
638
639           z = sizeof(int);
640           switch ((*p_arg)->type)
641             {
642             case FFI_TYPE_SINT8:
643             case FFI_TYPE_UINT8:
644               avalue[i] = (((char *)pst) + OFS_INT8);
645               break;
646   
647             case FFI_TYPE_SINT16:
648             case FFI_TYPE_UINT16:
649               avalue[i] = (((char *)pst) + OFS_INT16);
650               break;
651   
652             case FFI_TYPE_STRUCT:
653               avalue[i] = pst;
654               break;
655
656             default:
657               FFI_ASSERT(0);
658             }
659           pst++;
660         }
661       else if (z == sizeof(int))
662         {
663 #if defined(__SH4__)
664           if ((*p_arg)->type == FFI_TYPE_FLOAT)
665             {
666               if (freg++ < NFREGARG)
667                 continue;
668             }
669           else
670 #endif
671             {
672               if (greg++ < NGREGARG)
673                 continue;
674             }
675           avalue[i] = pst;
676           pst++;
677         }
678 #if defined(__SH4__)
679       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
680         {
681           if (freg + 1 < NFREGARG)
682             {
683               freg = (freg + 1) & ~1;
684               freg += 2;
685               continue;
686             }
687           avalue[i] = pst;
688           pst += 2;
689         }
690 #endif
691       else
692         {
693           int n = (z + sizeof (int) - 1) / sizeof (int);
694           if (greg + n - 1 < NGREGARG)
695             {
696               greg += n;
697               continue;
698             }
699 #if (! defined(__SH4__))
700           else if (greg < NGREGARG)
701             {
702               greg += n;
703               pst += greg - NGREGARG;
704               continue;
705             }
706 #endif
707           avalue[i] = pst;
708           pst += n;
709         }
710     }
711
712   (closure->fun) (cif, rvalue, avalue, closure->user_data);
713
714   /* Tell ffi_closure_SYSV how to perform return type promotions.  */
715   return return_type (cif->rtype);
716 }