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;