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

     1  /* -----------------------------------------------------------------------
     2     ffi.c - Copyright (c) 2000, 2007 Software AG
     3             Copyright (c) 2008 Red Hat, Inc
     4  
     5     S390 Foreign Function Interface
     6  
     7     Permission is hereby granted, free of charge, to any person obtaining
     8     a copy of this software and associated documentation files (the
     9     ``Software''), to deal in the Software without restriction, including
    10     without limitation the rights to use, copy, modify, merge, publish,
    11     distribute, sublicense, and/or sell copies of the Software, and to
    12     permit persons to whom the Software is furnished to do so, subject to
    13     the following conditions:
    14  
    15     The above copyright notice and this permission notice shall be included
    16     in all copies or substantial portions of the Software.
    17  
    18     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
    19     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    20     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    21     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
    22     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    23     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    24     OTHER DEALINGS IN THE SOFTWARE.
    25     ----------------------------------------------------------------------- */
    26  /*====================================================================*/
    27  /*                          Includes                                  */
    28  /*                          --------                                  */
    29  /*====================================================================*/
    30  
    31  #include <ffi.h>
    32  #include <ffi_common.h>
    33  #include <stdint.h>
    34  #include "internal.h"
    35  
    36  /*====================== End of Includes =============================*/
    37  
    38  /*====================================================================*/
    39  /*                           Defines                                  */
    40  /*                           -------                                  */
    41  /*====================================================================*/
    42  
    43  /* Maximum number of GPRs available for argument passing.  */
    44  #define MAX_GPRARGS 5
    45  
    46  /* Maximum number of FPRs available for argument passing.  */
    47  #ifdef __s390x__
    48  #define MAX_FPRARGS 4
    49  #else
    50  #define MAX_FPRARGS 2
    51  #endif
    52  
    53  /* Round to multiple of 16.  */
    54  #define ROUND_SIZE(size) (((size) + 15) & ~15)
    55  
    56  /*===================== End of Defines ===============================*/
    57  
    58  /*====================================================================*/
    59  /*                          Externals                                 */
    60  /*                          ---------                                 */
    61  /*====================================================================*/
    62  
    63  struct call_frame
    64  {
    65    void *back_chain;
    66    void *eos;
    67    unsigned long gpr_args[5];
    68    unsigned long gpr_save[9];
    69    unsigned long long fpr_args[4];
    70  };
    71  
    72  extern void FFI_HIDDEN ffi_call_SYSV(struct call_frame *, unsigned, void *,
    73  			             void (*fn)(void), void *);
    74  
    75  extern void ffi_closure_SYSV(void);
    76  extern void ffi_go_closure_SYSV(void);
    77  
    78  /*====================== End of Externals ============================*/
    79  
    80  /*====================================================================*/
    81  /*                                                                    */
    82  /* Name     - ffi_check_struct_type.                                  */
    83  /*                                                                    */
    84  /* Function - Determine if a structure can be passed within a         */
    85  /*            general purpose or floating point register.             */
    86  /*                                                                    */
    87  /*====================================================================*/
    88  
    89  static int
    90  ffi_check_struct_type (ffi_type *arg)
    91  {
    92    size_t size = arg->size;
    93  
    94    /* If the struct has just one element, look at that element
    95       to find out whether to consider the struct as floating point.  */
    96    while (arg->type == FFI_TYPE_STRUCT
    97           && arg->elements[0] && !arg->elements[1])
    98      arg = arg->elements[0];
    99  
   100    /* Structs of size 1, 2, 4, and 8 are passed in registers,
   101       just like the corresponding int/float types.  */
   102    switch (size)
   103      {
   104        case 1:
   105          return FFI_TYPE_UINT8;
   106  
   107        case 2:
   108          return FFI_TYPE_UINT16;
   109  
   110        case 4:
   111  	if (arg->type == FFI_TYPE_FLOAT)
   112            return FFI_TYPE_FLOAT;
   113  	else
   114  	  return FFI_TYPE_UINT32;
   115  
   116        case 8:
   117  	if (arg->type == FFI_TYPE_DOUBLE)
   118            return FFI_TYPE_DOUBLE;
   119  	else
   120  	  return FFI_TYPE_UINT64;
   121  
   122        default:
   123  	break;
   124      }
   125  
   126    /* Other structs are passed via a pointer to the data.  */
   127    return FFI_TYPE_POINTER;
   128  }
   129  
   130  /*======================== End of Routine ============================*/
   131  
   132  /*====================================================================*/
   133  /*                                                                    */
   134  /* Name     - ffi_prep_cif_machdep.                                   */
   135  /*                                                                    */
   136  /* Function - Perform machine dependent CIF processing.               */
   137  /*                                                                    */
   138  /*====================================================================*/
   139  
   140  ffi_status FFI_HIDDEN
   141  ffi_prep_cif_machdep(ffi_cif *cif)
   142  {
   143    size_t struct_size = 0;
   144    int n_gpr = 0;
   145    int n_fpr = 0;
   146    int n_ov = 0;
   147  
   148    ffi_type **ptr;
   149    int i;
   150  
   151    /* Determine return value handling.  */
   152  
   153    switch (cif->rtype->type)
   154      {
   155        /* Void is easy.  */
   156        case FFI_TYPE_VOID:
   157  	cif->flags = FFI390_RET_VOID;
   158  	break;
   159  
   160        /* Structures and complex are returned via a hidden pointer.  */
   161        case FFI_TYPE_STRUCT:
   162        case FFI_TYPE_COMPLEX:
   163  	cif->flags = FFI390_RET_STRUCT;
   164  	n_gpr++;  /* We need one GPR to pass the pointer.  */
   165  	break;
   166  
   167        /* Floating point values are returned in fpr 0.  */
   168        case FFI_TYPE_FLOAT:
   169  	cif->flags = FFI390_RET_FLOAT;
   170  	break;
   171  
   172        case FFI_TYPE_DOUBLE:
   173  	cif->flags = FFI390_RET_DOUBLE;
   174  	break;
   175  
   176  #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
   177        case FFI_TYPE_LONGDOUBLE:
   178  	cif->flags = FFI390_RET_STRUCT;
   179  	n_gpr++;
   180  	break;
   181  #endif
   182        /* Integer values are returned in gpr 2 (and gpr 3
   183  	 for 64-bit values on 31-bit machines).  */
   184        case FFI_TYPE_UINT64:
   185        case FFI_TYPE_SINT64:
   186  	cif->flags = FFI390_RET_INT64;
   187  	break;
   188  
   189        case FFI_TYPE_POINTER:
   190        case FFI_TYPE_INT:
   191        case FFI_TYPE_UINT32:
   192        case FFI_TYPE_SINT32:
   193        case FFI_TYPE_UINT16:
   194        case FFI_TYPE_SINT16:
   195        case FFI_TYPE_UINT8:
   196        case FFI_TYPE_SINT8:
   197  	/* These are to be extended to word size.  */
   198  #ifdef __s390x__
   199  	cif->flags = FFI390_RET_INT64;
   200  #else
   201  	cif->flags = FFI390_RET_INT32;
   202  #endif
   203  	break;
   204  
   205        default:
   206          FFI_ASSERT (0);
   207          break;
   208      }
   209  
   210    /* Now for the arguments.  */
   211  
   212    for (ptr = cif->arg_types, i = cif->nargs;
   213         i > 0;
   214         i--, ptr++)
   215      {
   216        int type = (*ptr)->type;
   217  
   218  #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
   219        /* 16-byte long double is passed like a struct.  */
   220        if (type == FFI_TYPE_LONGDOUBLE)
   221  	type = FFI_TYPE_STRUCT;
   222  #endif
   223  
   224        /* Check how a structure type is passed.  */
   225        if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
   226  	{
   227  	  if (type == FFI_TYPE_COMPLEX)
   228  	    type = FFI_TYPE_POINTER;
   229  	  else
   230  	    type = ffi_check_struct_type (*ptr);
   231  
   232  	  /* If we pass the struct via pointer, we must reserve space
   233  	     to copy its data for proper call-by-value semantics.  */
   234  	  if (type == FFI_TYPE_POINTER)
   235  	    struct_size += ROUND_SIZE ((*ptr)->size);
   236  	}
   237  
   238        /* Now handle all primitive int/float data types.  */
   239        switch (type)
   240  	{
   241  	  /* The first MAX_FPRARGS floating point arguments
   242  	     go in FPRs, the rest overflow to the stack.  */
   243  
   244  	  case FFI_TYPE_DOUBLE:
   245  	    if (n_fpr < MAX_FPRARGS)
   246  	      n_fpr++;
   247  	    else
   248  	      n_ov += sizeof (double) / sizeof (long);
   249  	    break;
   250  
   251  	  case FFI_TYPE_FLOAT:
   252  	    if (n_fpr < MAX_FPRARGS)
   253  	      n_fpr++;
   254  	    else
   255  	      n_ov++;
   256  	    break;
   257  
   258  	  /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
   259  	     if one is still available, or else on the stack.  If only one
   260  	     register is free, skip the register (it won't be used for any
   261  	     subsequent argument either).  */
   262  
   263  #ifndef __s390x__
   264  	  case FFI_TYPE_UINT64:
   265  	  case FFI_TYPE_SINT64:
   266  	    if (n_gpr == MAX_GPRARGS-1)
   267  	      n_gpr = MAX_GPRARGS;
   268  	    if (n_gpr < MAX_GPRARGS)
   269  	      n_gpr += 2;
   270  	    else
   271  	      n_ov += 2;
   272  	    break;
   273  #endif
   274  
   275  	  /* Everything else is passed in GPRs (until MAX_GPRARGS
   276  	     have been used) or overflows to the stack.  */
   277  
   278  	  default:
   279  	    if (n_gpr < MAX_GPRARGS)
   280  	      n_gpr++;
   281  	    else
   282  	      n_ov++;
   283  	    break;
   284          }
   285      }
   286  
   287    /* Total stack space as required for overflow arguments
   288       and temporary structure copies.  */
   289  
   290    cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
   291  
   292    return FFI_OK;
   293  }
   294  
   295  /*======================== End of Routine ============================*/
   296  
   297  /*====================================================================*/
   298  /*                                                                    */
   299  /* Name     - ffi_call.                                               */
   300  /*                                                                    */
   301  /* Function - Call the FFI routine.                                   */
   302  /*                                                                    */
   303  /*====================================================================*/
   304  
   305  static void
   306  ffi_call_int(ffi_cif *cif,
   307  	     void (*fn)(void),
   308  	     void *rvalue,
   309  	     void **avalue,
   310  	     void *closure)
   311  {
   312    int ret_type = cif->flags;
   313    size_t rsize = 0, bytes = cif->bytes;
   314    unsigned char *stack, *p_struct;
   315    struct call_frame *frame;
   316    unsigned long *p_ov, *p_gpr;
   317    unsigned long long *p_fpr;
   318    int n_fpr, n_gpr, n_ov, i, n;
   319    ffi_type **arg_types;
   320  
   321    FFI_ASSERT (cif->abi == FFI_SYSV);
   322  
   323    /* If we don't have a return value, we need to fake one.  */
   324    if (rvalue == NULL)
   325      {
   326        if (ret_type & FFI390_RET_IN_MEM)
   327  	rsize = cif->rtype->size;
   328        else
   329  	ret_type = FFI390_RET_VOID;
   330      }
   331  
   332    /* The stack space will be filled with those areas:
   333  
   334  	dummy structure return		    (highest addresses)
   335  	  FPR argument register save area
   336  	  GPR argument register save area
   337  	stack frame for ffi_call_SYSV
   338  	temporary struct copies
   339  	overflow argument area              (lowest addresses)
   340  
   341       We set up the following pointers:
   342  
   343          p_fpr: bottom of the FPR area (growing upwards)
   344  	p_gpr: bottom of the GPR area (growing upwards)
   345  	p_ov: bottom of the overflow area (growing upwards)
   346  	p_struct: top of the struct copy area (growing downwards)
   347  
   348       All areas are kept aligned to twice the word size.
   349  
   350       Note that we're going to create the stack frame for both
   351       ffi_call_SYSV _and_ the target function right here.  This
   352       works because we don't make any function calls with more
   353       than 5 arguments (indeed only memcpy and ffi_call_SYSV),
   354       and thus we don't have any stacked outgoing parameters.  */
   355  
   356    stack = alloca (bytes + sizeof(struct call_frame) + rsize);
   357    frame = (struct call_frame *)(stack + bytes);
   358    if (rsize)
   359      rvalue = frame + 1;
   360  
   361    /* Link the new frame back to the one from this function.  */
   362    frame->back_chain = __builtin_frame_address (0);
   363  
   364    /* Fill in all of the argument stuff.  */
   365    p_ov = (unsigned long *)stack;
   366    p_struct = (unsigned char *)frame;
   367    p_gpr = frame->gpr_args;
   368    p_fpr = frame->fpr_args;
   369    n_fpr = n_gpr = n_ov = 0;
   370  
   371    /* If we returning a structure then we set the first parameter register
   372       to the address of where we are returning this structure.  */
   373    if (cif->flags & FFI390_RET_IN_MEM)
   374      p_gpr[n_gpr++] = (uintptr_t) rvalue;
   375  
   376    /* Now for the arguments.  */
   377    arg_types = cif->arg_types;
   378    for (i = 0, n = cif->nargs; i < n; ++i)
   379      {
   380        ffi_type *ty = arg_types[i];
   381        void *arg = avalue[i];
   382        int type = ty->type;
   383        ffi_arg val;
   384  
   385      restart:
   386        switch (type)
   387  	{
   388  	case FFI_TYPE_SINT8:
   389  	  val = *(SINT8 *)arg;
   390  	  goto do_int;
   391  	case FFI_TYPE_UINT8:
   392  	  val = *(UINT8 *)arg;
   393  	  goto do_int;
   394  	case FFI_TYPE_SINT16:
   395  	  val = *(SINT16 *)arg;
   396  	  goto do_int;
   397  	case FFI_TYPE_UINT16:
   398  	  val = *(UINT16 *)arg;
   399  	  goto do_int;
   400  	case FFI_TYPE_INT:
   401  	case FFI_TYPE_SINT32:
   402  	  val = *(SINT32 *)arg;
   403  	  goto do_int;
   404  	case FFI_TYPE_UINT32:
   405  	  val = *(UINT32 *)arg;
   406  	  goto do_int;
   407  	case FFI_TYPE_POINTER:
   408  	  val = *(uintptr_t *)arg;
   409  	do_int:
   410  	  *(n_gpr < MAX_GPRARGS ? p_gpr + n_gpr++ : p_ov + n_ov++) = val;
   411  	  break;
   412  
   413  	case FFI_TYPE_UINT64:
   414  	case FFI_TYPE_SINT64:
   415  #ifdef __s390x__
   416  	  val = *(UINT64 *)arg;
   417  	  goto do_int;
   418  #else
   419  	  if (n_gpr == MAX_GPRARGS-1)
   420  	    n_gpr = MAX_GPRARGS;
   421  	  if (n_gpr < MAX_GPRARGS)
   422  	    p_gpr[n_gpr++] = ((UINT32 *) arg)[0],
   423  	    p_gpr[n_gpr++] = ((UINT32 *) arg)[1];
   424  	  else
   425  	    p_ov[n_ov++] = ((UINT32 *) arg)[0],
   426  	    p_ov[n_ov++] = ((UINT32 *) arg)[1];
   427  #endif
   428  	  break;
   429  
   430  	case FFI_TYPE_DOUBLE:
   431  	  if (n_fpr < MAX_FPRARGS)
   432  	    p_fpr[n_fpr++] = *(UINT64 *) arg;
   433  	  else
   434  	    {
   435  #ifdef __s390x__
   436  	      p_ov[n_ov++] = *(UINT64 *) arg;
   437  #else
   438  	      p_ov[n_ov++] = ((UINT32 *) arg)[0],
   439  	      p_ov[n_ov++] = ((UINT32 *) arg)[1];
   440  #endif
   441  	    }
   442  	  break;
   443  
   444  	case FFI_TYPE_FLOAT:
   445  	  val = *(UINT32 *)arg;
   446  	  if (n_fpr < MAX_FPRARGS)
   447  	    p_fpr[n_fpr++] = (UINT64)val << 32;
   448  	  else
   449  	    p_ov[n_ov++] = val;
   450  	  break;
   451  
   452  	case FFI_TYPE_STRUCT:
   453            /* Check how a structure type is passed.  */
   454  	  type = ffi_check_struct_type (ty);
   455  	  /* Some structures are passed via a type they contain.  */
   456  	  if (type != FFI_TYPE_POINTER)
   457  	    goto restart;
   458  	  /* ... otherwise, passed by reference.  fallthru.  */
   459  
   460  #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
   461  	case FFI_TYPE_LONGDOUBLE:
   462  	  /* 16-byte long double is passed via reference.  */
   463  #endif
   464  	case FFI_TYPE_COMPLEX:
   465  	  /* Complex types are passed via reference.  */
   466  	  p_struct -= ROUND_SIZE (ty->size);
   467  	  memcpy (p_struct, arg, ty->size);
   468  	  val = (uintptr_t)p_struct;
   469  	  goto do_int;
   470  
   471  	default:
   472  	  FFI_ASSERT (0);
   473  	  break;
   474          }
   475      }
   476  
   477    ffi_call_SYSV (frame, ret_type & FFI360_RET_MASK, rvalue, fn, closure);
   478  }
   479  
   480  void
   481  ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
   482  {
   483    ffi_call_int(cif, fn, rvalue, avalue, NULL);
   484  }
   485  
   486  void
   487  ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
   488  	     void **avalue, void *closure)
   489  {
   490    ffi_call_int(cif, fn, rvalue, avalue, closure);
   491  }
   492  
   493  /*======================== End of Routine ============================*/
   494  
   495  /*====================================================================*/
   496  /*                                                                    */
   497  /* Name     - ffi_closure_helper_SYSV.                                */
   498  /*                                                                    */
   499  /* Function - Call a FFI closure target function.                     */
   500  /*                                                                    */
   501  /*====================================================================*/
   502  
   503  void FFI_HIDDEN
   504  ffi_closure_helper_SYSV (ffi_cif *cif,
   505  			 void (*fun)(ffi_cif*,void*,void**,void*),
   506  			 void *user_data,
   507  			 unsigned long *p_gpr,
   508  			 unsigned long long *p_fpr,
   509  			 unsigned long *p_ov)
   510  {
   511    unsigned long long ret_buffer;
   512  
   513    void *rvalue = &ret_buffer;
   514    void **avalue;
   515    void **p_arg;
   516  
   517    int n_gpr = 0;
   518    int n_fpr = 0;
   519    int n_ov = 0;
   520  
   521    ffi_type **ptr;
   522    int i;
   523  
   524    /* Allocate buffer for argument list pointers.  */
   525    p_arg = avalue = alloca (cif->nargs * sizeof (void *));
   526  
   527    /* If we returning a structure, pass the structure address
   528       directly to the target function.  Otherwise, have the target
   529       function store the return value to the GPR save area.  */
   530    if (cif->flags & FFI390_RET_IN_MEM)
   531      rvalue = (void *) p_gpr[n_gpr++];
   532  
   533    /* Now for the arguments.  */
   534    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, p_arg++, ptr++)
   535      {
   536        int deref_struct_pointer = 0;
   537        int type = (*ptr)->type;
   538  
   539  #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
   540        /* 16-byte long double is passed like a struct.  */
   541        if (type == FFI_TYPE_LONGDOUBLE)
   542  	type = FFI_TYPE_STRUCT;
   543  #endif
   544  
   545        /* Check how a structure type is passed.  */
   546        if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
   547  	{
   548  	  if (type == FFI_TYPE_COMPLEX)
   549  	    type = FFI_TYPE_POINTER;
   550  	  else
   551  	    type = ffi_check_struct_type (*ptr);
   552  
   553  	  /* If we pass the struct via pointer, remember to
   554  	     retrieve the pointer later.  */
   555  	  if (type == FFI_TYPE_POINTER)
   556  	    deref_struct_pointer = 1;
   557  	}
   558  
   559        /* Pointers are passed like UINTs of the same size.  */
   560        if (type == FFI_TYPE_POINTER)
   561  	{
   562  #ifdef __s390x__
   563  	  type = FFI_TYPE_UINT64;
   564  #else
   565  	  type = FFI_TYPE_UINT32;
   566  #endif
   567  	}
   568  
   569        /* Now handle all primitive int/float data types.  */
   570        switch (type)
   571  	{
   572  	  case FFI_TYPE_DOUBLE:
   573  	    if (n_fpr < MAX_FPRARGS)
   574  	      *p_arg = &p_fpr[n_fpr++];
   575  	    else
   576  	      *p_arg = &p_ov[n_ov],
   577  	      n_ov += sizeof (double) / sizeof (long);
   578  	    break;
   579  
   580  	  case FFI_TYPE_FLOAT:
   581  	    if (n_fpr < MAX_FPRARGS)
   582  	      *p_arg = &p_fpr[n_fpr++];
   583  	    else
   584  	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
   585  	    break;
   586  
   587  	  case FFI_TYPE_UINT64:
   588  	  case FFI_TYPE_SINT64:
   589  #ifdef __s390x__
   590  	    if (n_gpr < MAX_GPRARGS)
   591  	      *p_arg = &p_gpr[n_gpr++];
   592  	    else
   593  	      *p_arg = &p_ov[n_ov++];
   594  #else
   595  	    if (n_gpr == MAX_GPRARGS-1)
   596  	      n_gpr = MAX_GPRARGS;
   597  	    if (n_gpr < MAX_GPRARGS)
   598  	      *p_arg = &p_gpr[n_gpr], n_gpr += 2;
   599  	    else
   600  	      *p_arg = &p_ov[n_ov], n_ov += 2;
   601  #endif
   602  	    break;
   603  
   604  	  case FFI_TYPE_INT:
   605  	  case FFI_TYPE_UINT32:
   606  	  case FFI_TYPE_SINT32:
   607  	    if (n_gpr < MAX_GPRARGS)
   608  	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
   609  	    else
   610  	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
   611  	    break;
   612  
   613  	  case FFI_TYPE_UINT16:
   614  	  case FFI_TYPE_SINT16:
   615  	    if (n_gpr < MAX_GPRARGS)
   616  	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
   617  	    else
   618  	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
   619  	    break;
   620  
   621  	  case FFI_TYPE_UINT8:
   622  	  case FFI_TYPE_SINT8:
   623  	    if (n_gpr < MAX_GPRARGS)
   624  	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
   625  	    else
   626  	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
   627  	    break;
   628  
   629  	  default:
   630  	    FFI_ASSERT (0);
   631  	    break;
   632          }
   633  
   634        /* If this is a struct passed via pointer, we need to
   635  	 actually retrieve that pointer.  */
   636        if (deref_struct_pointer)
   637  	*p_arg = *(void **)*p_arg;
   638      }
   639  
   640  
   641    /* Call the target function.  */
   642    (fun) (cif, rvalue, avalue, user_data);
   643  
   644    /* Convert the return value.  */
   645    switch (cif->rtype->type)
   646      {
   647        /* Void is easy, and so is struct.  */
   648        case FFI_TYPE_VOID:
   649        case FFI_TYPE_STRUCT:
   650        case FFI_TYPE_COMPLEX:
   651  #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
   652        case FFI_TYPE_LONGDOUBLE:
   653  #endif
   654  	break;
   655  
   656        /* Floating point values are returned in fpr 0.  */
   657        case FFI_TYPE_FLOAT:
   658  	p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
   659  	break;
   660  
   661        case FFI_TYPE_DOUBLE:
   662  	p_fpr[0] = *(unsigned long long *) rvalue;
   663  	break;
   664  
   665        /* Integer values are returned in gpr 2 (and gpr 3
   666  	 for 64-bit values on 31-bit machines).  */
   667        case FFI_TYPE_UINT64:
   668        case FFI_TYPE_SINT64:
   669  #ifdef __s390x__
   670  	p_gpr[0] = *(unsigned long *) rvalue;
   671  #else
   672  	p_gpr[0] = ((unsigned long *) rvalue)[0],
   673  	p_gpr[1] = ((unsigned long *) rvalue)[1];
   674  #endif
   675  	break;
   676  
   677        case FFI_TYPE_POINTER:
   678        case FFI_TYPE_UINT32:
   679        case FFI_TYPE_UINT16:
   680        case FFI_TYPE_UINT8:
   681  	p_gpr[0] = *(unsigned long *) rvalue;
   682  	break;
   683  
   684        case FFI_TYPE_INT:
   685        case FFI_TYPE_SINT32:
   686        case FFI_TYPE_SINT16:
   687        case FFI_TYPE_SINT8:
   688  	p_gpr[0] = *(signed long *) rvalue;
   689  	break;
   690  
   691        default:
   692          FFI_ASSERT (0);
   693          break;
   694      }
   695  }
   696  
   697  /*======================== End of Routine ============================*/
   698  
   699  /*====================================================================*/
   700  /*                                                                    */
   701  /* Name     - ffi_prep_closure_loc.                                   */
   702  /*                                                                    */
   703  /* Function - Prepare a FFI closure.                                  */
   704  /*                                                                    */
   705  /*====================================================================*/
   706  
   707  ffi_status
   708  ffi_prep_closure_loc (ffi_closure *closure,
   709  		      ffi_cif *cif,
   710  		      void (*fun) (ffi_cif *, void *, void **, void *),
   711  		      void *user_data,
   712  		      void *codeloc)
   713  {
   714    static unsigned short const template[] = {
   715      0x0d10,			/* basr %r1,0 */
   716  #ifndef __s390x__
   717      0x9801, 0x1006,		/* lm %r0,%r1,6(%r1) */
   718  #else
   719      0xeb01, 0x100e, 0x0004,	/* lmg %r0,%r1,14(%r1) */
   720  #endif
   721      0x07f1			/* br %r1 */
   722    };
   723  
   724    unsigned long *tramp = (unsigned long *)&closure->tramp;
   725  
   726    if (cif->abi != FFI_SYSV)
   727      return FFI_BAD_ABI;
   728  
   729    memcpy (tramp, template, sizeof(template));
   730    tramp[2] = (unsigned long)codeloc;
   731    tramp[3] = (unsigned long)&ffi_closure_SYSV;
   732  
   733    closure->cif = cif;
   734    closure->fun = fun;
   735    closure->user_data = user_data;
   736  
   737    return FFI_OK;
   738  }
   739  
   740  /*======================== End of Routine ============================*/
   741  
   742  /* Build a Go language closure.  */
   743  
   744  ffi_status
   745  ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
   746  		     void (*fun)(ffi_cif*,void*,void**,void*))
   747  {
   748    if (cif->abi != FFI_SYSV)
   749      return FFI_BAD_ABI;
   750  
   751    closure->tramp = ffi_go_closure_SYSV;
   752    closure->cif = cif;
   753    closure->fun = fun;
   754  
   755    return FFI_OK;
   756  }