github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/x86/ffi.c (about)

     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  #ifndef __x86_64__
    32  #include <ffi.h>
    33  #include <ffi_common.h>
    34  #include <stdlib.h>
    35  #include "internal.h"
    36  
    37  /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
    38     all further uses in this file will refer to the 80-bit type.  */
    39  #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    40  # if FFI_TYPE_LONGDOUBLE != 4
    41  #  error FFI_TYPE_LONGDOUBLE out of date
    42  # endif
    43  #else
    44  # undef FFI_TYPE_LONGDOUBLE
    45  # define FFI_TYPE_LONGDOUBLE 4
    46  #endif
    47  
    48  #if defined(__GNUC__) && !defined(__declspec)
    49  # define __declspec(x)  __attribute__((x))
    50  #endif
    51  
    52  /* Perform machine dependent cif processing.  */
    53  ffi_status FFI_HIDDEN
    54  ffi_prep_cif_machdep(ffi_cif *cif)
    55  {
    56    size_t bytes = 0;
    57    int i, n, flags, cabi = cif->abi;
    58  
    59    switch (cabi)
    60      {
    61      case FFI_SYSV:
    62      case FFI_STDCALL:
    63      case FFI_THISCALL:
    64      case FFI_FASTCALL:
    65      case FFI_MS_CDECL:
    66      case FFI_PASCAL:
    67      case FFI_REGISTER:
    68        break;
    69      default:
    70        return FFI_BAD_ABI;
    71      }
    72  
    73    switch (cif->rtype->type)
    74      {
    75      case FFI_TYPE_VOID:
    76        flags = X86_RET_VOID;
    77        break;
    78      case FFI_TYPE_FLOAT:
    79        flags = X86_RET_FLOAT;
    80        break;
    81      case FFI_TYPE_DOUBLE:
    82        flags = X86_RET_DOUBLE;
    83        break;
    84      case FFI_TYPE_LONGDOUBLE:
    85        flags = X86_RET_LDOUBLE;
    86        break;
    87      case FFI_TYPE_UINT8:
    88        flags = X86_RET_UINT8;
    89        break;
    90      case FFI_TYPE_UINT16:
    91        flags = X86_RET_UINT16;
    92        break;
    93      case FFI_TYPE_SINT8:
    94        flags = X86_RET_SINT8;
    95        break;
    96      case FFI_TYPE_SINT16:
    97        flags = X86_RET_SINT16;
    98        break;
    99      case FFI_TYPE_INT:
   100      case FFI_TYPE_SINT32:
   101      case FFI_TYPE_UINT32:
   102      case FFI_TYPE_POINTER:
   103        flags = X86_RET_INT32;
   104        break;
   105      case FFI_TYPE_SINT64:
   106      case FFI_TYPE_UINT64:
   107        flags = X86_RET_INT64;
   108        break;
   109      case FFI_TYPE_STRUCT:
   110  #ifndef X86
   111        /* ??? This should be a different ABI rather than an ifdef.  */
   112        if (cif->rtype->size == 1)
   113  	flags = X86_RET_STRUCT_1B;
   114        else if (cif->rtype->size == 2)
   115  	flags = X86_RET_STRUCT_2B;
   116        else if (cif->rtype->size == 4)
   117  	flags = X86_RET_INT32;
   118        else if (cif->rtype->size == 8)
   119  	flags = X86_RET_INT64;
   120        else
   121  #endif
   122  	{
   123  	do_struct:
   124  	  switch (cabi)
   125  	    {
   126  	    case FFI_THISCALL:
   127  	    case FFI_FASTCALL:
   128  	    case FFI_STDCALL:
   129  	    case FFI_MS_CDECL:
   130  	      flags = X86_RET_STRUCTARG;
   131  	      break;
   132  	    default:
   133  	      flags = X86_RET_STRUCTPOP;
   134  	      break;
   135  	    }
   136  	  /* Allocate space for return value pointer.  */
   137  	  bytes += ALIGN (sizeof(void*), FFI_SIZEOF_ARG);
   138  	}
   139        break;
   140      case FFI_TYPE_COMPLEX:
   141        switch (cif->rtype->elements[0]->type)
   142  	{
   143  	case FFI_TYPE_DOUBLE:
   144  	case FFI_TYPE_LONGDOUBLE:
   145  	case FFI_TYPE_SINT64:
   146  	case FFI_TYPE_UINT64:
   147  	  goto do_struct;
   148  	case FFI_TYPE_FLOAT:
   149  	case FFI_TYPE_INT:
   150  	case FFI_TYPE_SINT32:
   151  	case FFI_TYPE_UINT32:
   152  	  flags = X86_RET_INT64;
   153  	  break;
   154  	case FFI_TYPE_SINT16:
   155  	case FFI_TYPE_UINT16:
   156  	  flags = X86_RET_INT32;
   157  	  break;
   158  	case FFI_TYPE_SINT8:
   159  	case FFI_TYPE_UINT8:
   160  	  flags = X86_RET_STRUCT_2B;
   161  	  break;
   162  	default:
   163  	  return FFI_BAD_TYPEDEF;
   164  	}
   165        break;
   166      default:
   167        return FFI_BAD_TYPEDEF;
   168      }
   169    cif->flags = flags;
   170  
   171    for (i = 0, n = cif->nargs; i < n; i++)
   172      {
   173        ffi_type *t = cif->arg_types[i];
   174  
   175        bytes = ALIGN (bytes, t->alignment);
   176        bytes += ALIGN (t->size, FFI_SIZEOF_ARG);
   177      }
   178    cif->bytes = ALIGN (bytes, 16);
   179  
   180    return FFI_OK;
   181  }
   182  
   183  static ffi_arg
   184  extend_basic_type(void *arg, int type)
   185  {
   186    switch (type)
   187      {
   188      case FFI_TYPE_SINT8:
   189        return *(SINT8 *)arg;
   190      case FFI_TYPE_UINT8:
   191        return *(UINT8 *)arg;
   192      case FFI_TYPE_SINT16:
   193        return *(SINT16 *)arg;
   194      case FFI_TYPE_UINT16:
   195        return *(UINT16 *)arg;
   196  
   197      case FFI_TYPE_SINT32:
   198      case FFI_TYPE_UINT32:
   199      case FFI_TYPE_POINTER:
   200      case FFI_TYPE_FLOAT:
   201        return *(UINT32 *)arg;
   202  
   203      default:
   204        abort();
   205      }
   206  }
   207  
   208  struct call_frame
   209  {
   210    void *ebp;		/* 0 */
   211    void *retaddr;	/* 4 */
   212    void (*fn)(void);	/* 8 */
   213    int flags;		/* 12 */
   214    void *rvalue;		/* 16 */
   215    unsigned regs[3];	/* 20-28 */
   216  };
   217  
   218  struct abi_params
   219  {
   220    int dir;		/* parameter growth direction */
   221    int static_chain;	/* the static chain register used by gcc */
   222    int nregs;		/* number of register parameters */
   223    int regs[3];
   224  };
   225  
   226  static const struct abi_params abi_params[FFI_LAST_ABI] = {
   227    [FFI_SYSV] = { 1, R_ECX, 0 },
   228    [FFI_THISCALL] = { 1, R_EAX, 1, { R_ECX } },
   229    [FFI_FASTCALL] = { 1, R_EAX, 2, { R_ECX, R_EDX } },
   230    [FFI_STDCALL] = { 1, R_ECX, 0 },
   231    [FFI_PASCAL] = { -1, R_ECX, 0 },
   232    /* ??? No defined static chain; gcc does not support REGISTER.  */
   233    [FFI_REGISTER] = { -1, R_ECX, 3, { R_EAX, R_EDX, R_ECX } },
   234    [FFI_MS_CDECL] = { 1, R_ECX, 0 }
   235  };
   236  
   237  extern void ffi_call_i386(struct call_frame *, char *)
   238  #if HAVE_FASTCALL
   239  	__declspec(fastcall)
   240  #endif
   241  	FFI_HIDDEN;
   242  
   243  static void
   244  ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
   245  	      void **avalue, void *closure)
   246  {
   247    size_t rsize, bytes;
   248    struct call_frame *frame;
   249    char *stack, *argp;
   250    ffi_type **arg_types;
   251    int flags, cabi, i, n, dir, narg_reg;
   252    const struct abi_params *pabi;
   253  
   254    flags = cif->flags;
   255    cabi = cif->abi;
   256    pabi = &abi_params[cabi];
   257    dir = pabi->dir;
   258  
   259    rsize = 0;
   260    if (rvalue == NULL)
   261      {
   262        switch (flags)
   263  	{
   264  	case X86_RET_FLOAT:
   265  	case X86_RET_DOUBLE:
   266  	case X86_RET_LDOUBLE:
   267  	case X86_RET_STRUCTPOP:
   268  	case X86_RET_STRUCTARG:
   269  	  /* The float cases need to pop the 387 stack.
   270  	     The struct cases need to pass a valid pointer to the callee.  */
   271  	  rsize = cif->rtype->size;
   272  	  break;
   273  	default:
   274  	  /* We can pretend that the callee returns nothing.  */
   275  	  flags = X86_RET_VOID;
   276  	  break;
   277  	}
   278      }
   279  
   280    bytes = cif->bytes;
   281    stack = alloca(bytes + sizeof(*frame) + rsize);
   282    argp = (dir < 0 ? stack + bytes : stack);
   283    frame = (struct call_frame *)(stack + bytes);
   284    if (rsize)
   285      rvalue = frame + 1;
   286  
   287    frame->fn = fn;
   288    frame->flags = flags;
   289    frame->rvalue = rvalue;
   290    frame->regs[pabi->static_chain] = (unsigned)closure;
   291  
   292    narg_reg = 0;
   293    switch (flags)
   294      {
   295      case X86_RET_STRUCTARG:
   296        /* The pointer is passed as the first argument.  */
   297        if (pabi->nregs > 0)
   298  	{
   299  	  frame->regs[pabi->regs[0]] = (unsigned)rvalue;
   300  	  narg_reg = 1;
   301  	  break;
   302  	}
   303        /* fallthru */
   304      case X86_RET_STRUCTPOP:
   305        *(void **)argp = rvalue;
   306        argp += sizeof(void *);
   307        break;
   308      }
   309  
   310    arg_types = cif->arg_types;
   311    for (i = 0, n = cif->nargs; i < n; i++)
   312      {
   313        ffi_type *ty = arg_types[i];
   314        void *valp = avalue[i];
   315        size_t z = ty->size;
   316        int t = ty->type;
   317  
   318        if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
   319          {
   320  	  ffi_arg val = extend_basic_type (valp, t);
   321  
   322  	  if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
   323  	    frame->regs[pabi->regs[narg_reg++]] = val;
   324  	  else if (dir < 0)
   325  	    {
   326  	      argp -= 4;
   327  	      *(ffi_arg *)argp = val;
   328  	    }
   329  	  else
   330  	    {
   331  	      *(ffi_arg *)argp = val;
   332  	      argp += 4;
   333  	    }
   334  	}
   335        else
   336  	{
   337  	  size_t za = ALIGN (z, FFI_SIZEOF_ARG);
   338  	  size_t align = FFI_SIZEOF_ARG;
   339  
   340  	  /* Alignment rules for arguments are quite complex.  Vectors and
   341  	     structures with 16 byte alignment get it.  Note that long double
   342  	     on Darwin does have 16 byte alignment, and does not get this
   343  	     alignment if passed directly; a structure with a long double
   344  	     inside, however, would get 16 byte alignment.  Since libffi does
   345  	     not support vectors, we need non concern ourselves with other
   346  	     cases.  */
   347  	  if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
   348  	    align = 16;
   349  	    
   350  	  if (dir < 0)
   351  	    {
   352  	      /* ??? These reverse argument ABIs are probably too old
   353  		 to have cared about alignment.  Someone should check.  */
   354  	      argp -= za;
   355  	      memcpy (argp, valp, z);
   356  	    }
   357  	  else
   358  	    {
   359  	      argp = (char *)ALIGN (argp, align);
   360  	      memcpy (argp, valp, z);
   361  	      argp += za;
   362  	    }
   363  	}
   364      }
   365    FFI_ASSERT (dir > 0 || argp == stack);
   366  
   367    ffi_call_i386 (frame, stack);
   368  }
   369  
   370  void
   371  ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
   372  {
   373    ffi_call_int (cif, fn, rvalue, avalue, NULL);
   374  }
   375  
   376  void
   377  ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
   378  	     void **avalue, void *closure)
   379  {
   380    ffi_call_int (cif, fn, rvalue, avalue, closure);
   381  }
   382  
   383  /** private members **/
   384  
   385  void FFI_HIDDEN ffi_closure_i386(void);
   386  void FFI_HIDDEN ffi_closure_STDCALL(void);
   387  void FFI_HIDDEN ffi_closure_REGISTER(void);
   388  
   389  struct closure_frame
   390  {
   391    unsigned rettemp[4];				/* 0 */
   392    unsigned regs[3];				/* 16-24 */
   393    ffi_cif *cif;					/* 28 */
   394    void (*fun)(ffi_cif*,void*,void**,void*);	/* 32 */
   395    void *user_data;				/* 36 */
   396  };
   397  
   398  int FFI_HIDDEN
   399  #if HAVE_FASTCALL
   400  __declspec(fastcall)
   401  #endif
   402  ffi_closure_inner (struct closure_frame *frame, char *stack)
   403  {
   404    ffi_cif *cif = frame->cif;
   405    int cabi, i, n, flags, dir, narg_reg;
   406    const struct abi_params *pabi;
   407    ffi_type **arg_types;
   408    char *argp;
   409    void *rvalue;
   410    void **avalue;
   411  
   412    cabi = cif->abi;
   413    flags = cif->flags;
   414    narg_reg = 0;
   415    rvalue = frame->rettemp;
   416    pabi = &abi_params[cabi];
   417    dir = pabi->dir;
   418    argp = (dir < 0 ? stack + cif->bytes : stack);
   419  
   420    switch (flags)
   421      {
   422      case X86_RET_STRUCTARG:
   423        if (pabi->nregs > 0)
   424  	{
   425  	  rvalue = (void *)frame->regs[pabi->regs[0]];
   426  	  narg_reg = 1;
   427  	  frame->rettemp[0] = (unsigned)rvalue;
   428  	  break;
   429  	}
   430        /* fallthru */
   431      case X86_RET_STRUCTPOP:
   432        rvalue = *(void **)argp;
   433        argp += sizeof(void *);
   434        frame->rettemp[0] = (unsigned)rvalue;
   435        break;
   436      }
   437  
   438    n = cif->nargs;
   439    avalue = alloca(sizeof(void *) * n);
   440  
   441    arg_types = cif->arg_types;
   442    for (i = 0; i < n; ++i)
   443      {
   444        ffi_type *ty = arg_types[i];
   445        size_t z = ty->size;
   446        int t = ty->type;
   447        void *valp;
   448  
   449        if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
   450  	{
   451  	  if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
   452  	    valp = &frame->regs[pabi->regs[narg_reg++]];
   453  	  else if (dir < 0)
   454  	    {
   455  	      argp -= 4;
   456  	      valp = argp;
   457  	    }
   458  	  else
   459  	    {
   460  	      valp = argp;
   461  	      argp += 4;
   462  	    }
   463  	}
   464        else
   465  	{
   466  	  size_t za = ALIGN (z, FFI_SIZEOF_ARG);
   467  	  size_t align = FFI_SIZEOF_ARG;
   468  
   469  	  /* See the comment in ffi_call_int.  */
   470  	  if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
   471  	    align = 16;
   472  
   473  	  if (dir < 0)
   474  	    {
   475  	      /* ??? These reverse argument ABIs are probably too old
   476  		 to have cared about alignment.  Someone should check.  */
   477  	      argp -= za;
   478  	      valp = argp;
   479  	    }
   480  	  else
   481  	    {
   482  	      argp = (char *)ALIGN (argp, align);
   483  	      valp = argp;
   484  	      argp += za;
   485  	    }
   486  	}
   487  
   488        avalue[i] = valp;
   489      }
   490  
   491    frame->fun (cif, rvalue, avalue, frame->user_data);
   492  
   493    if (cabi == FFI_STDCALL)
   494      return flags + (cif->bytes << X86_RET_POP_SHIFT);
   495    else
   496      return flags;
   497  }
   498  
   499  ffi_status
   500  ffi_prep_closure_loc (ffi_closure* closure,
   501                        ffi_cif* cif,
   502                        void (*fun)(ffi_cif*,void*,void**,void*),
   503                        void *user_data,
   504                        void *codeloc)
   505  {
   506    char *tramp = closure->tramp;
   507    void (*dest)(void);
   508    int op = 0xb8;  /* movl imm, %eax */
   509  
   510    switch (cif->abi)
   511      {
   512      case FFI_SYSV:
   513      case FFI_THISCALL:
   514      case FFI_FASTCALL:
   515      case FFI_MS_CDECL:
   516        dest = ffi_closure_i386;
   517        break;
   518      case FFI_STDCALL:
   519      case FFI_PASCAL:
   520        dest = ffi_closure_STDCALL;
   521        break;
   522      case FFI_REGISTER:
   523        dest = ffi_closure_REGISTER;
   524        op = 0x68;  /* pushl imm */
   525      default:
   526        return FFI_BAD_ABI;
   527      }
   528  
   529    /* movl or pushl immediate.  */
   530    tramp[0] = op;
   531    *(void **)(tramp + 1) = codeloc;
   532  
   533    /* jmp dest */
   534    tramp[5] = 0xe9;
   535    *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
   536  
   537    closure->cif = cif;
   538    closure->fun = fun;
   539    closure->user_data = user_data;
   540  
   541    return FFI_OK;
   542  }
   543  
   544  void FFI_HIDDEN ffi_go_closure_EAX(void);
   545  void FFI_HIDDEN ffi_go_closure_ECX(void);
   546  void FFI_HIDDEN ffi_go_closure_STDCALL(void);
   547  
   548  ffi_status
   549  ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
   550  		     void (*fun)(ffi_cif*,void*,void**,void*))
   551  {
   552    void (*dest)(void);
   553  
   554    switch (cif->abi)
   555      {
   556      case FFI_SYSV:
   557      case FFI_MS_CDECL:
   558        dest = ffi_go_closure_ECX;
   559        break;
   560      case FFI_THISCALL:
   561      case FFI_FASTCALL:
   562        dest = ffi_go_closure_EAX;
   563        break;
   564      case FFI_STDCALL:
   565      case FFI_PASCAL:
   566        dest = ffi_go_closure_STDCALL;
   567        break;
   568      case FFI_REGISTER:
   569      default:
   570        return FFI_BAD_ABI;
   571      }
   572  
   573    closure->tramp = dest;
   574    closure->cif = cif;
   575    closure->fun = fun;
   576  
   577    return FFI_OK;
   578  }
   579  
   580  /* ------- Native raw API support -------------------------------- */
   581  
   582  #if !FFI_NO_RAW_API
   583  
   584  void FFI_HIDDEN ffi_closure_raw_SYSV(void);
   585  void FFI_HIDDEN ffi_closure_raw_THISCALL(void);
   586  
   587  ffi_status
   588  ffi_prep_raw_closure_loc (ffi_raw_closure *closure,
   589                            ffi_cif *cif,
   590                            void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
   591                            void *user_data,
   592                            void *codeloc)
   593  {
   594    char *tramp = closure->tramp;
   595    void (*dest)(void);
   596    int i;
   597  
   598    /* We currently don't support certain kinds of arguments for raw
   599       closures.  This should be implemented by a separate assembly
   600       language routine, since it would require argument processing,
   601       something we don't do now for performance.  */
   602    for (i = cif->nargs-1; i >= 0; i--)
   603      switch (cif->arg_types[i]->type)
   604        {
   605        case FFI_TYPE_STRUCT:
   606        case FFI_TYPE_LONGDOUBLE:
   607  	return FFI_BAD_TYPEDEF;
   608        }
   609  
   610    switch (cif->abi)
   611      {
   612      case FFI_THISCALL:
   613        dest = ffi_closure_raw_THISCALL;
   614        break;
   615      case FFI_SYSV:
   616        dest = ffi_closure_raw_SYSV;
   617        break;
   618      default:
   619        return FFI_BAD_ABI;
   620      }
   621  
   622    /* movl imm, %eax.  */
   623    tramp[0] = 0xb8;
   624    *(void **)(tramp + 1) = codeloc;
   625  
   626    /* jmp dest */
   627    tramp[5] = 0xe9;
   628    *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
   629  
   630    closure->cif = cif;
   631    closure->fun = fun;
   632    closure->user_data = user_data;
   633  
   634    return FFI_OK;
   635  }
   636  
   637  void
   638  ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue)
   639  {
   640    size_t rsize, bytes;
   641    struct call_frame *frame;
   642    char *stack, *argp;
   643    ffi_type **arg_types;
   644    int flags, cabi, i, n, narg_reg;
   645    const struct abi_params *pabi;
   646  
   647    flags = cif->flags;
   648    cabi = cif->abi;
   649    pabi = &abi_params[cabi];
   650  
   651    rsize = 0;
   652    if (rvalue == NULL)
   653      {
   654        switch (flags)
   655  	{
   656  	case X86_RET_FLOAT:
   657  	case X86_RET_DOUBLE:
   658  	case X86_RET_LDOUBLE:
   659  	case X86_RET_STRUCTPOP:
   660  	case X86_RET_STRUCTARG:
   661  	  /* The float cases need to pop the 387 stack.
   662  	     The struct cases need to pass a valid pointer to the callee.  */
   663  	  rsize = cif->rtype->size;
   664  	  break;
   665  	default:
   666  	  /* We can pretend that the callee returns nothing.  */
   667  	  flags = X86_RET_VOID;
   668  	  break;
   669  	}
   670      }
   671  
   672    bytes = cif->bytes;
   673    argp = stack = alloca(bytes + sizeof(*frame) + rsize);
   674    frame = (struct call_frame *)(stack + bytes);
   675    if (rsize)
   676      rvalue = frame + 1;
   677  
   678    narg_reg = 0;
   679    switch (flags)
   680      {
   681      case X86_RET_STRUCTARG:
   682        /* The pointer is passed as the first argument.  */
   683        if (pabi->nregs > 0)
   684  	{
   685  	  frame->regs[pabi->regs[0]] = (unsigned)rvalue;
   686  	  narg_reg = 1;
   687  	  break;
   688  	}
   689        /* fallthru */
   690      case X86_RET_STRUCTPOP:
   691        *(void **)argp = rvalue;
   692        argp += sizeof(void *);
   693        bytes -= sizeof(void *);
   694        break;
   695      }
   696  
   697    arg_types = cif->arg_types;
   698    for (i = 0, n = cif->nargs; narg_reg < pabi->nregs && i < n; i++)
   699      {
   700        ffi_type *ty = arg_types[i];
   701        size_t z = ty->size;
   702        int t = ty->type;
   703  
   704        if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT && t != FFI_TYPE_FLOAT)
   705  	{
   706  	  ffi_arg val = extend_basic_type (avalue, t);
   707  	  frame->regs[pabi->regs[narg_reg++]] = val;
   708  	  z = FFI_SIZEOF_ARG;
   709  	}
   710        else
   711  	{
   712  	  memcpy (argp, avalue, z);
   713  	  z = ALIGN (z, FFI_SIZEOF_ARG);
   714  	  argp += z;
   715  	}
   716        avalue += z;
   717        bytes -= z;
   718      }
   719    if (i < n)
   720      memcpy (argp, avalue, bytes);
   721  
   722    ffi_call_i386 (frame, stack);
   723  }
   724  #endif /* !FFI_NO_RAW_API */
   725  #endif /* !__x86_64__ */