Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libffi / src / cris / ffi.c
blob364c990f6f3feeeb583a2457e7223560ffa97c01
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1998 Cygnus Solutions
3 Copyright (c) 2004 Simon Posnjak
4 Copyright (c) 2005 Axis Communications AB
6 CRIS Foreign Function Interface
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 ``Software''), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice shall be included
17 in all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 OTHER DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
28 #include <ffi.h>
29 #include <ffi_common.h>
31 #define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
33 static ffi_status
34 initialize_aggregate_packed_struct (ffi_type * arg)
36 ffi_type **ptr;
38 FFI_ASSERT (arg != NULL);
40 FFI_ASSERT (arg->elements != NULL);
41 FFI_ASSERT (arg->size == 0);
42 FFI_ASSERT (arg->alignment == 0);
44 ptr = &(arg->elements[0]);
46 while ((*ptr) != NULL)
48 if (((*ptr)->size == 0)
49 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
50 return FFI_BAD_TYPEDEF;
52 FFI_ASSERT (ffi_type_test ((*ptr)));
54 arg->size += (*ptr)->size;
56 arg->alignment = (arg->alignment > (*ptr)->alignment) ?
57 arg->alignment : (*ptr)->alignment;
59 ptr++;
62 if (arg->size == 0)
63 return FFI_BAD_TYPEDEF;
64 else
65 return FFI_OK;
68 int
69 ffi_prep_args (char *stack, extended_cif * ecif)
71 unsigned int i;
72 unsigned int struct_count = 0;
73 void **p_argv;
74 char *argp;
75 ffi_type **p_arg;
77 argp = stack;
79 p_argv = ecif->avalue;
81 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
82 (i != 0); i--, p_arg++)
84 size_t z;
86 switch ((*p_arg)->type)
88 case FFI_TYPE_STRUCT:
90 z = (*p_arg)->size;
91 if (z <= 4)
93 memcpy (argp, *p_argv, z);
94 z = 4;
96 else if (z <= 8)
98 memcpy (argp, *p_argv, z);
99 z = 8;
101 else
103 unsigned int uiLocOnStack;
104 z = sizeof (void *);
105 uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
106 struct_count = struct_count + (*p_arg)->size;
107 *(unsigned int *) argp =
108 (unsigned int) (UINT32 *) (stack + uiLocOnStack);
109 memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
111 break;
113 default:
114 z = (*p_arg)->size;
115 if (z < sizeof (int))
117 switch ((*p_arg)->type)
119 case FFI_TYPE_SINT8:
120 *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
121 break;
123 case FFI_TYPE_UINT8:
124 *(unsigned int *) argp =
125 (unsigned int) *(UINT8 *) (*p_argv);
126 break;
128 case FFI_TYPE_SINT16:
129 *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
130 break;
132 case FFI_TYPE_UINT16:
133 *(unsigned int *) argp =
134 (unsigned int) *(UINT16 *) (*p_argv);
135 break;
137 default:
138 FFI_ASSERT (0);
140 z = sizeof (int);
142 else if (z == sizeof (int))
143 *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
144 else
145 memcpy (argp, *p_argv, z);
146 break;
148 p_argv++;
149 argp += z;
152 return (struct_count);
155 ffi_status
156 ffi_prep_cif (ffi_cif * cif,
157 ffi_abi abi, unsigned int nargs,
158 ffi_type * rtype, ffi_type ** atypes)
160 unsigned bytes = 0;
161 unsigned int i;
162 ffi_type **ptr;
164 FFI_ASSERT (cif != NULL);
165 FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
167 cif->abi = abi;
168 cif->arg_types = atypes;
169 cif->nargs = nargs;
170 cif->rtype = rtype;
172 cif->flags = 0;
174 if ((cif->rtype->size == 0)
175 && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
176 return FFI_BAD_TYPEDEF;
178 FFI_ASSERT_VALID_TYPE (cif->rtype);
180 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
182 if (((*ptr)->size == 0)
183 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
184 return FFI_BAD_TYPEDEF;
186 FFI_ASSERT_VALID_TYPE (*ptr);
188 if (((*ptr)->alignment - 1) & bytes)
189 bytes = ALIGN (bytes, (*ptr)->alignment);
190 if ((*ptr)->type == FFI_TYPE_STRUCT)
192 if ((*ptr)->size > 8)
194 bytes += (*ptr)->size;
195 bytes += sizeof (void *);
197 else
199 if ((*ptr)->size > 4)
200 bytes += 8;
201 else
202 bytes += 4;
205 else
206 bytes += STACK_ARG_SIZE ((*ptr)->size);
209 cif->bytes = bytes;
211 return ffi_prep_cif_machdep (cif);
214 ffi_status
215 ffi_prep_cif_machdep (ffi_cif * cif)
217 switch (cif->rtype->type)
219 case FFI_TYPE_VOID:
220 case FFI_TYPE_STRUCT:
221 case FFI_TYPE_FLOAT:
222 case FFI_TYPE_DOUBLE:
223 case FFI_TYPE_SINT64:
224 case FFI_TYPE_UINT64:
225 cif->flags = (unsigned) cif->rtype->type;
226 break;
228 default:
229 cif->flags = FFI_TYPE_INT;
230 break;
233 return FFI_OK;
236 extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
237 extended_cif *,
238 unsigned, unsigned, unsigned *, void (*fn) ())
239 __attribute__ ((__visibility__ ("hidden")));
241 void
242 ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
244 extended_cif ecif;
246 ecif.cif = cif;
247 ecif.avalue = avalue;
249 if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
251 ecif.rvalue = alloca (cif->rtype->size);
253 else
254 ecif.rvalue = rvalue;
256 switch (cif->abi)
258 case FFI_SYSV:
259 ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
260 cif->flags, ecif.rvalue, fn);
261 break;
262 default:
263 FFI_ASSERT (0);
264 break;
268 /* Because the following variables are not exported outside libffi, we
269 mark them hidden. */
271 /* Assembly code for the jump stub. */
272 extern const char ffi_cris_trampoline_template[]
273 __attribute__ ((__visibility__ ("hidden")));
275 /* Offset into ffi_cris_trampoline_template of where to put the
276 ffi_prep_closure_inner function. */
277 extern const int ffi_cris_trampoline_fn_offset
278 __attribute__ ((__visibility__ ("hidden")));
280 /* Offset into ffi_cris_trampoline_template of where to put the
281 closure data. */
282 extern const int ffi_cris_trampoline_closure_offset
283 __attribute__ ((__visibility__ ("hidden")));
285 /* This function is sibling-called (jumped to) by the closure
286 trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
287 PARAMS[4] to simplify handling of a straddling parameter. A copy
288 of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are
289 put at the appropriate place in CLOSURE which is then executed and
290 the return value is passed back to the caller. */
292 static unsigned long long
293 ffi_prep_closure_inner (void **params, ffi_closure* closure)
295 char *register_args = (char *) params;
296 void *struct_ret = params[5];
297 char *stack_args = params[6];
298 char *ptr = register_args;
299 ffi_cif *cif = closure->cif;
300 ffi_type **arg_types = cif->arg_types;
302 /* Max room needed is number of arguments as 64-bit values. */
303 void **avalue = alloca (closure->cif->nargs * sizeof(void *));
304 int i;
305 int doing_regs;
306 long long llret = 0;
308 /* Find the address of each argument. */
309 for (i = 0, doing_regs = 1; i < cif->nargs; i++)
311 /* Types up to and including 8 bytes go by-value. */
312 if (arg_types[i]->size <= 4)
314 avalue[i] = ptr;
315 ptr += 4;
317 else if (arg_types[i]->size <= 8)
319 avalue[i] = ptr;
320 ptr += 8;
322 else
324 FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
326 /* Passed by-reference, so copy the pointer. */
327 avalue[i] = *(void **) ptr;
328 ptr += 4;
331 /* If we've handled more arguments than fit in registers, start
332 looking at the those passed on the stack. Step over the
333 first one if we had a straddling parameter. */
334 if (doing_regs && ptr >= register_args + 4*4)
336 ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
337 doing_regs = 0;
341 /* Invoke the closure. */
342 (closure->fun) (cif,
344 cif->rtype->type == FFI_TYPE_STRUCT
345 /* The caller allocated space for the return
346 structure, and passed a pointer to this space in
347 R9. */
348 ? struct_ret
350 /* We take advantage of being able to ignore that
351 the high part isn't set if the return value is
352 not in R10:R11, but in R10 only. */
353 : (void *) &llret,
355 avalue, closure->user_data);
357 return llret;
360 /* API function: Prepare the trampoline. */
362 ffi_status
363 ffi_prep_closure (ffi_closure* closure,
364 ffi_cif* cif,
365 void (*fun)(ffi_cif *, void *, void **, void*),
366 void *user_data)
368 void *innerfn = ffi_prep_closure_inner;
369 FFI_ASSERT (cif->abi == FFI_SYSV);
370 closure->cif = cif;
371 closure->user_data = user_data;
372 closure->fun = fun;
373 memcpy (closure->tramp, ffi_cris_trampoline_template,
374 FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
375 memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
376 &innerfn, sizeof (void *));
377 memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
378 &closure, sizeof (void *));
380 return FFI_OK;