• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2002-2008, 2012 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 essentially 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   if (cif->abi != FFI_SYSV)
467     return FFI_BAD_ABI;
468 
469   tramp = (unsigned int *) &closure->tramp[0];
470   /* Set T bit if the function returns a struct pointed with R2.  */
471   insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
472 	  ? 0x0018 /* sett */
473 	  : 0x0008 /* clrt */);
474 
475 #ifdef __LITTLE_ENDIAN__
476   tramp[0] = 0xd301d102;
477   tramp[1] = 0x0000412b | (insn << 16);
478 #else
479   tramp[0] = 0xd102d301;
480   tramp[1] = 0x412b0000 | insn;
481 #endif
482   *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
483   *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
484 
485   closure->cif = cif;
486   closure->fun = fun;
487   closure->user_data = user_data;
488 
489 #if defined(__SH4__)
490   /* Flush the icache.  */
491   __ic_invalidate(codeloc);
492 #endif
493 
494   return FFI_OK;
495 }
496 
497 /* Basically the trampoline invokes ffi_closure_SYSV, and on
498  * entry, r3 holds the address of the closure.
499  * After storing the registers that could possibly contain
500  * parameters to be passed into the stack frame and setting
501  * up space for a return value, ffi_closure_SYSV invokes the
502  * following helper function to do most of the work.
503  */
504 
505 #ifdef __LITTLE_ENDIAN__
506 #define OFS_INT8	0
507 #define OFS_INT16	0
508 #else
509 #define OFS_INT8	3
510 #define OFS_INT16	2
511 #endif
512 
513 int
ffi_closure_helper_SYSV(ffi_closure * closure,void * rvalue,unsigned long * pgr,unsigned long * pfr,unsigned long * pst)514 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
515 			 unsigned long *pgr, unsigned long *pfr,
516 			 unsigned long *pst)
517 {
518   void **avalue;
519   ffi_type **p_arg;
520   int i, avn;
521   int ireg, greg = 0;
522 #if defined(__SH4__)
523   int freg = 0;
524 #endif
525   ffi_cif *cif;
526 
527   cif = closure->cif;
528   avalue = alloca(cif->nargs * sizeof(void *));
529 
530   /* Copy the caller's structure return value address so that the closure
531      returns the data directly to the caller.  */
532   if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
533     {
534       rvalue = (void *) *pgr++;
535       ireg = 1;
536     }
537   else
538     ireg = 0;
539 
540   cif = closure->cif;
541   greg = ireg;
542   avn = cif->nargs;
543 
544   /* Grab the addresses of the arguments from the stack frame.  */
545   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
546     {
547       size_t z;
548 
549       z = (*p_arg)->size;
550       if (z < sizeof(int))
551 	{
552 	  if (greg++ >= NGREGARG)
553 	    continue;
554 
555 	  z = sizeof(int);
556 	  switch ((*p_arg)->type)
557 	    {
558 	    case FFI_TYPE_SINT8:
559 	    case FFI_TYPE_UINT8:
560 	      avalue[i] = (((char *)pgr) + OFS_INT8);
561 	      break;
562 
563 	    case FFI_TYPE_SINT16:
564 	    case FFI_TYPE_UINT16:
565 	      avalue[i] = (((char *)pgr) + OFS_INT16);
566 	      break;
567 
568 	    case FFI_TYPE_STRUCT:
569 	      avalue[i] = pgr;
570 	      break;
571 
572 	    default:
573 	      FFI_ASSERT(0);
574 	    }
575 	  pgr++;
576 	}
577       else if (z == sizeof(int))
578 	{
579 #if defined(__SH4__)
580 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
581 	    {
582 	      if (freg++ >= NFREGARG)
583 		continue;
584 	      avalue[i] = pfr;
585 	      pfr++;
586 	    }
587 	  else
588 #endif
589 	    {
590 	      if (greg++ >= NGREGARG)
591 		continue;
592 	      avalue[i] = pgr;
593 	      pgr++;
594 	    }
595 	}
596 #if defined(__SH4__)
597       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
598 	{
599 	  if (freg + 1 >= NFREGARG)
600 	    continue;
601 	  if (freg & 1)
602 	    pfr++;
603 	  freg = (freg + 1) & ~1;
604 	  freg += 2;
605 	  avalue[i] = pfr;
606 	  pfr += 2;
607 	}
608 #endif
609       else
610 	{
611 	  int n = (z + sizeof (int) - 1) / sizeof (int);
612 #if defined(__SH4__)
613 	  if (greg + n - 1 >= NGREGARG)
614 	    continue;
615 #else
616 	  if (greg >= NGREGARG)
617 	    continue;
618 #endif
619 	  greg += n;
620 	  avalue[i] = pgr;
621 	  pgr += n;
622 	}
623     }
624 
625   greg = ireg;
626 #if defined(__SH4__)
627   freg = 0;
628 #endif
629 
630   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
631     {
632       size_t z;
633 
634       z = (*p_arg)->size;
635       if (z < sizeof(int))
636 	{
637 	  if (greg++ < NGREGARG)
638 	    continue;
639 
640 	  z = sizeof(int);
641 	  switch ((*p_arg)->type)
642 	    {
643 	    case FFI_TYPE_SINT8:
644 	    case FFI_TYPE_UINT8:
645 	      avalue[i] = (((char *)pst) + OFS_INT8);
646 	      break;
647 
648 	    case FFI_TYPE_SINT16:
649 	    case FFI_TYPE_UINT16:
650 	      avalue[i] = (((char *)pst) + OFS_INT16);
651 	      break;
652 
653 	    case FFI_TYPE_STRUCT:
654 	      avalue[i] = pst;
655 	      break;
656 
657 	    default:
658 	      FFI_ASSERT(0);
659 	    }
660 	  pst++;
661 	}
662       else if (z == sizeof(int))
663 	{
664 #if defined(__SH4__)
665 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
666 	    {
667 	      if (freg++ < NFREGARG)
668 		continue;
669 	    }
670 	  else
671 #endif
672 	    {
673 	      if (greg++ < NGREGARG)
674 		continue;
675 	    }
676 	  avalue[i] = pst;
677 	  pst++;
678 	}
679 #if defined(__SH4__)
680       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
681 	{
682 	  if (freg + 1 < NFREGARG)
683 	    {
684 	      freg = (freg + 1) & ~1;
685 	      freg += 2;
686 	      continue;
687 	    }
688 	  avalue[i] = pst;
689 	  pst += 2;
690 	}
691 #endif
692       else
693 	{
694 	  int n = (z + sizeof (int) - 1) / sizeof (int);
695 	  if (greg + n - 1 < NGREGARG)
696 	    {
697 	      greg += n;
698 	      continue;
699 	    }
700 #if (! defined(__SH4__))
701 	  else if (greg < NGREGARG)
702 	    {
703 	      greg += n;
704 	      pst += greg - NGREGARG;
705 	      continue;
706 	    }
707 #endif
708 	  avalue[i] = pst;
709 	  pst += n;
710 	}
711     }
712 
713   (closure->fun) (cif, rvalue, avalue, closure->user_data);
714 
715   /* Tell ffi_closure_SYSV how to perform return type promotions.  */
716   return return_type (cif->rtype);
717 }
718