1 /* -----------------------------------------------------------------------
4 m68k Foreign Function Interface
5 ----------------------------------------------------------------------- */
8 #include <ffi_common.h>
13 void rtems_cache_flush_multiple_data_lines( const void *, size_t );
15 #include <sys/syscall.h>
17 #include <mint/mintbind.h>
18 #include <mint/ssystem.h>
20 #include <asm/cachectl.h>
24 void ffi_call_SYSV (extended_cif *,
26 void *, void (*fn) ());
27 void *ffi_prep_args (void *stack, extended_cif *ecif);
28 void ffi_closure_SYSV (ffi_closure *);
29 void ffi_closure_struct_SYSV (ffi_closure *);
30 unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
31 void *resp, void *args);
33 /* ffi_prep_args is called by the assembly routine once stack space has
34 been allocated for the function's arguments. */
37 ffi_prep_args (void *stack, extended_cif *ecif)
43 void *struct_value_ptr;
49 (ecif->cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
51 (((ecif->cif->rtype->type == FFI_TYPE_STRUCT)
52 && !ecif->cif->flags)))
53 struct_value_ptr = ecif->rvalue;
55 struct_value_ptr = NULL;
57 p_argv = ecif->avalue;
59 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
63 size_t z = (*p_arg)->size;
64 int type = (*p_arg)->type;
71 *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
75 *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
79 *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
83 *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
89 memcpy (argp + 2, *p_argv, z);
91 memcpy (argp, *p_argv, z);
93 memcpy (argp + sizeof (int) - z, *p_argv, z);
104 memcpy (argp, *p_argv, z);
106 /* Align if necessary. */
107 if ((sizeof(int) - 1) & z)
108 z = ALIGN(z, sizeof(int));
115 return struct_value_ptr;
118 #define CIF_FLAGS_INT 1
119 #define CIF_FLAGS_DINT 2
120 #define CIF_FLAGS_FLOAT 4
121 #define CIF_FLAGS_DOUBLE 8
122 #define CIF_FLAGS_LDOUBLE 16
123 #define CIF_FLAGS_POINTER 32
124 #define CIF_FLAGS_STRUCT1 64
125 #define CIF_FLAGS_STRUCT2 128
127 /* Perform machine dependent cif processing */
129 ffi_prep_cif_machdep (ffi_cif *cif)
131 /* Set the return type flag */
132 switch (cif->rtype->type)
138 case FFI_TYPE_STRUCT:
139 if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
140 cif->rtype->elements[1])
146 switch (cif->rtype->size)
150 cif->flags = CIF_FLAGS_STRUCT2;
152 cif->flags = CIF_FLAGS_STRUCT1;
156 cif->flags = CIF_FLAGS_STRUCT2;
162 cif->flags = CIF_FLAGS_INT;
168 cif->flags = CIF_FLAGS_DINT;
177 cif->flags = CIF_FLAGS_FLOAT;
180 case FFI_TYPE_DOUBLE:
181 cif->flags = CIF_FLAGS_DOUBLE;
184 #if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
185 case FFI_TYPE_LONGDOUBLE:
189 cif->flags = CIF_FLAGS_LDOUBLE;
194 case FFI_TYPE_POINTER:
195 cif->flags = CIF_FLAGS_POINTER;
198 case FFI_TYPE_SINT64:
199 case FFI_TYPE_UINT64:
200 cif->flags = CIF_FLAGS_DINT;
204 cif->flags = CIF_FLAGS_INT;
212 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
217 ecif.avalue = avalue;
219 /* If the return value is a struct and we don't have a return value
220 address then we need to make one. */
223 && cif->rtype->type == FFI_TYPE_STRUCT
224 && cif->rtype->size > 8)
225 ecif.rvalue = alloca (cif->rtype->size);
227 ecif.rvalue = rvalue;
232 ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
243 ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
253 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
260 cif->rtype->type == FFI_TYPE_STRUCT &&
263 *p_argv = (void *) (argp + 2);
269 cif->rtype->type == FFI_TYPE_STRUCT &&
272 *p_argv = (void *) (argp);
280 *p_argv = (void *) (argp + 4 - z);
286 *p_argv = (void *) argp;
288 /* Align if necessary */
289 if ((sizeof(int) - 1) & z)
290 z = ALIGN(z, sizeof(int));
299 ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
305 arg_area = (void**) alloca (cif->nargs * sizeof (void *));
307 ffi_prep_incoming_args_SYSV(args, arg_area, cif);
309 (closure->fun) (cif, resp, arg_area, closure->user_data);
315 ffi_prep_closure_loc (ffi_closure* closure,
317 void (*fun)(ffi_cif*,void*,void**,void*),
321 if (cif->abi != FFI_SYSV)
324 *(unsigned short *)closure->tramp = 0x207c;
325 *(void **)(closure->tramp + 2) = codeloc;
326 *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
330 (cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
332 (((cif->rtype->type == FFI_TYPE_STRUCT)
334 *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
336 *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
339 rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
340 #elif defined(__MINT__)
341 Ssystem(S_FLUSHCACHE, codeloc, FFI_TRAMPOLINE_SIZE);
343 syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
344 FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
348 closure->user_data = user_data;