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