OSDN Git Service

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