1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1998 Cygnus Solutions
3 Copyright (c) 2004 Simon Posnjak
4 Copyright (c) 2005 Axis Communications AB
5 Copyright (C) 2007 Free Software Foundation, Inc.
7 CRIS Foreign Function Interface
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 ``Software''), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice shall be included
18 in all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 OTHER DEALINGS IN THE SOFTWARE.
27 ----------------------------------------------------------------------- */
30 #include <ffi_common.h>
32 #define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
35 initialize_aggregate_packed_struct (ffi_type * arg)
39 FFI_ASSERT (arg != NULL);
41 FFI_ASSERT (arg->elements != NULL);
42 FFI_ASSERT (arg->size == 0);
43 FFI_ASSERT (arg->alignment == 0);
45 ptr = &(arg->elements[0]);
47 while ((*ptr) != NULL)
49 if (((*ptr)->size == 0)
50 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
51 return FFI_BAD_TYPEDEF;
53 FFI_ASSERT (ffi_type_test ((*ptr)));
55 arg->size += (*ptr)->size;
57 arg->alignment = (arg->alignment > (*ptr)->alignment) ?
58 arg->alignment : (*ptr)->alignment;
64 return FFI_BAD_TYPEDEF;
70 ffi_prep_args (char *stack, extended_cif * ecif)
73 unsigned int struct_count = 0;
80 p_argv = ecif->avalue;
82 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
83 (i != 0); i--, p_arg++)
87 switch ((*p_arg)->type)
94 memcpy (argp, *p_argv, z);
99 memcpy (argp, *p_argv, z);
104 unsigned int uiLocOnStack;
106 uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
107 struct_count = struct_count + (*p_arg)->size;
108 *(unsigned int *) argp =
109 (unsigned int) (UINT32 *) (stack + uiLocOnStack);
110 memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
116 if (z < sizeof (int))
118 switch ((*p_arg)->type)
121 *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
125 *(unsigned int *) argp =
126 (unsigned int) *(UINT8 *) (*p_argv);
129 case FFI_TYPE_SINT16:
130 *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
133 case FFI_TYPE_UINT16:
134 *(unsigned int *) argp =
135 (unsigned int) *(UINT16 *) (*p_argv);
143 else if (z == sizeof (int))
144 *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
146 memcpy (argp, *p_argv, z);
153 return (struct_count);
157 ffi_prep_cif (ffi_cif * cif,
158 ffi_abi abi, unsigned int nargs,
159 ffi_type * rtype, ffi_type ** atypes)
165 FFI_ASSERT (cif != NULL);
166 FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI);
169 cif->arg_types = atypes;
175 if ((cif->rtype->size == 0)
176 && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
177 return FFI_BAD_TYPEDEF;
179 FFI_ASSERT_VALID_TYPE (cif->rtype);
181 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
183 if (((*ptr)->size == 0)
184 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
185 return FFI_BAD_TYPEDEF;
187 FFI_ASSERT_VALID_TYPE (*ptr);
189 if (((*ptr)->alignment - 1) & bytes)
190 bytes = ALIGN (bytes, (*ptr)->alignment);
191 if ((*ptr)->type == FFI_TYPE_STRUCT)
193 if ((*ptr)->size > 8)
195 bytes += (*ptr)->size;
196 bytes += sizeof (void *);
200 if ((*ptr)->size > 4)
207 bytes += STACK_ARG_SIZE ((*ptr)->size);
212 return ffi_prep_cif_machdep (cif);
216 ffi_prep_cif_machdep (ffi_cif * cif)
218 switch (cif->rtype->type)
221 case FFI_TYPE_STRUCT:
223 case FFI_TYPE_DOUBLE:
224 case FFI_TYPE_SINT64:
225 case FFI_TYPE_UINT64:
226 cif->flags = (unsigned) cif->rtype->type;
230 cif->flags = FFI_TYPE_INT;
237 extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
239 unsigned, unsigned, unsigned *, void (*fn) ())
240 __attribute__ ((__visibility__ ("hidden")));
243 ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
248 ecif.avalue = avalue;
250 if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
252 ecif.rvalue = alloca (cif->rtype->size);
255 ecif.rvalue = rvalue;
260 ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
261 cif->flags, ecif.rvalue, fn);
269 /* Because the following variables are not exported outside libffi, we
272 /* Assembly code for the jump stub. */
273 extern const char ffi_cris_trampoline_template[]
274 __attribute__ ((__visibility__ ("hidden")));
276 /* Offset into ffi_cris_trampoline_template of where to put the
277 ffi_prep_closure_inner function. */
278 extern const int ffi_cris_trampoline_fn_offset
279 __attribute__ ((__visibility__ ("hidden")));
281 /* Offset into ffi_cris_trampoline_template of where to put the
283 extern const int ffi_cris_trampoline_closure_offset
284 __attribute__ ((__visibility__ ("hidden")));
286 /* This function is sibling-called (jumped to) by the closure
287 trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
288 PARAMS[4] to simplify handling of a straddling parameter. A copy
289 of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are
290 put at the appropriate place in CLOSURE which is then executed and
291 the return value is passed back to the caller. */
293 static unsigned long long
294 ffi_prep_closure_inner (void **params, ffi_closure* closure)
296 char *register_args = (char *) params;
297 void *struct_ret = params[5];
298 char *stack_args = params[6];
299 char *ptr = register_args;
300 ffi_cif *cif = closure->cif;
301 ffi_type **arg_types = cif->arg_types;
303 /* Max room needed is number of arguments as 64-bit values. */
304 void **avalue = alloca (closure->cif->nargs * sizeof(void *));
309 /* Find the address of each argument. */
310 for (i = 0, doing_regs = 1; i < cif->nargs; i++)
312 /* Types up to and including 8 bytes go by-value. */
313 if (arg_types[i]->size <= 4)
318 else if (arg_types[i]->size <= 8)
325 FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
327 /* Passed by-reference, so copy the pointer. */
328 avalue[i] = *(void **) ptr;
332 /* If we've handled more arguments than fit in registers, start
333 looking at the those passed on the stack. Step over the
334 first one if we had a straddling parameter. */
335 if (doing_regs && ptr >= register_args + 4*4)
337 ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
342 /* Invoke the closure. */
345 cif->rtype->type == FFI_TYPE_STRUCT
346 /* The caller allocated space for the return
347 structure, and passed a pointer to this space in
351 /* We take advantage of being able to ignore that
352 the high part isn't set if the return value is
353 not in R10:R11, but in R10 only. */
356 avalue, closure->user_data);
361 /* API function: Prepare the trampoline. */
364 ffi_prep_closure_loc (ffi_closure* closure,
366 void (*fun)(ffi_cif *, void *, void **, void*),
370 void *innerfn = ffi_prep_closure_inner;
371 FFI_ASSERT (cif->abi == FFI_SYSV);
373 closure->user_data = user_data;
375 memcpy (closure->tramp, ffi_cris_trampoline_template,
376 FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
377 memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
378 &innerfn, sizeof (void *));
379 memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
380 &codeloc, sizeof (void *));