annotate libffi/src/m68k/ffi.c @ 155:da32f4b04d38

fix __code name conflict
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 17:51:46 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* -----------------------------------------------------------------------
kono
parents:
diff changeset
2 ffi.c
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 m68k Foreign Function Interface
kono
parents:
diff changeset
5 ----------------------------------------------------------------------- */
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 #include <ffi.h>
kono
parents:
diff changeset
8 #include <ffi_common.h>
kono
parents:
diff changeset
9
kono
parents:
diff changeset
10 #include <stdlib.h>
kono
parents:
diff changeset
11 #include <unistd.h>
kono
parents:
diff changeset
12 #ifdef __rtems__
kono
parents:
diff changeset
13 void rtems_cache_flush_multiple_data_lines( const void *, size_t );
kono
parents:
diff changeset
14 #else
kono
parents:
diff changeset
15 #include <sys/syscall.h>
kono
parents:
diff changeset
16 #ifdef __MINT__
kono
parents:
diff changeset
17 #include <mint/mintbind.h>
kono
parents:
diff changeset
18 #include <mint/ssystem.h>
kono
parents:
diff changeset
19 #else
kono
parents:
diff changeset
20 #include <asm/cachectl.h>
kono
parents:
diff changeset
21 #endif
kono
parents:
diff changeset
22 #endif
kono
parents:
diff changeset
23
kono
parents:
diff changeset
24 void ffi_call_SYSV (extended_cif *,
kono
parents:
diff changeset
25 unsigned, unsigned,
kono
parents:
diff changeset
26 void *, void (*fn) ());
kono
parents:
diff changeset
27 void *ffi_prep_args (void *stack, extended_cif *ecif);
kono
parents:
diff changeset
28 void ffi_closure_SYSV (ffi_closure *);
kono
parents:
diff changeset
29 void ffi_closure_struct_SYSV (ffi_closure *);
kono
parents:
diff changeset
30 unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
kono
parents:
diff changeset
31 void *resp, void *args);
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 /* ffi_prep_args is called by the assembly routine once stack space has
kono
parents:
diff changeset
34 been allocated for the function's arguments. */
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 void *
kono
parents:
diff changeset
37 ffi_prep_args (void *stack, extended_cif *ecif)
kono
parents:
diff changeset
38 {
kono
parents:
diff changeset
39 unsigned int i;
kono
parents:
diff changeset
40 void **p_argv;
kono
parents:
diff changeset
41 char *argp;
kono
parents:
diff changeset
42 ffi_type **p_arg;
kono
parents:
diff changeset
43 void *struct_value_ptr;
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 argp = stack;
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 if (
kono
parents:
diff changeset
48 #ifdef __MINT__
kono
parents:
diff changeset
49 (ecif->cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
kono
parents:
diff changeset
50 #endif
kono
parents:
diff changeset
51 (((ecif->cif->rtype->type == FFI_TYPE_STRUCT)
kono
parents:
diff changeset
52 && !ecif->cif->flags)))
kono
parents:
diff changeset
53 struct_value_ptr = ecif->rvalue;
kono
parents:
diff changeset
54 else
kono
parents:
diff changeset
55 struct_value_ptr = NULL;
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 p_argv = ecif->avalue;
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
kono
parents:
diff changeset
60 i != 0;
kono
parents:
diff changeset
61 i--, p_arg++)
kono
parents:
diff changeset
62 {
kono
parents:
diff changeset
63 size_t z = (*p_arg)->size;
kono
parents:
diff changeset
64 int type = (*p_arg)->type;
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 if (z < sizeof (int))
kono
parents:
diff changeset
67 {
kono
parents:
diff changeset
68 switch (type)
kono
parents:
diff changeset
69 {
kono
parents:
diff changeset
70 case FFI_TYPE_SINT8:
kono
parents:
diff changeset
71 *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
kono
parents:
diff changeset
72 break;
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 case FFI_TYPE_UINT8:
kono
parents:
diff changeset
75 *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
kono
parents:
diff changeset
76 break;
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 case FFI_TYPE_SINT16:
kono
parents:
diff changeset
79 *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
kono
parents:
diff changeset
80 break;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 case FFI_TYPE_UINT16:
kono
parents:
diff changeset
83 *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
kono
parents:
diff changeset
84 break;
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 case FFI_TYPE_STRUCT:
kono
parents:
diff changeset
87 #ifdef __MINT__
kono
parents:
diff changeset
88 if (z == 1 || z == 2)
kono
parents:
diff changeset
89 memcpy (argp + 2, *p_argv, z);
kono
parents:
diff changeset
90 else
kono
parents:
diff changeset
91 memcpy (argp, *p_argv, z);
kono
parents:
diff changeset
92 #else
kono
parents:
diff changeset
93 memcpy (argp + sizeof (int) - z, *p_argv, z);
kono
parents:
diff changeset
94 #endif
kono
parents:
diff changeset
95 break;
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 default:
kono
parents:
diff changeset
98 FFI_ASSERT (0);
kono
parents:
diff changeset
99 }
kono
parents:
diff changeset
100 z = sizeof (int);
kono
parents:
diff changeset
101 }
kono
parents:
diff changeset
102 else
kono
parents:
diff changeset
103 {
kono
parents:
diff changeset
104 memcpy (argp, *p_argv, z);
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 /* Align if necessary. */
kono
parents:
diff changeset
107 if ((sizeof(int) - 1) & z)
kono
parents:
diff changeset
108 z = ALIGN(z, sizeof(int));
kono
parents:
diff changeset
109 }
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 p_argv++;
kono
parents:
diff changeset
112 argp += z;
kono
parents:
diff changeset
113 }
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115 return struct_value_ptr;
kono
parents:
diff changeset
116 }
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 #define CIF_FLAGS_INT 1
kono
parents:
diff changeset
119 #define CIF_FLAGS_DINT 2
kono
parents:
diff changeset
120 #define CIF_FLAGS_FLOAT 4
kono
parents:
diff changeset
121 #define CIF_FLAGS_DOUBLE 8
kono
parents:
diff changeset
122 #define CIF_FLAGS_LDOUBLE 16
kono
parents:
diff changeset
123 #define CIF_FLAGS_POINTER 32
kono
parents:
diff changeset
124 #define CIF_FLAGS_STRUCT1 64
kono
parents:
diff changeset
125 #define CIF_FLAGS_STRUCT2 128
kono
parents:
diff changeset
126 #define CIF_FLAGS_SINT8 256
kono
parents:
diff changeset
127 #define CIF_FLAGS_SINT16 512
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 /* Perform machine dependent cif processing */
kono
parents:
diff changeset
130 ffi_status
kono
parents:
diff changeset
131 ffi_prep_cif_machdep (ffi_cif *cif)
kono
parents:
diff changeset
132 {
kono
parents:
diff changeset
133 /* Set the return type flag */
kono
parents:
diff changeset
134 switch (cif->rtype->type)
kono
parents:
diff changeset
135 {
kono
parents:
diff changeset
136 case FFI_TYPE_VOID:
kono
parents:
diff changeset
137 cif->flags = 0;
kono
parents:
diff changeset
138 break;
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 case FFI_TYPE_STRUCT:
kono
parents:
diff changeset
141 if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
kono
parents:
diff changeset
142 cif->rtype->elements[1])
kono
parents:
diff changeset
143 {
kono
parents:
diff changeset
144 cif->flags = 0;
kono
parents:
diff changeset
145 break;
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 switch (cif->rtype->size)
kono
parents:
diff changeset
149 {
kono
parents:
diff changeset
150 case 1:
kono
parents:
diff changeset
151 #ifdef __MINT__
kono
parents:
diff changeset
152 cif->flags = CIF_FLAGS_STRUCT2;
kono
parents:
diff changeset
153 #else
kono
parents:
diff changeset
154 cif->flags = CIF_FLAGS_STRUCT1;
kono
parents:
diff changeset
155 #endif
kono
parents:
diff changeset
156 break;
kono
parents:
diff changeset
157 case 2:
kono
parents:
diff changeset
158 cif->flags = CIF_FLAGS_STRUCT2;
kono
parents:
diff changeset
159 break;
kono
parents:
diff changeset
160 #ifdef __MINT__
kono
parents:
diff changeset
161 case 3:
kono
parents:
diff changeset
162 #endif
kono
parents:
diff changeset
163 case 4:
kono
parents:
diff changeset
164 cif->flags = CIF_FLAGS_INT;
kono
parents:
diff changeset
165 break;
kono
parents:
diff changeset
166 #ifdef __MINT__
kono
parents:
diff changeset
167 case 7:
kono
parents:
diff changeset
168 #endif
kono
parents:
diff changeset
169 case 8:
kono
parents:
diff changeset
170 cif->flags = CIF_FLAGS_DINT;
kono
parents:
diff changeset
171 break;
kono
parents:
diff changeset
172 default:
kono
parents:
diff changeset
173 cif->flags = 0;
kono
parents:
diff changeset
174 break;
kono
parents:
diff changeset
175 }
kono
parents:
diff changeset
176 break;
kono
parents:
diff changeset
177
kono
parents:
diff changeset
178 case FFI_TYPE_FLOAT:
kono
parents:
diff changeset
179 cif->flags = CIF_FLAGS_FLOAT;
kono
parents:
diff changeset
180 break;
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 case FFI_TYPE_DOUBLE:
kono
parents:
diff changeset
183 cif->flags = CIF_FLAGS_DOUBLE;
kono
parents:
diff changeset
184 break;
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 #if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
kono
parents:
diff changeset
187 case FFI_TYPE_LONGDOUBLE:
kono
parents:
diff changeset
188 #ifdef __MINT__
kono
parents:
diff changeset
189 cif->flags = 0;
kono
parents:
diff changeset
190 #else
kono
parents:
diff changeset
191 cif->flags = CIF_FLAGS_LDOUBLE;
kono
parents:
diff changeset
192 #endif
kono
parents:
diff changeset
193 break;
kono
parents:
diff changeset
194 #endif
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 case FFI_TYPE_POINTER:
kono
parents:
diff changeset
197 cif->flags = CIF_FLAGS_POINTER;
kono
parents:
diff changeset
198 break;
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 case FFI_TYPE_SINT64:
kono
parents:
diff changeset
201 case FFI_TYPE_UINT64:
kono
parents:
diff changeset
202 cif->flags = CIF_FLAGS_DINT;
kono
parents:
diff changeset
203 break;
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 case FFI_TYPE_SINT16:
kono
parents:
diff changeset
206 cif->flags = CIF_FLAGS_SINT16;
kono
parents:
diff changeset
207 break;
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 case FFI_TYPE_SINT8:
kono
parents:
diff changeset
210 cif->flags = CIF_FLAGS_SINT8;
kono
parents:
diff changeset
211 break;
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 default:
kono
parents:
diff changeset
214 cif->flags = CIF_FLAGS_INT;
kono
parents:
diff changeset
215 break;
kono
parents:
diff changeset
216 }
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 return FFI_OK;
kono
parents:
diff changeset
219 }
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 void
kono
parents:
diff changeset
222 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
kono
parents:
diff changeset
223 {
kono
parents:
diff changeset
224 extended_cif ecif;
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 ecif.cif = cif;
kono
parents:
diff changeset
227 ecif.avalue = avalue;
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 /* If the return value is a struct and we don't have a return value
kono
parents:
diff changeset
230 address then we need to make one. */
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 if (rvalue == NULL
kono
parents:
diff changeset
233 && cif->rtype->type == FFI_TYPE_STRUCT
kono
parents:
diff changeset
234 && cif->rtype->size > 8)
kono
parents:
diff changeset
235 ecif.rvalue = alloca (cif->rtype->size);
kono
parents:
diff changeset
236 else
kono
parents:
diff changeset
237 ecif.rvalue = rvalue;
kono
parents:
diff changeset
238
kono
parents:
diff changeset
239 switch (cif->abi)
kono
parents:
diff changeset
240 {
kono
parents:
diff changeset
241 case FFI_SYSV:
kono
parents:
diff changeset
242 ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
kono
parents:
diff changeset
243 ecif.rvalue, fn);
kono
parents:
diff changeset
244 break;
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 default:
kono
parents:
diff changeset
247 FFI_ASSERT (0);
kono
parents:
diff changeset
248 break;
kono
parents:
diff changeset
249 }
kono
parents:
diff changeset
250 }
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 static void
kono
parents:
diff changeset
253 ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
kono
parents:
diff changeset
254 {
kono
parents:
diff changeset
255 unsigned int i;
kono
parents:
diff changeset
256 void **p_argv;
kono
parents:
diff changeset
257 char *argp;
kono
parents:
diff changeset
258 ffi_type **p_arg;
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 argp = stack;
kono
parents:
diff changeset
261 p_argv = avalue;
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
kono
parents:
diff changeset
264 {
kono
parents:
diff changeset
265 size_t z;
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 z = (*p_arg)->size;
kono
parents:
diff changeset
268 #ifdef __MINT__
kono
parents:
diff changeset
269 if (cif->flags &&
kono
parents:
diff changeset
270 cif->rtype->type == FFI_TYPE_STRUCT &&
kono
parents:
diff changeset
271 (z == 1 || z == 2))
kono
parents:
diff changeset
272 {
kono
parents:
diff changeset
273 *p_argv = (void *) (argp + 2);
kono
parents:
diff changeset
274
kono
parents:
diff changeset
275 z = 4;
kono
parents:
diff changeset
276 }
kono
parents:
diff changeset
277 else
kono
parents:
diff changeset
278 if (cif->flags &&
kono
parents:
diff changeset
279 cif->rtype->type == FFI_TYPE_STRUCT &&
kono
parents:
diff changeset
280 (z == 3 || z == 4))
kono
parents:
diff changeset
281 {
kono
parents:
diff changeset
282 *p_argv = (void *) (argp);
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 z = 4;
kono
parents:
diff changeset
285 }
kono
parents:
diff changeset
286 else
kono
parents:
diff changeset
287 #endif
kono
parents:
diff changeset
288 if (z <= 4)
kono
parents:
diff changeset
289 {
kono
parents:
diff changeset
290 *p_argv = (void *) (argp + 4 - z);
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 z = 4;
kono
parents:
diff changeset
293 }
kono
parents:
diff changeset
294 else
kono
parents:
diff changeset
295 {
kono
parents:
diff changeset
296 *p_argv = (void *) argp;
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 /* Align if necessary */
kono
parents:
diff changeset
299 if ((sizeof(int) - 1) & z)
kono
parents:
diff changeset
300 z = ALIGN(z, sizeof(int));
kono
parents:
diff changeset
301 }
kono
parents:
diff changeset
302
kono
parents:
diff changeset
303 p_argv++;
kono
parents:
diff changeset
304 argp += z;
kono
parents:
diff changeset
305 }
kono
parents:
diff changeset
306 }
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 unsigned int
kono
parents:
diff changeset
309 ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
kono
parents:
diff changeset
310 {
kono
parents:
diff changeset
311 ffi_cif *cif;
kono
parents:
diff changeset
312 void **arg_area;
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 cif = closure->cif;
kono
parents:
diff changeset
315 arg_area = (void**) alloca (cif->nargs * sizeof (void *));
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 ffi_prep_incoming_args_SYSV(args, arg_area, cif);
kono
parents:
diff changeset
318
kono
parents:
diff changeset
319 (closure->fun) (cif, resp, arg_area, closure->user_data);
kono
parents:
diff changeset
320
kono
parents:
diff changeset
321 return cif->flags;
kono
parents:
diff changeset
322 }
kono
parents:
diff changeset
323
kono
parents:
diff changeset
324 ffi_status
kono
parents:
diff changeset
325 ffi_prep_closure_loc (ffi_closure* closure,
kono
parents:
diff changeset
326 ffi_cif* cif,
kono
parents:
diff changeset
327 void (*fun)(ffi_cif*,void*,void**,void*),
kono
parents:
diff changeset
328 void *user_data,
kono
parents:
diff changeset
329 void *codeloc)
kono
parents:
diff changeset
330 {
kono
parents:
diff changeset
331 if (cif->abi != FFI_SYSV)
kono
parents:
diff changeset
332 return FFI_BAD_ABI;
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 *(unsigned short *)closure->tramp = 0x207c;
kono
parents:
diff changeset
335 *(void **)(closure->tramp + 2) = codeloc;
kono
parents:
diff changeset
336 *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
kono
parents:
diff changeset
337
kono
parents:
diff changeset
338 if (
kono
parents:
diff changeset
339 #ifdef __MINT__
kono
parents:
diff changeset
340 (cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
kono
parents:
diff changeset
341 #endif
kono
parents:
diff changeset
342 (((cif->rtype->type == FFI_TYPE_STRUCT)
kono
parents:
diff changeset
343 && !cif->flags)))
kono
parents:
diff changeset
344 *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
kono
parents:
diff changeset
345 else
kono
parents:
diff changeset
346 *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 #ifdef __rtems__
kono
parents:
diff changeset
349 rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
kono
parents:
diff changeset
350 #elif defined(__MINT__)
kono
parents:
diff changeset
351 Ssystem(S_FLUSHCACHE, codeloc, FFI_TRAMPOLINE_SIZE);
kono
parents:
diff changeset
352 #else
kono
parents:
diff changeset
353 syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
kono
parents:
diff changeset
354 FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
kono
parents:
diff changeset
355 #endif
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 closure->cif = cif;
kono
parents:
diff changeset
358 closure->user_data = user_data;
kono
parents:
diff changeset
359 closure->fun = fun;
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361 return FFI_OK;
kono
parents:
diff changeset
362 }