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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libffi/] [src/] [x86/] [ffi.c] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* -----------------------------------------------------------------------
2
   ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
3
           Copyright (c) 2002  Ranjit Mathew
4
           Copyright (c) 2002  Bo Thorsen
5
           Copyright (c) 2002  Roger Sayle
6
 
7
   x86 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 CYGNUS SOLUTIONS 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
#ifndef __x86_64__
30
 
31
#include <ffi.h>
32
#include <ffi_common.h>
33
 
34
#include <stdlib.h>
35
 
36
/* ffi_prep_args is called by the assembly routine once stack space
37
   has been allocated for the function's arguments */
38
 
39
/*@-exportheader@*/
40
void ffi_prep_args(char *stack, extended_cif *ecif)
41
/*@=exportheader@*/
42
{
43
  register unsigned int i;
44
  register void **p_argv;
45
  register char *argp;
46
  register ffi_type **p_arg;
47
 
48
  argp = stack;
49
 
50
  if (ecif->cif->flags == FFI_TYPE_STRUCT)
51
    {
52
      *(void **) argp = ecif->rvalue;
53
      argp += 4;
54
    }
55
 
56
  p_argv = ecif->avalue;
57
 
58
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
59
       i != 0;
60
       i--, p_arg++)
61
    {
62
      size_t z;
63
 
64
      /* Align if necessary */
65
      if ((sizeof(int) - 1) & (unsigned) argp)
66
        argp = (char *) ALIGN(argp, sizeof(int));
67
 
68
      z = (*p_arg)->size;
69
      if (z < sizeof(int))
70
        {
71
          z = sizeof(int);
72
          switch ((*p_arg)->type)
73
            {
74
            case FFI_TYPE_SINT8:
75
              *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
76
              break;
77
 
78
            case FFI_TYPE_UINT8:
79
              *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
80
              break;
81
 
82
            case FFI_TYPE_SINT16:
83
              *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
84
              break;
85
 
86
            case FFI_TYPE_UINT16:
87
              *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
88
              break;
89
 
90
            case FFI_TYPE_SINT32:
91
              *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
92
              break;
93
 
94
            case FFI_TYPE_UINT32:
95
              *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
96
              break;
97
 
98
            case FFI_TYPE_STRUCT:
99
              *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
100
              break;
101
 
102
            default:
103
              FFI_ASSERT(0);
104
            }
105
        }
106
      else
107
        {
108
          memcpy(argp, *p_argv, z);
109
        }
110
      p_argv++;
111
      argp += z;
112
    }
113
 
114
  return;
115
}
116
 
117
/* Perform machine dependent cif processing */
118
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
119
{
120
  /* Set the return type flag */
121
  switch (cif->rtype->type)
122
    {
123
    case FFI_TYPE_VOID:
124
#ifndef X86_WIN32
125
    case FFI_TYPE_STRUCT:
126
#endif
127
    case FFI_TYPE_SINT64:
128
    case FFI_TYPE_FLOAT:
129
    case FFI_TYPE_DOUBLE:
130
    case FFI_TYPE_LONGDOUBLE:
131
      cif->flags = (unsigned) cif->rtype->type;
132
      break;
133
 
134
    case FFI_TYPE_UINT64:
135
      cif->flags = FFI_TYPE_SINT64;
136
      break;
137
 
138
#ifdef X86_WIN32
139
    case FFI_TYPE_STRUCT:
140
      if (cif->rtype->size == 1)
141
        {
142
          cif->flags = FFI_TYPE_SINT8; /* same as char size */
143
        }
144
      else if (cif->rtype->size == 2)
145
        {
146
          cif->flags = FFI_TYPE_SINT16; /* same as short size */
147
        }
148
      else if (cif->rtype->size == 4)
149
        {
150
          cif->flags = FFI_TYPE_INT; /* same as int type */
151
        }
152
      else if (cif->rtype->size == 8)
153
        {
154
          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
155
        }
156
      else
157
        {
158
          cif->flags = FFI_TYPE_STRUCT;
159
        }
160
      break;
161
#endif
162
 
163
    default:
164
      cif->flags = FFI_TYPE_INT;
165
      break;
166
    }
167
 
168
  return FFI_OK;
169
}
170
 
171
/*@-declundef@*/
172
/*@-exportheader@*/
173
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
174
                          /*@out@*/ extended_cif *,
175
                          unsigned, unsigned,
176
                          /*@out@*/ unsigned *,
177
                          void (*fn)());
178
/*@=declundef@*/
179
/*@=exportheader@*/
180
 
181
#ifdef X86_WIN32
182
/*@-declundef@*/
183
/*@-exportheader@*/
184
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *),
185
                          /*@out@*/ extended_cif *,
186
                          unsigned, unsigned,
187
                          /*@out@*/ unsigned *,
188
                          void (*fn)());
189
/*@=declundef@*/
190
/*@=exportheader@*/
191
#endif /* X86_WIN32 */
192
 
193
void ffi_call(/*@dependent@*/ ffi_cif *cif,
194
              void (*fn)(),
195
              /*@out@*/ void *rvalue,
196
              /*@dependent@*/ void **avalue)
197
{
198
  extended_cif ecif;
199
 
200
  ecif.cif = cif;
201
  ecif.avalue = avalue;
202
 
203
  /* If the return value is a struct and we don't have a return */
204
  /* value address then we need to make one                     */
205
 
206
  if ((rvalue == NULL) &&
207
      (cif->flags == FFI_TYPE_STRUCT))
208
    {
209
      /*@-sysunrecog@*/
210
      ecif.rvalue = alloca(cif->rtype->size);
211
      /*@=sysunrecog@*/
212
    }
213
  else
214
    ecif.rvalue = rvalue;
215
 
216
 
217
  switch (cif->abi)
218
    {
219
    case FFI_SYSV:
220
      /*@-usedef@*/
221
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
222
                    cif->flags, ecif.rvalue, fn);
223
      /*@=usedef@*/
224
      break;
225
#ifdef X86_WIN32
226
    case FFI_STDCALL:
227
      /*@-usedef@*/
228
      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
229
                    cif->flags, ecif.rvalue, fn);
230
      /*@=usedef@*/
231
      break;
232
#endif /* X86_WIN32 */
233
    default:
234
      FFI_ASSERT(0);
235
      break;
236
    }
237
}
238
 
239
 
240
/** private members **/
241
 
242
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
243
                                         void** args, ffi_cif* cif);
244
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
245
     __attribute__ ((regparm(1)));
246
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
247
     __attribute__ ((regparm(1)));
248
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
249
     __attribute__ ((regparm(1)));
250
 
251
/* This function is jumped to by the trampoline */
252
 
253
unsigned int FFI_HIDDEN
254
ffi_closure_SYSV_inner (closure, respp, args)
255
     ffi_closure *closure;
256
     void **respp;
257
     void *args;
258
{
259
  // our various things...
260
  ffi_cif       *cif;
261
  void         **arg_area;
262
 
263
  cif         = closure->cif;
264
  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));
265
 
266
  /* this call will initialize ARG_AREA, such that each
267
   * element in that array points to the corresponding
268
   * value on the stack; and if the function returns
269
   * a structure, it will re-set RESP to point to the
270
   * structure return address.  */
271
 
272
  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
273
 
274
  (closure->fun) (cif, *respp, arg_area, closure->user_data);
275
 
276
  return cif->flags;
277
}
278
 
279
/*@-exportheader@*/
280
static void
281
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
282
                            void **avalue, ffi_cif *cif)
283
/*@=exportheader@*/
284
{
285
  register unsigned int i;
286
  register void **p_argv;
287
  register char *argp;
288
  register ffi_type **p_arg;
289
 
290
  argp = stack;
291
 
292
  if ( cif->flags == FFI_TYPE_STRUCT ) {
293
    *rvalue = *(void **) argp;
294
    argp += 4;
295
  }
296
 
297
  p_argv = avalue;
298
 
299
  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
300
    {
301
      size_t z;
302
 
303
      /* Align if necessary */
304
      if ((sizeof(int) - 1) & (unsigned) argp) {
305
        argp = (char *) ALIGN(argp, sizeof(int));
306
      }
307
 
308
      z = (*p_arg)->size;
309
 
310
      /* because we're little endian, this is what it turns into.   */
311
 
312
      *p_argv = (void*) argp;
313
 
314
      p_argv++;
315
      argp += z;
316
    }
317
 
318
  return;
319
}
320
 
321
/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
322
 
323
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
324
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
325
   unsigned int  __fun = (unsigned int)(FUN); \
326
   unsigned int  __ctx = (unsigned int)(CTX); \
327
   unsigned int  __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \
328
   *(unsigned char*) &__tramp[0] = 0xb8; \
329
   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
330
   *(unsigned char *)  &__tramp[5] = 0xe9; \
331
   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
332
 })
333
 
334
 
335
/* the cif must already be prep'ed */
336
 
337
ffi_status
338
ffi_prep_closure (ffi_closure* closure,
339
                  ffi_cif* cif,
340
                  void (*fun)(ffi_cif*,void*,void**,void*),
341
                  void *user_data)
342
{
343
  FFI_ASSERT (cif->abi == FFI_SYSV);
344
 
345
  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
346
                       &ffi_closure_SYSV,  \
347
                       (void*)closure);
348
 
349
  closure->cif  = cif;
350
  closure->user_data = user_data;
351
  closure->fun  = fun;
352
 
353
  return FFI_OK;
354
}
355
 
356
/* ------- Native raw API support -------------------------------- */
357
 
358
#if !FFI_NO_RAW_API
359
 
360
ffi_status
361
ffi_prep_raw_closure (ffi_raw_closure* closure,
362
                      ffi_cif* cif,
363
                      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
364
                      void *user_data)
365
{
366
  int i;
367
 
368
  FFI_ASSERT (cif->abi == FFI_SYSV);
369
 
370
  // we currently don't support certain kinds of arguments for raw
371
  // closures.  This should be implemented by a separate assembly language
372
  // routine, since it would require argument processing, something we
373
  // don't do now for performance.
374
 
375
  for (i = cif->nargs-1; i >= 0; i--)
376
    {
377
      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
378
      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
379
    }
380
 
381
 
382
  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
383
                       (void*)closure);
384
 
385
  closure->cif  = cif;
386
  closure->user_data = user_data;
387
  closure->fun  = fun;
388
 
389
  return FFI_OK;
390
}
391
 
392
static void
393
ffi_prep_args_raw(char *stack, extended_cif *ecif)
394
{
395
  memcpy (stack, ecif->avalue, ecif->cif->bytes);
396
}
397
 
398
/* we borrow this routine from libffi (it must be changed, though, to
399
 * actually call the function passed in the first argument.  as of
400
 * libffi-1.20, this is not the case.)
401
 */
402
 
403
extern void
404
ffi_call_SYSV(void (*)(char *, extended_cif *),
405
              /*@out@*/ extended_cif *,
406
              unsigned, unsigned,
407
              /*@out@*/ unsigned *,
408
              void (*fn)());
409
 
410
#ifdef X86_WIN32
411
extern void
412
ffi_call_STDCALL(void (*)(char *, extended_cif *),
413
              /*@out@*/ extended_cif *,
414
              unsigned, unsigned,
415
              /*@out@*/ unsigned *,
416
              void (*fn)());
417
#endif /* X86_WIN32 */
418
 
419
void
420
ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
421
             void (*fn)(),
422
             /*@out@*/ void *rvalue,
423
             /*@dependent@*/ ffi_raw *fake_avalue)
424
{
425
  extended_cif ecif;
426
  void **avalue = (void **)fake_avalue;
427
 
428
  ecif.cif = cif;
429
  ecif.avalue = avalue;
430
 
431
  /* If the return value is a struct and we don't have a return */
432
  /* value address then we need to make one                     */
433
 
434
  if ((rvalue == NULL) &&
435
      (cif->rtype->type == FFI_TYPE_STRUCT))
436
    {
437
      /*@-sysunrecog@*/
438
      ecif.rvalue = alloca(cif->rtype->size);
439
      /*@=sysunrecog@*/
440
    }
441
  else
442
    ecif.rvalue = rvalue;
443
 
444
 
445
  switch (cif->abi)
446
    {
447
    case FFI_SYSV:
448
      /*@-usedef@*/
449
      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
450
                    cif->flags, ecif.rvalue, fn);
451
      /*@=usedef@*/
452
      break;
453
#ifdef X86_WIN32
454
    case FFI_STDCALL:
455
      /*@-usedef@*/
456
      ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
457
                    cif->flags, ecif.rvalue, fn);
458
      /*@=usedef@*/
459
      break;
460
#endif /* X86_WIN32 */
461
    default:
462
      FFI_ASSERT(0);
463
      break;
464
    }
465
}
466
 
467
#endif
468
 
469
#endif /* __x86_64__  */

powered by: WebSVN 2.1.0

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