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
126 #define CIF_FLAGS_SINT8 256
127 #define CIF_FLAGS_SINT16 512
129 /* Perform machine dependent cif processing */
131 ffi_prep_cif_machdep (ffi_cif
*cif
)
133 /* Set the return type flag */
134 switch (cif
->rtype
->type
)
140 case FFI_TYPE_STRUCT
:
141 if (cif
->rtype
->elements
[0]->type
== FFI_TYPE_STRUCT
&&
142 cif
->rtype
->elements
[1])
148 switch (cif
->rtype
->size
)
152 cif
->flags
= CIF_FLAGS_STRUCT2
;
154 cif
->flags
= CIF_FLAGS_STRUCT1
;
158 cif
->flags
= CIF_FLAGS_STRUCT2
;
164 cif
->flags
= CIF_FLAGS_INT
;
170 cif
->flags
= CIF_FLAGS_DINT
;
179 cif
->flags
= CIF_FLAGS_FLOAT
;
182 case FFI_TYPE_DOUBLE
:
183 cif
->flags
= CIF_FLAGS_DOUBLE
;
186 #if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
187 case FFI_TYPE_LONGDOUBLE
:
191 cif
->flags
= CIF_FLAGS_LDOUBLE
;
196 case FFI_TYPE_POINTER
:
197 cif
->flags
= CIF_FLAGS_POINTER
;
200 case FFI_TYPE_SINT64
:
201 case FFI_TYPE_UINT64
:
202 cif
->flags
= CIF_FLAGS_DINT
;
205 case FFI_TYPE_SINT16
:
206 cif
->flags
= CIF_FLAGS_SINT16
;
210 cif
->flags
= CIF_FLAGS_SINT8
;
214 cif
->flags
= CIF_FLAGS_INT
;
222 ffi_call (ffi_cif
*cif
, void (*fn
) (), void *rvalue
, void **avalue
)
227 ecif
.avalue
= avalue
;
229 /* If the return value is a struct and we don't have a return value
230 address then we need to make one. */
233 && cif
->rtype
->type
== FFI_TYPE_STRUCT
234 && cif
->rtype
->size
> 8)
235 ecif
.rvalue
= alloca (cif
->rtype
->size
);
237 ecif
.rvalue
= rvalue
;
242 ffi_call_SYSV (&ecif
, cif
->bytes
, cif
->flags
,
253 ffi_prep_incoming_args_SYSV (char *stack
, void **avalue
, ffi_cif
*cif
)
263 for (i
= cif
->nargs
, p_arg
= cif
->arg_types
; (i
!= 0); i
--, p_arg
++)
270 cif
->rtype
->type
== FFI_TYPE_STRUCT
&&
273 *p_argv
= (void *) (argp
+ 2);
279 cif
->rtype
->type
== FFI_TYPE_STRUCT
&&
282 *p_argv
= (void *) (argp
);
290 *p_argv
= (void *) (argp
+ 4 - z
);
296 *p_argv
= (void *) argp
;
298 /* Align if necessary */
299 if ((sizeof(int) - 1) & z
)
300 z
= ALIGN(z
, sizeof(int));
309 ffi_closure_SYSV_inner (ffi_closure
*closure
, void *resp
, void *args
)
315 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void *));
317 ffi_prep_incoming_args_SYSV(args
, arg_area
, cif
);
319 (closure
->fun
) (cif
, resp
, arg_area
, closure
->user_data
);
325 ffi_prep_closure_loc (ffi_closure
* closure
,
327 void (*fun
)(ffi_cif
*,void*,void**,void*),
331 if (cif
->abi
!= FFI_SYSV
)
334 *(unsigned short *)closure
->tramp
= 0x207c;
335 *(void **)(closure
->tramp
+ 2) = codeloc
;
336 *(unsigned short *)(closure
->tramp
+ 6) = 0x4ef9;
340 (cif
->rtype
->type
== FFI_TYPE_LONGDOUBLE
) ||
342 (((cif
->rtype
->type
== FFI_TYPE_STRUCT
)
344 *(void **)(closure
->tramp
+ 8) = ffi_closure_struct_SYSV
;
346 *(void **)(closure
->tramp
+ 8) = ffi_closure_SYSV
;
349 rtems_cache_flush_multiple_data_lines( codeloc
, FFI_TRAMPOLINE_SIZE
);
350 #elif defined(__MINT__)
351 Ssystem(S_FLUSHCACHE
, codeloc
, FFI_TRAMPOLINE_SIZE
);
353 syscall(SYS_cacheflush
, codeloc
, FLUSH_SCOPE_LINE
,
354 FLUSH_CACHE_BOTH
, FFI_TRAMPOLINE_SIZE
);
358 closure
->user_data
= user_data
;