1 /* -----------------------------------------------------------------------
4 m68k Foreign Function Interface
5 ----------------------------------------------------------------------- */
8 #include <ffi_common.h>
12 #include <sys/syscall.h>
13 #include <asm/cachectl.h>
15 void ffi_call_SYSV (extended_cif
*,
17 void *, void (*fn
) ());
18 void *ffi_prep_args (void *stack
, extended_cif
*ecif
);
19 void ffi_closure_SYSV (ffi_closure
*);
20 void ffi_closure_struct_SYSV (ffi_closure
*);
21 unsigned int ffi_closure_SYSV_inner (ffi_closure
*closure
,
22 void *resp
, void *args
);
24 /* ffi_prep_args is called by the assembly routine once stack space has
25 been allocated for the function's arguments. */
28 ffi_prep_args (void *stack
, extended_cif
*ecif
)
34 void *struct_value_ptr
;
38 if (ecif
->cif
->rtype
->type
== FFI_TYPE_STRUCT
40 struct_value_ptr
= ecif
->rvalue
;
42 struct_value_ptr
= NULL
;
44 p_argv
= ecif
->avalue
;
46 for (i
= ecif
->cif
->nargs
, p_arg
= ecif
->cif
->arg_types
;
55 switch ((*p_arg
)->type
)
58 *(signed int *) argp
= (signed int) *(SINT8
*) *p_argv
;
62 *(unsigned int *) argp
= (unsigned int) *(UINT8
*) *p_argv
;
66 *(signed int *) argp
= (signed int) *(SINT16
*) *p_argv
;
70 *(unsigned int *) argp
= (unsigned int) *(UINT16
*) *p_argv
;
74 memcpy (argp
+ sizeof (int) - z
, *p_argv
, z
);
84 memcpy (argp
, *p_argv
, z
);
86 /* Align if necessary. */
87 if ((sizeof(int) - 1) & z
)
88 z
= ALIGN(z
, sizeof(int));
95 return struct_value_ptr
;
98 #define CIF_FLAGS_INT 1
99 #define CIF_FLAGS_DINT 2
100 #define CIF_FLAGS_FLOAT 4
101 #define CIF_FLAGS_DOUBLE 8
102 #define CIF_FLAGS_LDOUBLE 16
103 #define CIF_FLAGS_POINTER 32
104 #define CIF_FLAGS_STRUCT1 64
105 #define CIF_FLAGS_STRUCT2 128
107 /* Perform machine dependent cif processing */
109 ffi_prep_cif_machdep (ffi_cif
*cif
)
111 /* Set the return type flag */
112 switch (cif
->rtype
->type
)
118 case FFI_TYPE_STRUCT
:
119 switch (cif
->rtype
->size
)
122 cif
->flags
= CIF_FLAGS_STRUCT1
;
125 cif
->flags
= CIF_FLAGS_STRUCT2
;
128 cif
->flags
= CIF_FLAGS_INT
;
131 cif
->flags
= CIF_FLAGS_DINT
;
140 cif
->flags
= CIF_FLAGS_FLOAT
;
143 case FFI_TYPE_DOUBLE
:
144 cif
->flags
= CIF_FLAGS_DOUBLE
;
147 case FFI_TYPE_LONGDOUBLE
:
148 cif
->flags
= CIF_FLAGS_LDOUBLE
;
151 case FFI_TYPE_POINTER
:
152 cif
->flags
= CIF_FLAGS_POINTER
;
155 case FFI_TYPE_SINT64
:
156 case FFI_TYPE_UINT64
:
157 cif
->flags
= CIF_FLAGS_DINT
;
161 cif
->flags
= CIF_FLAGS_INT
;
169 ffi_call (ffi_cif
*cif
, void (*fn
) (), void *rvalue
, void **avalue
)
174 ecif
.avalue
= avalue
;
176 /* If the return value is a struct and we don't have a return value
177 address then we need to make one. */
180 && cif
->rtype
->type
== FFI_TYPE_STRUCT
181 && cif
->rtype
->size
> 8)
182 ecif
.rvalue
= alloca (cif
->rtype
->size
);
184 ecif
.rvalue
= rvalue
;
189 ffi_call_SYSV (&ecif
, cif
->bytes
, cif
->flags
,
200 ffi_prep_incoming_args_SYSV (char *stack
, void **avalue
, ffi_cif
*cif
)
210 for (i
= cif
->nargs
, p_arg
= cif
->arg_types
; (i
!= 0); i
--, p_arg
++)
217 *p_argv
= (void *) (argp
+ 4 - z
);
223 *p_argv
= (void *) argp
;
225 /* Align if necessary */
226 if ((sizeof(int) - 1) & z
)
227 z
= ALIGN(z
, sizeof(int));
236 ffi_closure_SYSV_inner (ffi_closure
*closure
, void *resp
, void *args
)
242 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void *));
244 ffi_prep_incoming_args_SYSV(args
, arg_area
, cif
);
246 (closure
->fun
) (cif
, resp
, arg_area
, closure
->user_data
);
252 ffi_prep_closure_loc (ffi_closure
* closure
,
254 void (*fun
)(ffi_cif
*,void*,void**,void*),
258 FFI_ASSERT (cif
->abi
== FFI_SYSV
);
260 *(unsigned short *)closure
->tramp
= 0x207c;
261 *(void **)(closure
->tramp
+ 2) = codeloc
;
262 *(unsigned short *)(closure
->tramp
+ 6) = 0x4ef9;
263 if (cif
->rtype
->type
== FFI_TYPE_STRUCT
265 *(void **)(closure
->tramp
+ 8) = ffi_closure_struct_SYSV
;
267 *(void **)(closure
->tramp
+ 8) = ffi_closure_SYSV
;
269 syscall(SYS_cacheflush
, codeloc
, FLUSH_SCOPE_LINE
,
270 FLUSH_CACHE_BOTH
, FFI_TRAMPOLINE_SIZE
);
273 closure
->user_data
= user_data
;