1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2002-2008, 2012 Kaz Kojima
3 Copyright (c) 2008 Red Hat, Inc.
5 SuperH Foreign Function Interface
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:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
29 #include <ffi_common.h>
38 #if defined(__HITACHI__)
39 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
41 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
44 /* If the structure has essentially an unique element, return its type. */
46 simple_type (ffi_type
*arg
)
48 if (arg
->type
!= FFI_TYPE_STRUCT
)
50 else if (arg
->elements
[1])
51 return FFI_TYPE_STRUCT
;
53 return simple_type (arg
->elements
[0]);
57 return_type (ffi_type
*arg
)
61 if (arg
->type
!= FFI_TYPE_STRUCT
)
64 type
= simple_type (arg
->elements
[0]);
65 if (! arg
->elements
[1])
82 /* gcc uses r0/r1 pair for some kind of structures. */
83 if (arg
->size
<= 2 * sizeof (int))
88 while ((e
= arg
->elements
[i
++]))
90 type
= simple_type (e
);
97 return FFI_TYPE_UINT64
;
105 return FFI_TYPE_STRUCT
;
108 /* ffi_prep_args is called by the assembly routine once stack space
109 has been allocated for the function's arguments */
111 void ffi_prep_args(char *stack
, extended_cif
*ecif
)
113 register unsigned int i
;
115 register unsigned int avn
;
116 register void **p_argv
;
118 register ffi_type
**p_arg
;
127 if (return_type (ecif
->cif
->rtype
) == FFI_TYPE_STRUCT
)
129 *(void **) argp
= ecif
->rvalue
;
131 ireg
= STRUCT_VALUE_ADDRESS_WITH_ARG
? 1 : 0;
136 /* Set arguments for registers. */
138 avn
= ecif
->cif
->nargs
;
139 p_argv
= ecif
->avalue
;
141 for (i
= 0, p_arg
= ecif
->cif
->arg_types
; i
< avn
; i
++, p_arg
++, p_argv
++)
148 if (greg
++ >= NGREGARG
)
152 switch ((*p_arg
)->type
)
155 *(signed int *) argp
= (signed int)*(SINT8
*)(* p_argv
);
159 *(unsigned int *) argp
= (unsigned int)*(UINT8
*)(* p_argv
);
162 case FFI_TYPE_SINT16
:
163 *(signed int *) argp
= (signed int)*(SINT16
*)(* p_argv
);
166 case FFI_TYPE_UINT16
:
167 *(unsigned int *) argp
= (unsigned int)*(UINT16
*)(* p_argv
);
170 case FFI_TYPE_STRUCT
:
171 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
179 else if (z
== sizeof(int))
182 if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
184 if (freg
++ >= NFREGARG
)
190 if (greg
++ >= NGREGARG
)
193 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
197 else if ((*p_arg
)->type
== FFI_TYPE_DOUBLE
)
199 if (freg
+ 1 >= NFREGARG
)
201 freg
= (freg
+ 1) & ~1;
203 memcpy (argp
, *p_argv
, z
);
209 int n
= (z
+ sizeof (int) - 1) / sizeof (int);
211 if (greg
+ n
- 1 >= NGREGARG
)
214 if (greg
>= NGREGARG
)
218 memcpy (argp
, *p_argv
, z
);
219 argp
+= n
* sizeof (int);
223 /* Set arguments on stack. */
228 p_argv
= ecif
->avalue
;
230 for (i
= 0, p_arg
= ecif
->cif
->arg_types
; i
< avn
; i
++, p_arg
++, p_argv
++)
237 if (greg
++ < NGREGARG
)
241 switch ((*p_arg
)->type
)
244 *(signed int *) argp
= (signed int)*(SINT8
*)(* p_argv
);
248 *(unsigned int *) argp
= (unsigned int)*(UINT8
*)(* p_argv
);
251 case FFI_TYPE_SINT16
:
252 *(signed int *) argp
= (signed int)*(SINT16
*)(* p_argv
);
255 case FFI_TYPE_UINT16
:
256 *(unsigned int *) argp
= (unsigned int)*(UINT16
*)(* p_argv
);
259 case FFI_TYPE_STRUCT
:
260 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
268 else if (z
== sizeof(int))
271 if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
273 if (freg
++ < NFREGARG
)
279 if (greg
++ < NGREGARG
)
282 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
286 else if ((*p_arg
)->type
== FFI_TYPE_DOUBLE
)
288 if (freg
+ 1 < NFREGARG
)
290 freg
= (freg
+ 1) & ~1;
294 memcpy (argp
, *p_argv
, z
);
300 int n
= (z
+ sizeof (int) - 1) / sizeof (int);
301 if (greg
+ n
- 1 < NGREGARG
)
306 #if (! defined(__SH4__))
307 else if (greg
< NGREGARG
)
313 memcpy (argp
, *p_argv
, z
);
314 argp
+= n
* sizeof (int);
321 /* Perform machine dependent cif processing */
322 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
334 greg
= ((return_type (cif
->rtype
) == FFI_TYPE_STRUCT
) &&
335 STRUCT_VALUE_ADDRESS_WITH_ARG
) ? 1 : 0;
338 for (i
= j
= 0; i
< cif
->nargs
&& j
< 12; i
++)
340 type
= (cif
->arg_types
)[i
]->type
;
344 if (freg
>= NFREGARG
)
347 cif
->flags
+= ((cif
->arg_types
)[i
]->type
) << (2 * j
);
351 case FFI_TYPE_DOUBLE
:
352 if ((freg
+ 1) >= NFREGARG
)
354 freg
= (freg
+ 1) & ~1;
356 cif
->flags
+= ((cif
->arg_types
)[i
]->type
) << (2 * j
);
361 size
= (cif
->arg_types
)[i
]->size
;
362 n
= (size
+ sizeof (int) - 1) / sizeof (int);
363 if (greg
+ n
- 1 >= NGREGARG
)
366 for (m
= 0; m
< n
; m
++)
367 cif
->flags
+= FFI_TYPE_INT
<< (2 * j
++);
372 for (i
= j
= 0; i
< cif
->nargs
&& j
< 4; i
++)
374 size
= (cif
->arg_types
)[i
]->size
;
375 n
= (size
+ sizeof (int) - 1) / sizeof (int);
376 if (greg
>= NGREGARG
)
378 else if (greg
+ n
- 1 >= NGREGARG
)
381 for (m
= 0; m
< n
; m
++)
382 cif
->flags
+= FFI_TYPE_INT
<< (2 * j
++);
386 /* Set the return type flag */
387 switch (cif
->rtype
->type
)
389 case FFI_TYPE_STRUCT
:
390 cif
->flags
+= (unsigned) (return_type (cif
->rtype
)) << 24;
395 case FFI_TYPE_DOUBLE
:
396 case FFI_TYPE_SINT64
:
397 case FFI_TYPE_UINT64
:
398 cif
->flags
+= (unsigned) cif
->rtype
->type
<< 24;
402 cif
->flags
+= FFI_TYPE_INT
<< 24;
409 extern void ffi_call_SYSV(void (*)(char *, extended_cif
*), extended_cif
*,
410 unsigned, unsigned, unsigned *, void (*fn
)(void));
412 void ffi_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
418 ecif
.avalue
= avalue
;
420 /* If the return value is a struct and we don't have a return */
421 /* value address then we need to make one */
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
))
429 ecif
.rvalue
= alloca(cif
->rtype
->size
);
432 ecif
.rvalue
= rvalue
;
437 ffi_call_SYSV(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
, ecif
.rvalue
,
446 && cif
->rtype
->type
== FFI_TYPE_STRUCT
447 && return_type (cif
->rtype
) != FFI_TYPE_STRUCT
)
448 memcpy (rvalue
, &trvalue
, cif
->rtype
->size
);
451 extern void ffi_closure_SYSV (void);
453 extern void __ic_invalidate (void *line
);
457 ffi_prep_closure_loc (ffi_closure
* closure
,
459 void (*fun
)(ffi_cif
*, void*, void**, void*),
466 if (cif
->abi
!= FFI_SYSV
)
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
473 : 0x0008 /* clrt */);
475 #ifdef __LITTLE_ENDIAN__
476 tramp
[0] = 0xd301d102;
477 tramp
[1] = 0x0000412b | (insn
<< 16);
479 tramp
[0] = 0xd102d301;
480 tramp
[1] = 0x412b0000 | insn
;
482 *(void **) &tramp
[2] = (void *)codeloc
; /* ctx */
483 *(void **) &tramp
[3] = (void *)ffi_closure_SYSV
; /* funaddr */
487 closure
->user_data
= user_data
;
490 /* Flush the icache. */
491 __ic_invalidate(codeloc
);
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.
505 #ifdef __LITTLE_ENDIAN__
514 ffi_closure_helper_SYSV (ffi_closure
*closure
, void *rvalue
,
515 unsigned long *pgr
, unsigned long *pfr
,
528 avalue
= alloca(cif
->nargs
* sizeof(void *));
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
)
534 rvalue
= (void *) *pgr
++;
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
++)
552 if (greg
++ >= NGREGARG
)
556 switch ((*p_arg
)->type
)
560 avalue
[i
] = (((char *)pgr
) + OFS_INT8
);
563 case FFI_TYPE_SINT16
:
564 case FFI_TYPE_UINT16
:
565 avalue
[i
] = (((char *)pgr
) + OFS_INT16
);
568 case FFI_TYPE_STRUCT
:
577 else if (z
== sizeof(int))
580 if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
582 if (freg
++ >= NFREGARG
)
590 if (greg
++ >= NGREGARG
)
597 else if ((*p_arg
)->type
== FFI_TYPE_DOUBLE
)
599 if (freg
+ 1 >= NFREGARG
)
603 freg
= (freg
+ 1) & ~1;
611 int n
= (z
+ sizeof (int) - 1) / sizeof (int);
613 if (greg
+ n
- 1 >= NGREGARG
)
616 if (greg
>= NGREGARG
)
630 for (i
= 0, p_arg
= cif
->arg_types
; i
< avn
; i
++, p_arg
++)
637 if (greg
++ < NGREGARG
)
641 switch ((*p_arg
)->type
)
645 avalue
[i
] = (((char *)pst
) + OFS_INT8
);
648 case FFI_TYPE_SINT16
:
649 case FFI_TYPE_UINT16
:
650 avalue
[i
] = (((char *)pst
) + OFS_INT16
);
653 case FFI_TYPE_STRUCT
:
662 else if (z
== sizeof(int))
665 if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
667 if (freg
++ < NFREGARG
)
673 if (greg
++ < NGREGARG
)
680 else if ((*p_arg
)->type
== FFI_TYPE_DOUBLE
)
682 if (freg
+ 1 < NFREGARG
)
684 freg
= (freg
+ 1) & ~1;
694 int n
= (z
+ sizeof (int) - 1) / sizeof (int);
695 if (greg
+ n
- 1 < NGREGARG
)
700 #if (! defined(__SH4__))
701 else if (greg
< NGREGARG
)
704 pst
+= greg
- NGREGARG
;
713 (closure
->fun
) (cif
, rvalue
, avalue
, closure
->user_data
);
715 /* Tell ffi_closure_SYSV how to perform return type promotions. */
716 return return_type (cif
->rtype
);