eda/EDASQLite: Improved SQL Custom Functions support, now taking an arbitrary set...
[sdk] / deps / libffi-3.0.11 / src / m68k / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c
3
4    m68k Foreign Function Interface
5    ----------------------------------------------------------------------- */
6
7 #include <ffi.h>
8 #include <ffi_common.h>
9
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
23
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);
32
33 /* ffi_prep_args is called by the assembly routine once stack space has
34    been allocated for the function's arguments.  */
35
36 void *
37 ffi_prep_args (void *stack, extended_cif *ecif)
38 {
39   unsigned int i;
40   void **p_argv;
41   char *argp;
42   ffi_type **p_arg;
43   void *struct_value_ptr;
44
45   argp = stack;
46
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;
56
57   p_argv = ecif->avalue;
58
59   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
60        i != 0;
61        i--, p_arg++)
62     {
63       size_t z = (*p_arg)->size;
64       int type = (*p_arg)->type;
65
66       if (z < sizeof (int))
67         {
68           switch (type)
69             {
70             case FFI_TYPE_SINT8:
71               *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
72               break;
73
74             case FFI_TYPE_UINT8:
75               *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
76               break;
77
78             case FFI_TYPE_SINT16:
79               *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
80               break;
81
82             case FFI_TYPE_UINT16:
83               *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
84               break;
85
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;
96
97             default:
98               FFI_ASSERT (0);
99             }
100           z = sizeof (int);
101         }
102       else
103         {
104           memcpy (argp, *p_argv, z);
105
106           /* Align if necessary.  */
107           if ((sizeof(int) - 1) & z)
108             z = ALIGN(z, sizeof(int));
109         }
110
111       p_argv++;
112       argp += z;
113     }
114
115   return struct_value_ptr;
116 }
117
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
127 /* Perform machine dependent cif processing */
128 ffi_status
129 ffi_prep_cif_machdep (ffi_cif *cif)
130 {
131   /* Set the return type flag */
132   switch (cif->rtype->type)
133     {
134     case FFI_TYPE_VOID:
135       cif->flags = 0;
136       break;
137
138     case FFI_TYPE_STRUCT:
139       if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
140           cif->rtype->elements[1])
141         {
142           cif->flags = 0;
143           break;
144         }
145
146       switch (cif->rtype->size)
147         {
148         case 1:
149 #ifdef __MINT__
150           cif->flags = CIF_FLAGS_STRUCT2;
151 #else
152           cif->flags = CIF_FLAGS_STRUCT1;
153 #endif
154           break;
155         case 2:
156           cif->flags = CIF_FLAGS_STRUCT2;
157           break;
158 #ifdef __MINT__
159         case 3:
160 #endif
161         case 4:
162           cif->flags = CIF_FLAGS_INT;
163           break;
164 #ifdef __MINT__
165         case 7:
166 #endif
167         case 8:
168           cif->flags = CIF_FLAGS_DINT;
169           break;
170         default:
171           cif->flags = 0;
172           break;
173         }
174       break;
175
176     case FFI_TYPE_FLOAT:
177       cif->flags = CIF_FLAGS_FLOAT;
178       break;
179
180     case FFI_TYPE_DOUBLE:
181       cif->flags = CIF_FLAGS_DOUBLE;
182       break;
183
184 #if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
185     case FFI_TYPE_LONGDOUBLE:
186 #ifdef __MINT__
187       cif->flags = 0;
188 #else
189       cif->flags = CIF_FLAGS_LDOUBLE;
190 #endif
191       break;
192 #endif
193
194     case FFI_TYPE_POINTER:
195       cif->flags = CIF_FLAGS_POINTER;
196       break;
197
198     case FFI_TYPE_SINT64:
199     case FFI_TYPE_UINT64:
200       cif->flags = CIF_FLAGS_DINT;
201       break;
202
203     default:
204       cif->flags = CIF_FLAGS_INT;
205       break;
206     }
207
208   return FFI_OK;
209 }
210
211 void
212 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
213 {
214   extended_cif ecif;
215
216   ecif.cif = cif;
217   ecif.avalue = avalue;
218
219   /* If the return value is a struct and we don't have a return value
220      address then we need to make one.  */
221
222   if (rvalue == NULL
223       && cif->rtype->type == FFI_TYPE_STRUCT
224       && cif->rtype->size > 8)
225     ecif.rvalue = alloca (cif->rtype->size);
226   else
227     ecif.rvalue = rvalue;
228
229   switch (cif->abi)
230     {
231     case FFI_SYSV:
232       ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
233                      ecif.rvalue, fn);
234       break;
235
236     default:
237       FFI_ASSERT (0);
238       break;
239     }
240 }
241
242 static void
243 ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
244 {
245   unsigned int i;
246   void **p_argv;
247   char *argp;
248   ffi_type **p_arg;
249
250   argp = stack;
251   p_argv = avalue;
252
253   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
254     {
255       size_t z;
256
257       z = (*p_arg)->size;
258 #ifdef __MINT__
259       if (cif->flags &&
260           cif->rtype->type == FFI_TYPE_STRUCT &&
261           (z == 1 || z == 2))
262         {
263           *p_argv = (void *) (argp + 2);
264
265           z = 4;
266         }
267       else
268       if (cif->flags &&
269           cif->rtype->type == FFI_TYPE_STRUCT &&
270           (z == 3 || z == 4))
271         {
272           *p_argv = (void *) (argp);
273
274           z = 4;
275         }
276       else
277 #endif
278       if (z <= 4)
279         {
280           *p_argv = (void *) (argp + 4 - z);
281
282           z = 4;
283         }
284       else
285         {
286           *p_argv = (void *) argp;
287
288           /* Align if necessary */
289           if ((sizeof(int) - 1) & z)
290             z = ALIGN(z, sizeof(int));
291         }
292
293       p_argv++;
294       argp += z;
295     }
296 }
297
298 unsigned int
299 ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
300 {
301   ffi_cif *cif;
302   void **arg_area;
303
304   cif = closure->cif;
305   arg_area = (void**) alloca (cif->nargs * sizeof (void *));
306
307   ffi_prep_incoming_args_SYSV(args, arg_area, cif);
308
309   (closure->fun) (cif, resp, arg_area, closure->user_data);
310
311   return cif->flags;
312 }
313
314 ffi_status
315 ffi_prep_closure_loc (ffi_closure* closure,
316                       ffi_cif* cif,
317                       void (*fun)(ffi_cif*,void*,void**,void*),
318                       void *user_data,
319                       void *codeloc)
320 {
321   if (cif->abi != FFI_SYSV)
322     return FFI_BAD_ABI;
323
324   *(unsigned short *)closure->tramp = 0x207c;
325   *(void **)(closure->tramp + 2) = codeloc;
326   *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
327
328   if (
329 #ifdef __MINT__
330       (cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
331 #endif
332       (((cif->rtype->type == FFI_TYPE_STRUCT)
333          && !cif->flags)))
334     *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
335   else
336     *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
337
338 #ifdef __rtems__
339   rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
340 #elif defined(__MINT__)
341   Ssystem(S_FLUSHCACHE, codeloc, FFI_TRAMPOLINE_SIZE);
342 #else
343   syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
344           FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
345 #endif
346
347   closure->cif  = cif;
348   closure->user_data = user_data;
349   closure->fun  = fun;
350
351   return FFI_OK;
352 }