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