~ubuntu-branches/ubuntu/lucid/gauche-c-wrapper/lucid

« back to all changes in this revision

Viewing changes to libffi/src/cris/ffi.c

  • Committer: Bazaar Package Importer
  • Author(s): NIIBE Yutaka
  • Date: 2008-04-07 09:15:03 UTC
  • Revision ID: james.westby@ubuntu.com-20080407091503-wu0h414koe95kj4i
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}