* fr.po: Update.
[official-gcc.git] / libffi / src / m68k / ffi.c
blob0dee9383a8d88778d36f2a594ba37ef04c9cd035
1 /* -----------------------------------------------------------------------
2 ffi.c
4 m68k Foreign Function Interface
5 ----------------------------------------------------------------------- */
7 #include <ffi.h>
8 #include <ffi_common.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #ifdef __rtems__
13 void rtems_cache_flush_multiple_data_lines( const void *, size_t );
14 #else
15 #include <sys/syscall.h>
16 #ifdef __MINT__
17 #include <mint/mintbind.h>
18 #include <mint/ssystem.h>
19 #else
20 #include <asm/cachectl.h>
21 #endif
22 #endif
24 void ffi_call_SYSV (extended_cif *,
25 unsigned, unsigned,
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. */
36 void *
37 ffi_prep_args (void *stack, extended_cif *ecif)
39 unsigned int i;
40 void **p_argv;
41 char *argp;
42 ffi_type **p_arg;
43 void *struct_value_ptr;
45 argp = stack;
47 if (
48 #ifdef __MINT__
49 (ecif->cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
50 #endif
51 (((ecif->cif->rtype->type == FFI_TYPE_STRUCT)
52 && !ecif->cif->flags)))
53 struct_value_ptr = ecif->rvalue;
54 else
55 struct_value_ptr = NULL;
57 p_argv = ecif->avalue;
59 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
60 i != 0;
61 i--, p_arg++)
63 size_t z = (*p_arg)->size;
64 int type = (*p_arg)->type;
66 if (z < sizeof (int))
68 switch (type)
70 case FFI_TYPE_SINT8:
71 *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
72 break;
74 case FFI_TYPE_UINT8:
75 *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
76 break;
78 case FFI_TYPE_SINT16:
79 *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
80 break;
82 case FFI_TYPE_UINT16:
83 *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
84 break;
86 case FFI_TYPE_STRUCT:
87 #ifdef __MINT__
88 if (z == 1 || z == 2)
89 memcpy (argp + 2, *p_argv, z);
90 else
91 memcpy (argp, *p_argv, z);
92 #else
93 memcpy (argp + sizeof (int) - z, *p_argv, z);
94 #endif
95 break;
97 default:
98 FFI_ASSERT (0);
100 z = sizeof (int);
102 else
104 memcpy (argp, *p_argv, z);
106 /* Align if necessary. */
107 if ((sizeof(int) - 1) & z)
108 z = ALIGN(z, sizeof(int));
111 p_argv++;
112 argp += z;
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 */
130 ffi_status
131 ffi_prep_cif_machdep (ffi_cif *cif)
133 /* Set the return type flag */
134 switch (cif->rtype->type)
136 case FFI_TYPE_VOID:
137 cif->flags = 0;
138 break;
140 case FFI_TYPE_STRUCT:
141 if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
142 cif->rtype->elements[1])
144 cif->flags = 0;
145 break;
148 switch (cif->rtype->size)
150 case 1:
151 #ifdef __MINT__
152 cif->flags = CIF_FLAGS_STRUCT2;
153 #else
154 cif->flags = CIF_FLAGS_STRUCT1;
155 #endif
156 break;
157 case 2:
158 cif->flags = CIF_FLAGS_STRUCT2;
159 break;
160 #ifdef __MINT__
161 case 3:
162 #endif
163 case 4:
164 cif->flags = CIF_FLAGS_INT;
165 break;
166 #ifdef __MINT__
167 case 7:
168 #endif
169 case 8:
170 cif->flags = CIF_FLAGS_DINT;
171 break;
172 default:
173 cif->flags = 0;
174 break;
176 break;
178 case FFI_TYPE_FLOAT:
179 cif->flags = CIF_FLAGS_FLOAT;
180 break;
182 case FFI_TYPE_DOUBLE:
183 cif->flags = CIF_FLAGS_DOUBLE;
184 break;
186 #if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
187 case FFI_TYPE_LONGDOUBLE:
188 #ifdef __MINT__
189 cif->flags = 0;
190 #else
191 cif->flags = CIF_FLAGS_LDOUBLE;
192 #endif
193 break;
194 #endif
196 case FFI_TYPE_POINTER:
197 cif->flags = CIF_FLAGS_POINTER;
198 break;
200 case FFI_TYPE_SINT64:
201 case FFI_TYPE_UINT64:
202 cif->flags = CIF_FLAGS_DINT;
203 break;
205 case FFI_TYPE_SINT16:
206 cif->flags = CIF_FLAGS_SINT16;
207 break;
209 case FFI_TYPE_SINT8:
210 cif->flags = CIF_FLAGS_SINT8;
211 break;
213 default:
214 cif->flags = CIF_FLAGS_INT;
215 break;
218 return FFI_OK;
221 void
222 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
224 extended_cif ecif;
226 ecif.cif = cif;
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. */
232 if (rvalue == NULL
233 && cif->rtype->type == FFI_TYPE_STRUCT
234 && cif->rtype->size > 8)
235 ecif.rvalue = alloca (cif->rtype->size);
236 else
237 ecif.rvalue = rvalue;
239 switch (cif->abi)
241 case FFI_SYSV:
242 ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
243 ecif.rvalue, fn);
244 break;
246 default:
247 FFI_ASSERT (0);
248 break;
252 static void
253 ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
255 unsigned int i;
256 void **p_argv;
257 char *argp;
258 ffi_type **p_arg;
260 argp = stack;
261 p_argv = avalue;
263 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
265 size_t z;
267 z = (*p_arg)->size;
268 #ifdef __MINT__
269 if (cif->flags &&
270 cif->rtype->type == FFI_TYPE_STRUCT &&
271 (z == 1 || z == 2))
273 *p_argv = (void *) (argp + 2);
275 z = 4;
277 else
278 if (cif->flags &&
279 cif->rtype->type == FFI_TYPE_STRUCT &&
280 (z == 3 || z == 4))
282 *p_argv = (void *) (argp);
284 z = 4;
286 else
287 #endif
288 if (z <= 4)
290 *p_argv = (void *) (argp + 4 - z);
292 z = 4;
294 else
296 *p_argv = (void *) argp;
298 /* Align if necessary */
299 if ((sizeof(int) - 1) & z)
300 z = ALIGN(z, sizeof(int));
303 p_argv++;
304 argp += z;
308 unsigned int
309 ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
311 ffi_cif *cif;
312 void **arg_area;
314 cif = closure->cif;
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);
321 return cif->flags;
324 ffi_status
325 ffi_prep_closure_loc (ffi_closure* closure,
326 ffi_cif* cif,
327 void (*fun)(ffi_cif*,void*,void**,void*),
328 void *user_data,
329 void *codeloc)
331 if (cif->abi != FFI_SYSV)
332 return FFI_BAD_ABI;
334 *(unsigned short *)closure->tramp = 0x207c;
335 *(void **)(closure->tramp + 2) = codeloc;
336 *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
338 if (
339 #ifdef __MINT__
340 (cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
341 #endif
342 (((cif->rtype->type == FFI_TYPE_STRUCT)
343 && !cif->flags)))
344 *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
345 else
346 *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
348 #ifdef __rtems__
349 rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
350 #elif defined(__MINT__)
351 Ssystem(S_FLUSHCACHE, codeloc, FFI_TRAMPOLINE_SIZE);
352 #else
353 syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
354 FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
355 #endif
357 closure->cif = cif;
358 closure->user_data = user_data;
359 closure->fun = fun;
361 return FFI_OK;