OSDN Git Service

* Makefile.am: Add CRIS support.
[pf3gnuchains/gcc-fork.git] / libffi / src / cris / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1998 Cygnus Solutions
3            Copyright (c) 2004 Simon Posnjak
4            Copyright (c) 2005 Axis Communications AB
5
6    CRIS Foreign Function Interface
7
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:
15
16    The above copyright notice and this permission notice shall be included
17    in all copies or substantial portions of the Software.
18
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    ----------------------------------------------------------------------- */
27
28 #include <ffi.h>
29 #include <ffi_common.h>
30
31 #define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
32
33 static ffi_status
34 initialize_aggregate_packed_struct (ffi_type * arg)
35 {
36   ffi_type **ptr;
37
38   FFI_ASSERT (arg != NULL);
39
40   FFI_ASSERT (arg->elements != NULL);
41   FFI_ASSERT (arg->size == 0);
42   FFI_ASSERT (arg->alignment == 0);
43
44   ptr = &(arg->elements[0]);
45
46   while ((*ptr) != NULL)
47     {
48       if (((*ptr)->size == 0)
49           && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
50         return FFI_BAD_TYPEDEF;
51
52       FFI_ASSERT (ffi_type_test ((*ptr)));
53
54       arg->size += (*ptr)->size;
55
56       arg->alignment = (arg->alignment > (*ptr)->alignment) ?
57         arg->alignment : (*ptr)->alignment;
58
59       ptr++;
60     }
61
62   if (arg->size == 0)
63     return FFI_BAD_TYPEDEF;
64   else
65     return FFI_OK;
66 }
67
68 int
69 ffi_prep_args (char *stack, extended_cif * ecif)
70 {
71   unsigned int i;
72   unsigned int struct_count = 0;
73   void **p_argv;
74   char *argp;
75   ffi_type **p_arg;
76
77   argp = stack;
78
79   p_argv = ecif->avalue;
80
81   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
82        (i != 0); i--, p_arg++)
83     {
84       size_t z;
85
86       switch ((*p_arg)->type)
87         {
88         case FFI_TYPE_STRUCT:
89           {
90             z = (*p_arg)->size;
91             if (z <= 4)
92               {
93                 memcpy (argp, *p_argv, z);
94                 z = 4;
95               }
96             else if (z <= 8)
97               {
98                 memcpy (argp, *p_argv, z);
99                 z = 8;
100               }
101             else
102               {
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);
110               }
111             break;
112           }
113         default:
114           z = (*p_arg)->size;
115           if (z < sizeof (int))
116             {
117               switch ((*p_arg)->type)
118                 {
119                 case FFI_TYPE_SINT8:
120                   *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
121                   break;
122
123                 case FFI_TYPE_UINT8:
124                   *(unsigned int *) argp =
125                     (unsigned int) *(UINT8 *) (*p_argv);
126                   break;
127
128                 case FFI_TYPE_SINT16:
129                   *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
130                   break;
131
132                 case FFI_TYPE_UINT16:
133                   *(unsigned int *) argp =
134                     (unsigned int) *(UINT16 *) (*p_argv);
135                   break;
136
137                 default:
138                   FFI_ASSERT (0);
139                 }
140               z = sizeof (int);
141             }
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;
147         }
148       p_argv++;
149       argp += z;
150     }
151
152   return (struct_count);
153 }
154
155 ffi_status
156 ffi_prep_cif (ffi_cif * cif,
157               ffi_abi abi, unsigned int nargs,
158               ffi_type * rtype, ffi_type ** atypes)
159 {
160   unsigned bytes = 0;
161   unsigned int i;
162   ffi_type **ptr;
163
164   FFI_ASSERT (cif != NULL);
165   FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
166
167   cif->abi = abi;
168   cif->arg_types = atypes;
169   cif->nargs = nargs;
170   cif->rtype = rtype;
171
172   cif->flags = 0;
173
174   if ((cif->rtype->size == 0)
175       && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
176     return FFI_BAD_TYPEDEF;
177
178   FFI_ASSERT_VALID_TYPE (cif->rtype);
179
180   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
181     {
182       if (((*ptr)->size == 0)
183           && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
184         return FFI_BAD_TYPEDEF;
185
186       FFI_ASSERT_VALID_TYPE (*ptr);
187
188       if (((*ptr)->alignment - 1) & bytes)
189         bytes = ALIGN (bytes, (*ptr)->alignment);
190       if ((*ptr)->type == FFI_TYPE_STRUCT)
191         {
192           if ((*ptr)->size > 8)
193             {
194               bytes += (*ptr)->size;
195               bytes += sizeof (void *);
196             }
197           else
198             {
199               if ((*ptr)->size > 4)
200                 bytes += 8;
201               else
202                 bytes += 4;
203             }
204         }
205       else
206         bytes += STACK_ARG_SIZE ((*ptr)->size);
207     }
208
209   cif->bytes = bytes;
210
211   return ffi_prep_cif_machdep (cif);
212 }
213
214 ffi_status
215 ffi_prep_cif_machdep (ffi_cif * cif)
216 {
217   switch (cif->rtype->type)
218     {
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;
227
228     default:
229       cif->flags = FFI_TYPE_INT;
230       break;
231     }
232
233   return FFI_OK;
234 }
235
236 extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
237                            extended_cif *,
238                            unsigned, unsigned, unsigned *, void (*fn) ())
239      __attribute__ ((__visibility__ ("hidden")));
240
241 void
242 ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
243 {
244   extended_cif ecif;
245
246   ecif.cif = cif;
247   ecif.avalue = avalue;
248
249   if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
250     {
251       ecif.rvalue = alloca (cif->rtype->size);
252     }
253   else
254     ecif.rvalue = rvalue;
255
256   switch (cif->abi)
257     {
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;
265     }
266 }
267
268 /* Because the following variables are not exported outside libffi, we
269    mark them hidden.  */
270
271 /* Assembly code for the jump stub.  */
272 extern const char ffi_cris_trampoline_template[]
273  __attribute__ ((__visibility__ ("hidden")));
274
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")));
279
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")));
284
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.  */
291
292 static unsigned long long
293 ffi_prep_closure_inner (void **params, ffi_closure* closure)
294 {
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;
301
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;
307
308   /* Find the address of each argument.  */
309   for (i = 0, doing_regs = 1; i < cif->nargs; i++)
310     {
311       /* Types up to and including 8 bytes go by-value.  */
312       if (arg_types[i]->size <= 4)
313         {
314           avalue[i] = ptr;
315           ptr += 4;
316         }
317       else if (arg_types[i]->size <= 8)
318         {
319           avalue[i] = ptr;
320           ptr += 8;
321         }
322       else
323         {
324           FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
325
326           /* Passed by-reference, so copy the pointer.  */
327           avalue[i] = *(void **) ptr;
328           ptr += 4;
329         }
330
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)
335         {
336           ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
337           doing_regs = 0;
338         }
339     }
340
341   /* Invoke the closure.  */
342   (closure->fun) (cif,
343
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
349
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,
354
355                   avalue, closure->user_data);
356
357   return llret;
358 }
359
360 /* API function: Prepare the trampoline.  */
361
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)
367 {
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 *));
379
380   return FFI_OK;
381 }