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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 732 jeremybenn
/* -----------------------------------------------------------------------
2
   ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008  Red Hat, Inc.
3
           Copyright (c) 2002  Ranjit Mathew
4
           Copyright (c) 2002  Bo Thorsen
5
           Copyright (c) 2002  Roger Sayle
6
           Copyright (C) 2008, 2010  Free Software Foundation, Inc.
7
 
8
   x86 Foreign Function Interface
9
 
10
   Permission is hereby granted, free of charge, to any person obtaining
11
   a copy of this software and associated documentation files (the
12
   ``Software''), to deal in the Software without restriction, including
13
   without limitation the rights to use, copy, modify, merge, publish,
14
   distribute, sublicense, and/or sell copies of the Software, and to
15
   permit persons to whom the Software is furnished to do so, subject to
16
   the following conditions:
17
 
18
   The above copyright notice and this permission notice shall be included
19
   in all copies or substantial portions of the Software.
20
 
21
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25
   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28
   DEALINGS IN THE SOFTWARE.
29
   ----------------------------------------------------------------------- */
30
 
31
#if !defined(__x86_64__) || defined(_WIN64)
32
 
33
#ifdef _WIN64
34
#include <windows.h>
35
#endif
36
 
37
#include <ffi.h>
38
#include <ffi_common.h>
39
 
40
#include <stdlib.h>
41
 
42
/* ffi_prep_args is called by the assembly routine once stack space
43
   has been allocated for the function's arguments */
44
 
45
void ffi_prep_args(char *stack, extended_cif *ecif)
46
{
47
  register unsigned int i;
48
  register void **p_argv;
49
  register char *argp;
50
  register ffi_type **p_arg;
51
#ifdef X86_WIN32
52
  size_t p_stack_args[2];
53
  void *p_stack_data[2];
54
  char *argp2 = stack;
55
  int stack_args_count = 0;
56
  int cabi = ecif->cif->abi;
57
#endif
58
 
59
  argp = stack;
60
 
61
  if (ecif->cif->flags == FFI_TYPE_STRUCT
62
#ifdef X86_WIN64
63
      && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
64
          && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
65
#endif
66
      )
67
    {
68
      *(void **) argp = ecif->rvalue;
69
#ifdef X86_WIN32
70
      /* For fastcall/thiscall this is first register-passed
71
         argument.  */
72
      if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
73
        {
74
          p_stack_args[stack_args_count] = sizeof (void*);
75
          p_stack_data[stack_args_count] = argp;
76
          ++stack_args_count;
77
        }
78
#endif
79
      argp += sizeof(void*);
80
    }
81
 
82
  p_argv = ecif->avalue;
83
 
84
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
85
       i != 0;
86
       i--, p_arg++)
87
    {
88
      size_t z;
89
 
90
      /* Align if necessary */
91
      if ((sizeof(void*) - 1) & (size_t) argp)
92
        argp = (char *) ALIGN(argp, sizeof(void*));
93
 
94
      z = (*p_arg)->size;
95
#ifdef X86_WIN64
96
      if (z > sizeof(ffi_arg)
97
          || ((*p_arg)->type == FFI_TYPE_STRUCT
98
              && (z != 1 && z != 2 && z != 4 && z != 8))
99
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
100
          || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
101
#endif
102
          )
103
        {
104
          z = sizeof(ffi_arg);
105
          *(void **)argp = *p_argv;
106
        }
107
      else if ((*p_arg)->type == FFI_TYPE_FLOAT)
108
        {
109
          memcpy(argp, *p_argv, z);
110
        }
111
      else
112
#endif
113
      if (z < sizeof(ffi_arg))
114
        {
115
          z = sizeof(ffi_arg);
116
          switch ((*p_arg)->type)
117
            {
118
            case FFI_TYPE_SINT8:
119
              *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
120
              break;
121
 
122
            case FFI_TYPE_UINT8:
123
              *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
124
              break;
125
 
126
            case FFI_TYPE_SINT16:
127
              *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
128
              break;
129
 
130
            case FFI_TYPE_UINT16:
131
              *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
132
              break;
133
 
134
            case FFI_TYPE_SINT32:
135
              *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
136
              break;
137
 
138
            case FFI_TYPE_UINT32:
139
              *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
140
              break;
141
 
142
            case FFI_TYPE_STRUCT:
143
              *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
144
              break;
145
 
146
            default:
147
              FFI_ASSERT(0);
148
            }
149
        }
150
      else
151
        {
152
          memcpy(argp, *p_argv, z);
153
        }
154
 
155
#ifdef X86_WIN32
156
    /* For thiscall/fastcall convention register-passed arguments
157
       are the first two none-floating-point arguments with a size
158
       smaller or equal to sizeof (void*).  */
159
    if ((cabi == FFI_THISCALL && stack_args_count < 1)
160
        || (cabi == FFI_FASTCALL && stack_args_count < 2))
161
      {
162
        if (z <= 4
163
            && ((*p_arg)->type != FFI_TYPE_FLOAT
164
                && (*p_arg)->type != FFI_TYPE_STRUCT))
165
          {
166
            p_stack_args[stack_args_count] = z;
167
            p_stack_data[stack_args_count] = argp;
168
            ++stack_args_count;
169
          }
170
      }
171
#endif
172
      p_argv++;
173
#ifdef X86_WIN64
174
      argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
175
#else
176
      argp += z;
177
#endif
178
    }
179
 
180
#ifdef X86_WIN32
181
  /* We need to move the register-passed arguments for thiscall/fastcall
182
     on top of stack, so that those can be moved to registers ecx/edx by
183
     call-handler.  */
184
  if (stack_args_count > 0)
185
    {
186
      size_t zz = (p_stack_args[0] + 3) & ~3;
187
      char *h;
188
 
189
      /* Move first argument to top-stack position.  */
190
      if (p_stack_data[0] != argp2)
191
        {
192
          h = alloca (zz + 1);
193
          memcpy (h, p_stack_data[0], zz);
194
          memmove (argp2 + zz, argp2,
195
                   (size_t) ((char *) p_stack_data[0] - (char*)argp2));
196
          memcpy (argp2, h, zz);
197
        }
198
 
199
      argp2 += zz;
200
      --stack_args_count;
201
      if (zz > 4)
202
        stack_args_count = 0;
203
 
204
      /* If we have a second argument, then move it on top
205
         after the first one.  */
206
      if (stack_args_count > 0 && p_stack_data[1] != argp2)
207
        {
208
          zz = p_stack_args[1];
209
          zz = (zz + 3) & ~3;
210
          h = alloca (zz + 1);
211
          h = alloca (zz + 1);
212
          memcpy (h, p_stack_data[1], zz);
213
          memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
214
          memcpy (argp2, h, zz);
215
        }
216
    }
217
#endif
218
  return;
219
}
220
 
221
/* Perform machine dependent cif processing */
222
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
223
{
224
  unsigned int i;
225
  ffi_type **ptr;
226
 
227
  /* Set the return type flag */
228
  switch (cif->rtype->type)
229
    {
230
    case FFI_TYPE_VOID:
231
#if defined(X86) || defined (X86_WIN32) || defined(X86_FREEBSD) || defined(X86_DARWIN) || defined(X86_WIN64)
232
    case FFI_TYPE_UINT8:
233
    case FFI_TYPE_UINT16:
234
    case FFI_TYPE_SINT8:
235
    case FFI_TYPE_SINT16:
236
#endif
237
#ifdef X86_WIN64
238
    case FFI_TYPE_UINT32:
239
    case FFI_TYPE_SINT32:
240
#endif
241
    case FFI_TYPE_SINT64:
242
    case FFI_TYPE_FLOAT:
243
    case FFI_TYPE_DOUBLE:
244
#ifndef X86_WIN64
245
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
246
    case FFI_TYPE_LONGDOUBLE:
247
#endif
248
#endif
249
      cif->flags = (unsigned) cif->rtype->type;
250
      break;
251
 
252
    case FFI_TYPE_UINT64:
253
#ifdef X86_WIN64
254
    case FFI_TYPE_POINTER:
255
#endif
256
      cif->flags = FFI_TYPE_SINT64;
257
      break;
258
 
259
    case FFI_TYPE_STRUCT:
260
#ifndef X86
261
      if (cif->rtype->size == 1)
262
        {
263
          cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
264
        }
265
      else if (cif->rtype->size == 2)
266
        {
267
          cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
268
        }
269
      else if (cif->rtype->size == 4)
270
        {
271
#ifdef X86_WIN64
272
          cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
273
#else
274
          cif->flags = FFI_TYPE_INT; /* same as int type */
275
#endif
276
        }
277
      else if (cif->rtype->size == 8)
278
        {
279
          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
280
        }
281
      else
282
#endif
283
        {
284
          cif->flags = FFI_TYPE_STRUCT;
285
          /* allocate space for return value pointer */
286
          cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
287
        }
288
      break;
289
 
290
    default:
291
#ifdef X86_WIN64
292
      cif->flags = FFI_TYPE_SINT64;
293
      break;
294
    case FFI_TYPE_INT:
295
      cif->flags = FFI_TYPE_SINT32;
296
#else
297
      cif->flags = FFI_TYPE_INT;
298
#endif
299
      break;
300
    }
301
 
302
  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
303
    {
304
      if (((*ptr)->alignment - 1) & cif->bytes)
305
        cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
306
      cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
307
    }
308
 
309
#ifdef X86_WIN64
310
  /* ensure space for storing four registers */
311
  cif->bytes += 4 * sizeof(ffi_arg);
312
#endif
313
 
314
#ifdef X86_DARWIN
315
  cif->bytes = (cif->bytes + 15) & ~0xF;
316
#endif
317
 
318
  return FFI_OK;
319
}
320
 
321
#ifdef X86_WIN64
322
extern int
323
ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
324
               unsigned, unsigned, unsigned *, void (*fn)(void));
325
#elif defined(X86_WIN32)
326
extern void
327
ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
328
               unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
329
#else
330
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
331
                          unsigned, unsigned, unsigned *, void (*fn)(void));
332
#endif
333
 
334
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
335
{
336
  extended_cif ecif;
337
 
338
  ecif.cif = cif;
339
  ecif.avalue = avalue;
340
 
341
  /* If the return value is a struct and we don't have a return */
342
  /* value address then we need to make one                     */
343
 
344
#ifdef X86_WIN64
345
  if (rvalue == NULL
346
      && cif->flags == FFI_TYPE_STRUCT
347
      && cif->rtype->size != 1 && cif->rtype->size != 2
348
      && cif->rtype->size != 4 && cif->rtype->size != 8)
349
    {
350
      ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
351
    }
352
#else
353
  if (rvalue == NULL
354
      && cif->flags == FFI_TYPE_STRUCT)
355
    {
356
      ecif.rvalue = alloca(cif->rtype->size);
357
    }
358
#endif
359
  else
360
    ecif.rvalue = rvalue;
361
 
362
 
363
  switch (cif->abi)
364
    {
365
#ifdef X86_WIN64
366
    case FFI_WIN64:
367
      {
368
        /* Make copies of all struct arguments
369
           NOTE: not sure if responsibility should be here or in caller */
370
        unsigned int i;
371
        for (i=0; i < cif->nargs;i++) {
372
          size_t size = cif->arg_types[i]->size;
373
          if ((cif->arg_types[i]->type == FFI_TYPE_STRUCT
374
               && (size != 1 && size != 2 && size != 4 && size != 8))
375
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
376
              || cif->arg_types[i]->type == FFI_TYPE_LONGDOUBLE
377
#endif
378
              )
379
            {
380
              void *local = alloca(size);
381
              memcpy(local, avalue[i], size);
382
              avalue[i] = local;
383
            }
384
        }
385
        ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
386
                       cif->flags, ecif.rvalue, fn);
387
      }
388
      break;
389
#elif defined(X86_WIN32)
390
    case FFI_SYSV:
391
    case FFI_STDCALL:
392
      ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
393
                     ecif.rvalue, fn);
394
      break;
395
    case FFI_THISCALL:
396
    case FFI_FASTCALL:
397
      {
398
        unsigned int abi = cif->abi;
399
        unsigned int i, passed_regs = 0;
400
 
401
        if (cif->flags == FFI_TYPE_STRUCT)
402
          ++passed_regs;
403
 
404
        for (i=0; i < cif->nargs && passed_regs < 2;i++)
405
          {
406
            size_t sz;
407
 
408
            if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
409
                || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
410
              continue;
411
            sz = (cif->arg_types[i]->size + 3) & ~3;
412
            if (sz == 0 || sz > 4)
413
              continue;
414
            ++passed_regs;
415
          }
416
        if (passed_regs < 2 && abi == FFI_FASTCALL)
417
          abi = FFI_THISCALL;
418
        if (passed_regs < 1 && abi == FFI_THISCALL)
419
          abi = FFI_STDCALL;
420
        ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
421
                       ecif.rvalue, fn);
422
      }
423
      break;
424
#else
425
    case FFI_SYSV:
426
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
427
                    fn);
428
      break;
429
#endif
430
    default:
431
      FFI_ASSERT(0);
432
      break;
433
    }
434
}
435
 
436
 
437
/** private members **/
438
 
439
/* The following __attribute__((regparm(1))) decorations will have no effect
440
   on MSVC - standard cdecl convention applies. */
441
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
442
                                         void** args, ffi_cif* cif);
443
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
444
     __attribute__ ((regparm(1)));
445
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
446
     __attribute__ ((regparm(1)));
447
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
448
     __attribute__ ((regparm(1)));
449
#ifdef X86_WIN32
450
void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
451
     __attribute__ ((regparm(1)));
452
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
453
     __attribute__ ((regparm(1)));
454
void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
455
     __attribute__ ((regparm(1)));
456
#endif
457
#ifdef X86_WIN64
458
void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
459
#endif
460
 
461
/* This function is jumped to by the trampoline */
462
 
463
#ifdef X86_WIN64
464
void * FFI_HIDDEN
465
ffi_closure_win64_inner (ffi_closure *closure, void *args) {
466
  ffi_cif       *cif;
467
  void         **arg_area;
468
  void          *result;
469
  void          *resp = &result;
470
 
471
  cif         = closure->cif;
472
  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));
473
 
474
  /* this call will initialize ARG_AREA, such that each
475
   * element in that array points to the corresponding
476
   * value on the stack; and if the function returns
477
   * a structure, it will change RESP to point to the
478
   * structure return address.  */
479
 
480
  ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
481
 
482
  (closure->fun) (cif, resp, arg_area, closure->user_data);
483
 
484
  /* The result is returned in rax.  This does the right thing for
485
     result types except for floats; we have to 'mov xmm0, rax' in the
486
     caller to correct this.
487
     TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
488
  */
489
  return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
490
}
491
 
492
#else
493
unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
494
ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
495
{
496
  /* our various things...  */
497
  ffi_cif       *cif;
498
  void         **arg_area;
499
 
500
  cif         = closure->cif;
501
  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));
502
 
503
  /* this call will initialize ARG_AREA, such that each
504
   * element in that array points to the corresponding
505
   * value on the stack; and if the function returns
506
   * a structure, it will change RESP to point to the
507
   * structure return address.  */
508
 
509
  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
510
 
511
  (closure->fun) (cif, *respp, arg_area, closure->user_data);
512
 
513
  return cif->flags;
514
}
515
#endif /* !X86_WIN64 */
516
 
517
static void
518
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
519
                            ffi_cif *cif)
520
{
521
  register unsigned int i;
522
  register void **p_argv;
523
  register char *argp;
524
  register ffi_type **p_arg;
525
 
526
  argp = stack;
527
 
528
#ifdef X86_WIN64
529
  if (cif->rtype->size > sizeof(ffi_arg)
530
      || (cif->flags == FFI_TYPE_STRUCT
531
          && (cif->rtype->size != 1 && cif->rtype->size != 2
532
              && cif->rtype->size != 4 && cif->rtype->size != 8))) {
533
    *rvalue = *(void **) argp;
534
    argp += sizeof(void *);
535
  }
536
#else
537
  if ( cif->flags == FFI_TYPE_STRUCT ) {
538
    *rvalue = *(void **) argp;
539
    argp += sizeof(void *);
540
  }
541
#endif
542
 
543
  p_argv = avalue;
544
 
545
  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
546
    {
547
      size_t z;
548
 
549
      /* Align if necessary */
550
      if ((sizeof(void*) - 1) & (size_t) argp) {
551
        argp = (char *) ALIGN(argp, sizeof(void*));
552
      }
553
 
554
#ifdef X86_WIN64
555
      if ((*p_arg)->size > sizeof(ffi_arg)
556
          || ((*p_arg)->type == FFI_TYPE_STRUCT
557
              && ((*p_arg)->size != 1 && (*p_arg)->size != 2
558
                  && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
559
        {
560
          z = sizeof(void *);
561
          *p_argv = *(void **)argp;
562
        }
563
      else
564
#endif
565
        {
566
          z = (*p_arg)->size;
567
 
568
          /* because we're little endian, this is what it turns into.   */
569
 
570
          *p_argv = (void*) argp;
571
        }
572
 
573
      p_argv++;
574
#ifdef X86_WIN64
575
      argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
576
#else
577
      argp += z;
578
#endif
579
    }
580
 
581
  return;
582
}
583
 
584
#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
585
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
586
   void*  __fun = (void*)(FUN); \
587
   void*  __ctx = (void*)(CTX); \
588
   *(unsigned char*) &__tramp[0] = 0x41; \
589
   *(unsigned char*) &__tramp[1] = 0xbb; \
590
   *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
591
   *(unsigned char*) &__tramp[6] = 0x48; \
592
   *(unsigned char*) &__tramp[7] = 0xb8; \
593
   *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
594
   *(unsigned char *)  &__tramp[16] = 0x49; \
595
   *(unsigned char *)  &__tramp[17] = 0xba; \
596
   *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
597
   *(unsigned char *)  &__tramp[26] = 0x41; \
598
   *(unsigned char *)  &__tramp[27] = 0xff; \
599
   *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
600
 }
601
 
602
/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
603
 
604
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
605
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
606
   unsigned int  __fun = (unsigned int)(FUN); \
607
   unsigned int  __ctx = (unsigned int)(CTX); \
608
   unsigned int  __dis = __fun - (__ctx + 10);  \
609
   *(unsigned char*) &__tramp[0] = 0xb8; \
610
   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
611
   *(unsigned char *)  &__tramp[5] = 0xe9; \
612
   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
613
 }
614
 
615
#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
616
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
617
   unsigned int  __fun = (unsigned int)(FUN); \
618
   unsigned int  __ctx = (unsigned int)(CTX); \
619
   unsigned int  __dis = __fun - (__ctx + 49);  \
620
   unsigned short __size = (unsigned short)(SIZE); \
621
   *(unsigned int *) &__tramp[0] = 0x8324048b;   /* mov (%esp), %eax */ \
622
   *(unsigned int *) &__tramp[4] = 0x4c890cec;  /* sub $12, %esp */ \
623
   *(unsigned int *) &__tramp[8] = 0x04890424;  /* mov %ecx, 4(%esp) */ \
624
   *(unsigned char*) &__tramp[12] = 0x24;       /* mov %eax, (%esp) */ \
625
   *(unsigned char*) &__tramp[13] = 0xb8; \
626
   *(unsigned int *) &__tramp[14] = __size;     /* mov __size, %eax */ \
627
   *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
628
   *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
629
   *(unsigned short*) &__tramp[26] = 0x0b74;    /* jz 1f */ \
630
   *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
631
   *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
632
   *(unsigned char*) &__tramp[36] = 0x48;       /* dec %eax */ \
633
   *(unsigned short*) &__tramp[37] = 0xf575;    /* jnz 2b ; 1f: */ \
634
   *(unsigned char*) &__tramp[39] = 0xb8; \
635
   *(unsigned int*)  &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
636
   *(unsigned char *)  &__tramp[44] = 0xe8; \
637
   *(unsigned int*)  &__tramp[45] = __dis; /* call __fun  */ \
638
   *(unsigned char*)  &__tramp[49] = 0xc2; /* ret  */ \
639
   *(unsigned short*)  &__tramp[50] = (__size + 8); /* ret (__size + 8)  */ \
640
 }
641
 
642
#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
643
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
644
   unsigned int  __fun = (unsigned int)(FUN); \
645
   unsigned int  __ctx = (unsigned int)(CTX); \
646
   unsigned int  __dis = __fun - (__ctx + 10); \
647
   unsigned short __size = (unsigned short)(SIZE); \
648
   *(unsigned char*) &__tramp[0] = 0xb8; \
649
   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
650
   *(unsigned char *)  &__tramp[5] = 0xe8; \
651
   *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
652
   *(unsigned char *)  &__tramp[10] = 0xc2; \
653
   *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
654
 }
655
 
656
/* the cif must already be prep'ed */
657
 
658
ffi_status
659
ffi_prep_closure_loc (ffi_closure* closure,
660
                      ffi_cif* cif,
661
                      void (*fun)(ffi_cif*,void*,void**,void*),
662
                      void *user_data,
663
                      void *codeloc)
664
{
665
#ifdef X86_WIN64
666
#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
667
#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
668
  if (cif->abi == FFI_WIN64)
669
    {
670
      int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
671
      FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
672
                                 &ffi_closure_win64,
673
                                 codeloc, mask);
674
      /* make sure we can execute here */
675
    }
676
#else
677
  if (cif->abi == FFI_SYSV)
678
    {
679
      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
680
                           &ffi_closure_SYSV,
681
                           (void*)codeloc);
682
    }
683
#ifdef X86_WIN32
684
  else if (cif->abi == FFI_THISCALL)
685
    {
686
      FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
687
                                    &ffi_closure_THISCALL,
688
                                    (void*)codeloc,
689
                                    cif->bytes);
690
    }
691
  else if (cif->abi == FFI_STDCALL)
692
    {
693
      FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
694
                                   &ffi_closure_STDCALL,
695
                                   (void*)codeloc, cif->bytes);
696
    }
697
#endif /* X86_WIN32 */
698
#endif /* !X86_WIN64 */
699
  else
700
    {
701
      return FFI_BAD_ABI;
702
    }
703
 
704
  closure->cif  = cif;
705
  closure->user_data = user_data;
706
  closure->fun  = fun;
707
 
708
  return FFI_OK;
709
}
710
 
711
/* ------- Native raw API support -------------------------------- */
712
 
713
#if !FFI_NO_RAW_API
714
 
715
ffi_status
716
ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
717
                          ffi_cif* cif,
718
                          void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
719
                          void *user_data,
720
                          void *codeloc)
721
{
722
  int i;
723
 
724
  if (cif->abi != FFI_SYSV) {
725
#ifdef X86_WIN32
726
    if (cif->abi != FFI_THISCALL)
727
#endif
728
    return FFI_BAD_ABI;
729
  }
730
 
731
  /* we currently don't support certain kinds of arguments for raw
732
     closures.  This should be implemented by a separate assembly
733
     language routine, since it would require argument processing,
734
     something we don't do now for performance.  */
735
 
736
  for (i = cif->nargs-1; i >= 0; i--)
737
    {
738
      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
739
      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
740
    }
741
 
742
#ifdef X86_WIN32
743
  if (cif->abi == FFI_SYSV)
744
    {
745
#endif
746
  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
747
                       codeloc);
748
#ifdef X86_WIN32
749
    }
750
  else if (cif->abi == FFI_THISCALL)
751
    {
752
      FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
753
                                    codeloc, cif->bytes);
754
    }
755
#endif
756
  closure->cif  = cif;
757
  closure->user_data = user_data;
758
  closure->fun  = fun;
759
 
760
  return FFI_OK;
761
}
762
 
763
static void
764
ffi_prep_args_raw(char *stack, extended_cif *ecif)
765
{
766
  memcpy (stack, ecif->avalue, ecif->cif->bytes);
767
}
768
 
769
/* we borrow this routine from libffi (it must be changed, though, to
770
 * actually call the function passed in the first argument.  as of
771
 * libffi-1.20, this is not the case.)
772
 */
773
 
774
void
775
ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
776
{
777
  extended_cif ecif;
778
  void **avalue = (void **)fake_avalue;
779
 
780
  ecif.cif = cif;
781
  ecif.avalue = avalue;
782
 
783
  /* If the return value is a struct and we don't have a return */
784
  /* value address then we need to make one                     */
785
 
786
  if ((rvalue == NULL) &&
787
      (cif->rtype->type == FFI_TYPE_STRUCT))
788
    {
789
      ecif.rvalue = alloca(cif->rtype->size);
790
    }
791
  else
792
    ecif.rvalue = rvalue;
793
 
794
 
795
  switch (cif->abi)
796
    {
797
#ifdef X86_WIN32
798
    case FFI_SYSV:
799
    case FFI_STDCALL:
800
      ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
801
                     ecif.rvalue, fn);
802
      break;
803
    case FFI_THISCALL:
804
    case FFI_FASTCALL:
805
      {
806
        unsigned int abi = cif->abi;
807
        unsigned int i, passed_regs = 0;
808
 
809
        if (cif->flags == FFI_TYPE_STRUCT)
810
          ++passed_regs;
811
 
812
        for (i=0; i < cif->nargs && passed_regs < 2;i++)
813
          {
814
            size_t sz;
815
 
816
            if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
817
                || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
818
              continue;
819
            sz = (cif->arg_types[i]->size + 3) & ~3;
820
            if (sz == 0 || sz > 4)
821
              continue;
822
            ++passed_regs;
823
          }
824
        if (passed_regs < 2 && abi == FFI_FASTCALL)
825
          cif->abi = abi = FFI_THISCALL;
826
        if (passed_regs < 1 && abi == FFI_THISCALL)
827
          cif->abi = abi = FFI_STDCALL;
828
        ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
829
                       ecif.rvalue, fn);
830
      }
831
      break;
832
#else
833
    case FFI_SYSV:
834
      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
835
                    ecif.rvalue, fn);
836
      break;
837
#endif
838
    default:
839
      FFI_ASSERT(0);
840
      break;
841
    }
842
}
843
 
844
#endif
845
 
846
#endif /* !__x86_64__  || X86_WIN64 */
847
 

powered by: WebSVN 2.1.0

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