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.
6
7 CRIS Foreign Function Interface
8
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:
16
17 The above copyright notice and this permission notice shall be included
18 in all copies or substantial portions of the Software.
19
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 ----------------------------------------------------------------------- */
28
29 #include <ffi.h>
30 #include <ffi_common.h>
31
32 #define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
33
34 static ffi_status
initialize_aggregate_packed_struct(ffi_type * arg)35 initialize_aggregate_packed_struct (ffi_type * arg)
36 {
37 ffi_type **ptr;
38
39 FFI_ASSERT (arg != NULL);
40
41 FFI_ASSERT (arg->elements != NULL);
42 FFI_ASSERT (arg->size == 0);
43 FFI_ASSERT (arg->alignment == 0);
44
45 ptr = &(arg->elements[0]);
46
47 while ((*ptr) != NULL)
48 {
49 if (((*ptr)->size == 0)
50 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
51 return FFI_BAD_TYPEDEF;
52
53 FFI_ASSERT (ffi_type_test ((*ptr)));
54
55 arg->size += (*ptr)->size;
56
57 arg->alignment = (arg->alignment > (*ptr)->alignment) ?
58 arg->alignment : (*ptr)->alignment;
59
60 ptr++;
61 }
62
63 if (arg->size == 0)
64 return FFI_BAD_TYPEDEF;
65 else
66 return FFI_OK;
67 }
68
69 int
ffi_prep_args(char * stack,extended_cif * ecif)70 ffi_prep_args (char *stack, extended_cif * ecif)
71 {
72 unsigned int i;
73 unsigned int struct_count = 0;
74 void **p_argv;
75 char *argp;
76 ffi_type **p_arg;
77
78 argp = stack;
79
80 p_argv = ecif->avalue;
81
82 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
83 (i != 0); i--, p_arg++)
84 {
85 size_t z;
86
87 switch ((*p_arg)->type)
88 {
89 case FFI_TYPE_STRUCT:
90 {
91 z = (*p_arg)->size;
92 if (z <= 4)
93 {
94 memcpy (argp, *p_argv, z);
95 z = 4;
96 }
97 else if (z <= 8)
98 {
99 memcpy (argp, *p_argv, z);
100 z = 8;
101 }
102 else
103 {
104 unsigned int uiLocOnStack;
105 z = sizeof (void *);
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);
111 }
112 break;
113 }
114 default:
115 z = (*p_arg)->size;
116 if (z < sizeof (int))
117 {
118 switch ((*p_arg)->type)
119 {
120 case FFI_TYPE_SINT8:
121 *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
122 break;
123
124 case FFI_TYPE_UINT8:
125 *(unsigned int *) argp =
126 (unsigned int) *(UINT8 *) (*p_argv);
127 break;
128
129 case FFI_TYPE_SINT16:
130 *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
131 break;
132
133 case FFI_TYPE_UINT16:
134 *(unsigned int *) argp =
135 (unsigned int) *(UINT16 *) (*p_argv);
136 break;
137
138 default:
139 FFI_ASSERT (0);
140 }
141 z = sizeof (int);
142 }
143 else if (z == sizeof (int))
144 *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
145 else
146 memcpy (argp, *p_argv, z);
147 break;
148 }
149 p_argv++;
150 argp += z;
151 }
152
153 return (struct_count);
154 }
155
156 ffi_status
ffi_prep_cif(ffi_cif * cif,ffi_abi abi,unsigned int nargs,ffi_type * rtype,ffi_type ** atypes)157 ffi_prep_cif (ffi_cif * cif,
158 ffi_abi abi, unsigned int nargs,
159 ffi_type * rtype, ffi_type ** atypes)
160 {
161 unsigned bytes = 0;
162 unsigned int i;
163 ffi_type **ptr;
164
165 FFI_ASSERT (cif != NULL);
166 FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
167
168 cif->abi = abi;
169 cif->arg_types = atypes;
170 cif->nargs = nargs;
171 cif->rtype = rtype;
172
173 cif->flags = 0;
174
175 if ((cif->rtype->size == 0)
176 && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
177 return FFI_BAD_TYPEDEF;
178
179 FFI_ASSERT_VALID_TYPE (cif->rtype);
180
181 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
182 {
183 if (((*ptr)->size == 0)
184 && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
185 return FFI_BAD_TYPEDEF;
186
187 FFI_ASSERT_VALID_TYPE (*ptr);
188
189 if (((*ptr)->alignment - 1) & bytes)
190 bytes = ALIGN (bytes, (*ptr)->alignment);
191 if ((*ptr)->type == FFI_TYPE_STRUCT)
192 {
193 if ((*ptr)->size > 8)
194 {
195 bytes += (*ptr)->size;
196 bytes += sizeof (void *);
197 }
198 else
199 {
200 if ((*ptr)->size > 4)
201 bytes += 8;
202 else
203 bytes += 4;
204 }
205 }
206 else
207 bytes += STACK_ARG_SIZE ((*ptr)->size);
208 }
209
210 cif->bytes = bytes;
211
212 return ffi_prep_cif_machdep (cif);
213 }
214
215 ffi_status
ffi_prep_cif_machdep(ffi_cif * cif)216 ffi_prep_cif_machdep (ffi_cif * cif)
217 {
218 switch (cif->rtype->type)
219 {
220 case FFI_TYPE_VOID:
221 case FFI_TYPE_STRUCT:
222 case FFI_TYPE_FLOAT:
223 case FFI_TYPE_DOUBLE:
224 case FFI_TYPE_SINT64:
225 case FFI_TYPE_UINT64:
226 cif->flags = (unsigned) cif->rtype->type;
227 break;
228
229 default:
230 cif->flags = FFI_TYPE_INT;
231 break;
232 }
233
234 return FFI_OK;
235 }
236
237 extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
238 extended_cif *,
239 unsigned, unsigned, unsigned *, void (*fn) ())
240 __attribute__ ((__visibility__ ("hidden")));
241
242 void
ffi_call(ffi_cif * cif,void (* fn)(),void * rvalue,void ** avalue)243 ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
244 {
245 extended_cif ecif;
246
247 ecif.cif = cif;
248 ecif.avalue = avalue;
249
250 if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
251 {
252 ecif.rvalue = alloca (cif->rtype->size);
253 }
254 else
255 ecif.rvalue = rvalue;
256
257 switch (cif->abi)
258 {
259 case FFI_SYSV:
260 ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
261 cif->flags, ecif.rvalue, fn);
262 break;
263 default:
264 FFI_ASSERT (0);
265 break;
266 }
267 }
268
269 /* Because the following variables are not exported outside libffi, we
270 mark them hidden. */
271
272 /* Assembly code for the jump stub. */
273 extern const char ffi_cris_trampoline_template[]
274 __attribute__ ((__visibility__ ("hidden")));
275
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")));
280
281 /* Offset into ffi_cris_trampoline_template of where to put the
282 closure data. */
283 extern const int ffi_cris_trampoline_closure_offset
284 __attribute__ ((__visibility__ ("hidden")));
285
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. */
292
293 static unsigned long long
ffi_prep_closure_inner(void ** params,ffi_closure * closure)294 ffi_prep_closure_inner (void **params, ffi_closure* closure)
295 {
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;
302
303 /* Max room needed is number of arguments as 64-bit values. */
304 void **avalue = alloca (closure->cif->nargs * sizeof(void *));
305 int i;
306 int doing_regs;
307 long long llret = 0;
308
309 /* Find the address of each argument. */
310 for (i = 0, doing_regs = 1; i < cif->nargs; i++)
311 {
312 /* Types up to and including 8 bytes go by-value. */
313 if (arg_types[i]->size <= 4)
314 {
315 avalue[i] = ptr;
316 ptr += 4;
317 }
318 else if (arg_types[i]->size <= 8)
319 {
320 avalue[i] = ptr;
321 ptr += 8;
322 }
323 else
324 {
325 FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
326
327 /* Passed by-reference, so copy the pointer. */
328 avalue[i] = *(void **) ptr;
329 ptr += 4;
330 }
331
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)
336 {
337 ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
338 doing_regs = 0;
339 }
340 }
341
342 /* Invoke the closure. */
343 (closure->fun) (cif,
344
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
348 R9. */
349 ? struct_ret
350
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. */
354 : (void *) &llret,
355
356 avalue, closure->user_data);
357
358 return llret;
359 }
360
361 /* API function: Prepare the trampoline. */
362
363 ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)364 ffi_prep_closure_loc (ffi_closure* closure,
365 ffi_cif* cif,
366 void (*fun)(ffi_cif *, void *, void **, void*),
367 void *user_data,
368 void *codeloc)
369 {
370 void *innerfn = ffi_prep_closure_inner;
371 FFI_ASSERT (cif->abi == FFI_SYSV);
372 closure->cif = cif;
373 closure->user_data = user_data;
374 closure->fun = fun;
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 *));
381
382 return FFI_OK;
383 }
384