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>
16 #include <asm/cachectl.h>
19 void ffi_call_SYSV (extended_cif *,
21 void *, void (*fn) ());
22 void *ffi_prep_args (void *stack, extended_cif *ecif);
23 void ffi_closure_SYSV (ffi_closure *);
24 void ffi_closure_struct_SYSV (ffi_closure *);
25 unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
26 void *resp, void *args);
28 /* ffi_prep_args is called by the assembly routine once stack space has
29 been allocated for the function's arguments. */
32 ffi_prep_args (void *stack, extended_cif *ecif)
38 void *struct_value_ptr;
42 if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
44 struct_value_ptr = ecif->rvalue;
46 struct_value_ptr = NULL;
48 p_argv = ecif->avalue;
50 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
59 switch ((*p_arg)->type)
62 *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
66 *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
70 *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
74 *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
78 memcpy (argp + sizeof (int) - z, *p_argv, z);
88 memcpy (argp, *p_argv, z);
90 /* Align if necessary. */
91 if ((sizeof(int) - 1) & z)
92 z = ALIGN(z, sizeof(int));
99 return struct_value_ptr;
102 #define CIF_FLAGS_INT 1
103 #define CIF_FLAGS_DINT 2
104 #define CIF_FLAGS_FLOAT 4
105 #define CIF_FLAGS_DOUBLE 8
106 #define CIF_FLAGS_LDOUBLE 16
107 #define CIF_FLAGS_POINTER 32
108 #define CIF_FLAGS_STRUCT1 64
109 #define CIF_FLAGS_STRUCT2 128
111 /* Perform machine dependent cif processing */
113 ffi_prep_cif_machdep (ffi_cif *cif)
115 /* Set the return type flag */
116 switch (cif->rtype->type)
122 case FFI_TYPE_STRUCT:
123 switch (cif->rtype->size)
126 cif->flags = CIF_FLAGS_STRUCT1;
129 cif->flags = CIF_FLAGS_STRUCT2;
132 cif->flags = CIF_FLAGS_INT;
135 cif->flags = CIF_FLAGS_DINT;
144 cif->flags = CIF_FLAGS_FLOAT;
147 case FFI_TYPE_DOUBLE:
148 cif->flags = CIF_FLAGS_DOUBLE;
151 #if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
152 case FFI_TYPE_LONGDOUBLE:
153 cif->flags = CIF_FLAGS_LDOUBLE;
157 case FFI_TYPE_POINTER:
158 cif->flags = CIF_FLAGS_POINTER;
161 case FFI_TYPE_SINT64:
162 case FFI_TYPE_UINT64:
163 cif->flags = CIF_FLAGS_DINT;
167 cif->flags = CIF_FLAGS_INT;
175 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
180 ecif.avalue = avalue;
182 /* If the return value is a struct and we don't have a return value
183 address then we need to make one. */
186 && cif->rtype->type == FFI_TYPE_STRUCT
187 && cif->rtype->size > 8)
188 ecif.rvalue = alloca (cif->rtype->size);
190 ecif.rvalue = rvalue;
195 ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
206 ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
216 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
223 *p_argv = (void *) (argp + 4 - z);
229 *p_argv = (void *) argp;
231 /* Align if necessary */
232 if ((sizeof(int) - 1) & z)
233 z = ALIGN(z, sizeof(int));
242 ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
248 arg_area = (void**) alloca (cif->nargs * sizeof (void *));
250 ffi_prep_incoming_args_SYSV(args, arg_area, cif);
252 (closure->fun) (cif, resp, arg_area, closure->user_data);
258 ffi_prep_closure_loc (ffi_closure* closure,
260 void (*fun)(ffi_cif*,void*,void**,void*),
264 if (cif->abi != FFI_SYSV)
267 *(unsigned short *)closure->tramp = 0x207c;
268 *(void **)(closure->tramp + 2) = codeloc;
269 *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
270 if (cif->rtype->type == FFI_TYPE_STRUCT
272 *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
274 *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
277 rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
279 syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
280 FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
284 closure->user_data = user_data;