(root)/
gcc-13.2.0/
libffi/
src/
s390/
ffi.c
       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  }