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 *));