OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libffi/] [src/] [cris/] [ffi.c] - Blame information for rev 745

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 732 jeremybenn
/* -----------------------------------------------------------------------
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
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
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
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
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
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
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
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.