• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
simple_type(ffi_type * arg)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
return_type(ffi_type * arg)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 
ffi_prep_args(char * stack,extended_cif * ecif)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 */
ffi_prep_cif_machdep(ffi_cif * cif)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 
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)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
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)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
ffi_closure_helper_SYSV(ffi_closure * closure,void * rvalue,unsigned long * pgr,unsigned long * pfr,unsigned long * pst)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 }
717