1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Kaz Kojima
4 SuperH Foreign Function Interface
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:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 DEALINGS IN THE SOFTWARE.
25 ----------------------------------------------------------------------- */
28 #include <ffi_common.h>
37 #if defined(__HITACHI__)
38 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
40 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
43 /* If the structure has essentialy an unique element, return its type. */
45 simple_type (ffi_type
*arg
)
47 if (arg
->type
!= FFI_TYPE_STRUCT
)
49 else if (arg
->elements
[1])
50 return FFI_TYPE_STRUCT
;
52 return simple_type (arg
->elements
[0]);
56 return_type (ffi_type
*arg
)
60 if (arg
->type
!= FFI_TYPE_STRUCT
)
63 type
= simple_type (arg
->elements
[0]);
64 if (! arg
->elements
[1])
81 /* gcc uses r0/r1 pair for some kind of structures. */
82 if (arg
->size
<= 2 * sizeof (int))
87 while ((e
= arg
->elements
[i
++]))
89 type
= simple_type (e
);
96 return FFI_TYPE_UINT64
;
104 return FFI_TYPE_STRUCT
;
107 /* ffi_prep_args is called by the assembly routine once stack space
108 has been allocated for the function's arguments */
110 void ffi_prep_args(char *stack
, extended_cif
*ecif
)
112 register unsigned int i
;
114 register unsigned int avn
;
115 register void **p_argv
;
117 register ffi_type
**p_arg
;
126 if (return_type (ecif
->cif
->rtype
) == FFI_TYPE_STRUCT
)
128 *(void **) argp
= ecif
->rvalue
;
130 ireg
= STRUCT_VALUE_ADDRESS_WITH_ARG
? 1 : 0;
135 /* Set arguments for registers. */
137 avn
= ecif
->cif
->nargs
;
138 p_argv
= ecif
->avalue
;
140 for (i
= 0, p_arg
= ecif
->cif
->arg_types
; i
< avn
; i
++, p_arg
++, p_argv
++)
147 if (greg
++ >= NGREGARG
)
151 switch ((*p_arg
)->type
)
154 *(signed int *) argp
= (signed int)*(SINT8
*)(* p_argv
);
158 *(unsigned int *) argp
= (unsigned int)*(UINT8
*)(* p_argv
);
161 case FFI_TYPE_SINT16
:
162 *(signed int *) argp
= (signed int)*(SINT16
*)(* p_argv
);
165 case FFI_TYPE_UINT16
:
166 *(unsigned int *) argp
= (unsigned int)*(UINT16
*)(* p_argv
);
169 case FFI_TYPE_STRUCT
:
170 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
178 else if (z
== sizeof(int))
181 if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
183 if (freg
++ >= NFREGARG
)
189 if (greg
++ >= NGREGARG
)
192 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
196 else if ((*p_arg
)->type
== FFI_TYPE_DOUBLE
)
198 if (freg
+ 1 >= NFREGARG
)
200 freg
= (freg
+ 1) & ~1;
202 memcpy (argp
, *p_argv
, z
);
208 int n
= (z
+ sizeof (int) - 1) / sizeof (int);
210 if (greg
+ n
- 1 >= NGREGARG
)
213 if (greg
>= NGREGARG
)
217 memcpy (argp
, *p_argv
, z
);
218 argp
+= n
* sizeof (int);
222 /* Set arguments on stack. */
227 p_argv
= ecif
->avalue
;
229 for (i
= 0, p_arg
= ecif
->cif
->arg_types
; i
< avn
; i
++, p_arg
++, p_argv
++)
236 if (greg
++ < NGREGARG
)
240 switch ((*p_arg
)->type
)
243 *(signed int *) argp
= (signed int)*(SINT8
*)(* p_argv
);
247 *(unsigned int *) argp
= (unsigned int)*(UINT8
*)(* p_argv
);
250 case FFI_TYPE_SINT16
:
251 *(signed int *) argp
= (signed int)*(SINT16
*)(* p_argv
);
254 case FFI_TYPE_UINT16
:
255 *(unsigned int *) argp
= (unsigned int)*(UINT16
*)(* p_argv
);
258 case FFI_TYPE_STRUCT
:
259 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
267 else if (z
== sizeof(int))
270 if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
272 if (freg
++ < NFREGARG
)
278 if (greg
++ < NGREGARG
)
281 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
285 else if ((*p_arg
)->type
== FFI_TYPE_DOUBLE
)
287 if (freg
+ 1 < NFREGARG
)
289 freg
= (freg
+ 1) & ~1;
293 memcpy (argp
, *p_argv
, z
);
299 int n
= (z
+ sizeof (int) - 1) / sizeof (int);
300 if (greg
+ n
- 1 < NGREGARG
)
305 #if (! defined(__SH4__))
306 else if (greg
< NGREGARG
)
312 memcpy (argp
, *p_argv
, z
);
313 argp
+= n
* sizeof (int);
320 /* Perform machine dependent cif processing */
321 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
333 greg
= ((return_type (cif
->rtype
) == FFI_TYPE_STRUCT
) &&
334 STRUCT_VALUE_ADDRESS_WITH_ARG
) ? 1 : 0;
337 for (i
= j
= 0; i
< cif
->nargs
&& j
< 12; i
++)
339 type
= (cif
->arg_types
)[i
]->type
;
343 if (freg
>= NFREGARG
)
346 cif
->flags
+= ((cif
->arg_types
)[i
]->type
) << (2 * j
);
350 case FFI_TYPE_DOUBLE
:
351 if ((freg
+ 1) >= NFREGARG
)
353 freg
= (freg
+ 1) & ~1;
355 cif
->flags
+= ((cif
->arg_types
)[i
]->type
) << (2 * j
);
360 size
= (cif
->arg_types
)[i
]->size
;
361 n
= (size
+ sizeof (int) - 1) / sizeof (int);
362 if (greg
+ n
- 1 >= NGREGARG
)
365 for (m
= 0; m
< n
; m
++)
366 cif
->flags
+= FFI_TYPE_INT
<< (2 * j
++);
371 for (i
= j
= 0; i
< cif
->nargs
&& j
< 4; i
++)
373 size
= (cif
->arg_types
)[i
]->size
;
374 n
= (size
+ sizeof (int) - 1) / sizeof (int);
375 if (greg
>= NGREGARG
)
377 else if (greg
+ n
- 1 >= NGREGARG
)
380 for (m
= 0; m
< n
; m
++)
381 cif
->flags
+= FFI_TYPE_INT
<< (2 * j
++);
385 /* Set the return type flag */
386 switch (cif
->rtype
->type
)
388 case FFI_TYPE_STRUCT
:
389 cif
->flags
+= (unsigned) (return_type (cif
->rtype
)) << 24;
394 case FFI_TYPE_DOUBLE
:
395 case FFI_TYPE_SINT64
:
396 case FFI_TYPE_UINT64
:
397 cif
->flags
+= (unsigned) cif
->rtype
->type
<< 24;
401 cif
->flags
+= FFI_TYPE_INT
<< 24;
408 extern void ffi_call_SYSV(void (*)(char *, extended_cif
*), extended_cif
*,
409 unsigned, unsigned, unsigned *, void (*fn
)());
411 void ffi_call(ffi_cif
*cif
, void (*fn
)(), void *rvalue
, void **avalue
)
417 ecif
.avalue
= avalue
;
419 /* If the return value is a struct and we don't have a return */
420 /* value address then we need to make one */
422 if (cif
->rtype
->type
== FFI_TYPE_STRUCT
423 && return_type (cif
->rtype
) != FFI_TYPE_STRUCT
)
424 ecif
.rvalue
= &trvalue
;
425 else if ((rvalue
== NULL
) &&
426 (cif
->rtype
->type
== FFI_TYPE_STRUCT
))
428 ecif
.rvalue
= alloca(cif
->rtype
->size
);
431 ecif
.rvalue
= rvalue
;
436 ffi_call_SYSV(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
, ecif
.rvalue
,
445 && cif
->rtype
->type
== FFI_TYPE_STRUCT
446 && return_type (cif
->rtype
) != FFI_TYPE_STRUCT
)
447 memcpy (rvalue
, &trvalue
, cif
->rtype
->size
);
450 extern void ffi_closure_SYSV (void);
452 extern void __ic_invalidate (void *line
);
456 ffi_prep_closure_loc (ffi_closure
* closure
,
458 void (*fun
)(ffi_cif
*, void*, void**, void*),
465 FFI_ASSERT (cif
->abi
== FFI_GCC_SYSV
);
467 tramp
= (unsigned int *) &closure
->tramp
[0];
468 /* Set T bit if the function returns a struct pointed with R2. */
469 insn
= (return_type (cif
->rtype
) == FFI_TYPE_STRUCT
471 : 0x0008 /* clrt */);
473 #ifdef __LITTLE_ENDIAN__
474 tramp
[0] = 0xd301d102;
475 tramp
[1] = 0x0000412b | (insn
<< 16);
477 tramp
[0] = 0xd102d301;
478 tramp
[1] = 0x412b0000 | insn
;
480 *(void **) &tramp
[2] = (void *)codeloc
; /* ctx */
481 *(void **) &tramp
[3] = (void *)ffi_closure_SYSV
; /* funaddr */
485 closure
->user_data
= user_data
;
488 /* Flush the icache. */
489 __ic_invalidate(codeloc
);
495 /* Basically the trampoline invokes ffi_closure_SYSV, and on
496 * entry, r3 holds the address of the closure.
497 * After storing the registers that could possibly contain
498 * parameters to be passed into the stack frame and setting
499 * up space for a return value, ffi_closure_SYSV invokes the
500 * following helper function to do most of the work.
503 #ifdef __LITTLE_ENDIAN__
512 ffi_closure_helper_SYSV (ffi_closure
*closure
, void *rvalue
,
513 unsigned long *pgr
, unsigned long *pfr
,
526 avalue
= alloca(cif
->nargs
* sizeof(void *));
528 /* Copy the caller's structure return value address so that the closure
529 returns the data directly to the caller. */
530 if (cif
->rtype
->type
== FFI_TYPE_STRUCT
&& STRUCT_VALUE_ADDRESS_WITH_ARG
)
532 rvalue
= (void *) *pgr
++;
542 /* Grab the addresses of the arguments from the stack frame. */
543 for (i
= 0, p_arg
= cif
->arg_types
; i
< avn
; i
++, p_arg
++)
550 if (greg
++ >= NGREGARG
)
554 switch ((*p_arg
)->type
)
558 avalue
[i
] = (((char *)pgr
) + OFS_INT8
);
561 case FFI_TYPE_SINT16
:
562 case FFI_TYPE_UINT16
:
563 avalue
[i
] = (((char *)pgr
) + OFS_INT16
);
566 case FFI_TYPE_STRUCT
:
575 else if (z
== sizeof(int))
578 if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
580 if (freg
++ >= NFREGARG
)
588 if (greg
++ >= NGREGARG
)
595 else if ((*p_arg
)->type
== FFI_TYPE_DOUBLE
)
597 if (freg
+ 1 >= NFREGARG
)
601 freg
= (freg
+ 1) & ~1;
609 int n
= (z
+ sizeof (int) - 1) / sizeof (int);
611 if (greg
+ n
- 1 >= NGREGARG
)
614 if (greg
>= NGREGARG
)
628 for (i
= 0, p_arg
= cif
->arg_types
; i
< avn
; i
++, p_arg
++)
635 if (greg
++ < NGREGARG
)
639 switch ((*p_arg
)->type
)
643 avalue
[i
] = (((char *)pst
) + OFS_INT8
);
646 case FFI_TYPE_SINT16
:
647 case FFI_TYPE_UINT16
:
648 avalue
[i
] = (((char *)pst
) + OFS_INT16
);
651 case FFI_TYPE_STRUCT
:
660 else if (z
== sizeof(int))
663 if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
665 if (freg
++ < NFREGARG
)
671 if (greg
++ < NGREGARG
)
678 else if ((*p_arg
)->type
== FFI_TYPE_DOUBLE
)
680 if (freg
+ 1 < NFREGARG
)
682 freg
= (freg
+ 1) & ~1;
692 int n
= (z
+ sizeof (int) - 1) / sizeof (int);
693 if (greg
+ n
- 1 < NGREGARG
)
698 #if (! defined(__SH4__))
699 else if (greg
< NGREGARG
)
702 pst
+= greg
- NGREGARG
;
711 (closure
->fun
) (cif
, rvalue
, avalue
, closure
->user_data
);
713 /* Tell ffi_closure_SYSV how to perform return type promotions. */
714 return return_type (cif
->rtype
);