Home | History | Annotate | Download | only in sparc
      1 /* -----------------------------------------------------------------------
      2    ffi.c - Copyright (c) 2011, 2013 Anthony Green
      3            Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
      4 
      5    SPARC 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,
     19    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     22    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     23    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     24    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     25    DEALINGS IN THE SOFTWARE.
     26    ----------------------------------------------------------------------- */
     27 
     28 #include <ffi.h>
     29 #include <ffi_common.h>
     30 
     31 #include <stdlib.h>
     32 
     33 
     34 /* ffi_prep_args is called by the assembly routine once stack space
     35    has been allocated for the function's arguments */
     36 
     37 void ffi_prep_args_v8(char *stack, extended_cif *ecif)
     38 {
     39   int i;
     40   void **p_argv;
     41   char *argp;
     42   ffi_type **p_arg;
     43 
     44   /* Skip 16 words for the window save area */
     45   argp = stack + 16*sizeof(int);
     46 
     47   /* This should only really be done when we are returning a structure,
     48      however, it's faster just to do it all the time...
     49 
     50   if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
     51   *(int *) argp = (long)ecif->rvalue;
     52 
     53   /* And 1 word for the  structure return value. */
     54   argp += sizeof(int);
     55 
     56 #ifdef USING_PURIFY
     57   /* Purify will probably complain in our assembly routine, unless we
     58      zero out this memory. */
     59 
     60   ((int*)argp)[0] = 0;
     61   ((int*)argp)[1] = 0;
     62   ((int*)argp)[2] = 0;
     63   ((int*)argp)[3] = 0;
     64   ((int*)argp)[4] = 0;
     65   ((int*)argp)[5] = 0;
     66 #endif
     67 
     68   p_argv = ecif->avalue;
     69 
     70   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
     71     {
     72       size_t z;
     73 
     74 	  if ((*p_arg)->type == FFI_TYPE_STRUCT
     75 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
     76 	      || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
     77 #endif
     78 	      )
     79 	    {
     80 	      *(unsigned int *) argp = (unsigned long)(* p_argv);
     81 	      z = sizeof(int);
     82 	    }
     83 	  else
     84 	    {
     85 	      z = (*p_arg)->size;
     86 	      if (z < sizeof(int))
     87 		{
     88 		  z = sizeof(int);
     89 		  switch ((*p_arg)->type)
     90 		    {
     91 		    case FFI_TYPE_SINT8:
     92 		      *(signed int *) argp = *(SINT8 *)(* p_argv);
     93 		      break;
     94 
     95 		    case FFI_TYPE_UINT8:
     96 		      *(unsigned int *) argp = *(UINT8 *)(* p_argv);
     97 		      break;
     98 
     99 		    case FFI_TYPE_SINT16:
    100 		      *(signed int *) argp = *(SINT16 *)(* p_argv);
    101 		      break;
    102 
    103 		    case FFI_TYPE_UINT16:
    104 		      *(unsigned int *) argp = *(UINT16 *)(* p_argv);
    105 		      break;
    106 
    107 		    default:
    108 		      FFI_ASSERT(0);
    109 		    }
    110 		}
    111 	      else
    112 		{
    113 		  memcpy(argp, *p_argv, z);
    114 		}
    115 	    }
    116 	  p_argv++;
    117 	  argp += z;
    118     }
    119 
    120   return;
    121 }
    122 
    123 int ffi_prep_args_v9(char *stack, extended_cif *ecif)
    124 {
    125   int i, ret = 0;
    126   int tmp;
    127   void **p_argv;
    128   char *argp;
    129   ffi_type **p_arg;
    130 
    131   tmp = 0;
    132 
    133   /* Skip 16 words for the window save area */
    134   argp = stack + 16*sizeof(long long);
    135 
    136 #ifdef USING_PURIFY
    137   /* Purify will probably complain in our assembly routine, unless we
    138      zero out this memory. */
    139 
    140   ((long long*)argp)[0] = 0;
    141   ((long long*)argp)[1] = 0;
    142   ((long long*)argp)[2] = 0;
    143   ((long long*)argp)[3] = 0;
    144   ((long long*)argp)[4] = 0;
    145   ((long long*)argp)[5] = 0;
    146 #endif
    147 
    148   p_argv = ecif->avalue;
    149 
    150   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
    151       ecif->cif->rtype->size > 32)
    152     {
    153       *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
    154       argp += sizeof(long long);
    155       tmp = 1;
    156     }
    157 
    158   for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
    159        i++, p_arg++)
    160     {
    161       size_t z;
    162 
    163       z = (*p_arg)->size;
    164       switch ((*p_arg)->type)
    165 	{
    166 	case FFI_TYPE_STRUCT:
    167 	  if (z > 16)
    168 	    {
    169 	      /* For structures larger than 16 bytes we pass reference.  */
    170 	      *(unsigned long long *) argp = (unsigned long)* p_argv;
    171 	      argp += sizeof(long long);
    172 	      tmp++;
    173 	      p_argv++;
    174 	      continue;
    175 	    }
    176 	  /* FALLTHROUGH */
    177 	case FFI_TYPE_FLOAT:
    178 	case FFI_TYPE_DOUBLE:
    179 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    180 	case FFI_TYPE_LONGDOUBLE:
    181 #endif
    182 	  ret = 1; /* We should promote into FP regs as well as integer.  */
    183 	  break;
    184 	}
    185       if (z < sizeof(long long))
    186 	{
    187 	  switch ((*p_arg)->type)
    188 	    {
    189 	    case FFI_TYPE_SINT8:
    190 	      *(signed long long *) argp = *(SINT8 *)(* p_argv);
    191 	      break;
    192 
    193 	    case FFI_TYPE_UINT8:
    194 	      *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
    195 	      break;
    196 
    197 	    case FFI_TYPE_SINT16:
    198 	      *(signed long long *) argp = *(SINT16 *)(* p_argv);
    199 	      break;
    200 
    201 	    case FFI_TYPE_UINT16:
    202 	      *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
    203 	      break;
    204 
    205 	    case FFI_TYPE_SINT32:
    206 	      *(signed long long *) argp = *(SINT32 *)(* p_argv);
    207 	      break;
    208 
    209 	    case FFI_TYPE_UINT32:
    210 	      *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
    211 	      break;
    212 
    213 	    case FFI_TYPE_FLOAT:
    214 	      *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
    215 	      break;
    216 
    217 	    case FFI_TYPE_STRUCT:
    218 	      memcpy(argp, *p_argv, z);
    219 	      break;
    220 
    221 	    default:
    222 	      FFI_ASSERT(0);
    223 	    }
    224 	  z = sizeof(long long);
    225 	  tmp++;
    226 	}
    227       else if (z == sizeof(long long))
    228 	{
    229 	  memcpy(argp, *p_argv, z);
    230 	  z = sizeof(long long);
    231 	  tmp++;
    232 	}
    233       else
    234 	{
    235 	  if ((tmp & 1) && (*p_arg)->alignment > 8)
    236 	    {
    237 	      tmp++;
    238 	      argp += sizeof(long long);
    239 	    }
    240 	  memcpy(argp, *p_argv, z);
    241 	  z = 2 * sizeof(long long);
    242 	  tmp += 2;
    243 	}
    244       p_argv++;
    245       argp += z;
    246     }
    247 
    248   return ret;
    249 }
    250 
    251 /* Perform machine dependent cif processing */
    252 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
    253 {
    254   int wordsize;
    255 
    256   if (cif->abi != FFI_V9)
    257     {
    258       wordsize = 4;
    259 
    260       /* If we are returning a struct, this will already have been added.
    261 	 Otherwise we need to add it because it's always got to be there! */
    262 
    263       if (cif->rtype->type != FFI_TYPE_STRUCT)
    264 	cif->bytes += wordsize;
    265 
    266       /* sparc call frames require that space is allocated for 6 args,
    267 	 even if they aren't used. Make that space if necessary. */
    268 
    269       if (cif->bytes < 4*6+4)
    270 	cif->bytes = 4*6+4;
    271     }
    272   else
    273     {
    274       wordsize = 8;
    275 
    276       /* sparc call frames require that space is allocated for 6 args,
    277 	 even if they aren't used. Make that space if necessary. */
    278 
    279       if (cif->bytes < 8*6)
    280 	cif->bytes = 8*6;
    281     }
    282 
    283   /* Adjust cif->bytes. to include 16 words for the window save area,
    284      and maybe the struct/union return pointer area, */
    285 
    286   cif->bytes += 16 * wordsize;
    287 
    288   /* The stack must be 2 word aligned, so round bytes up
    289      appropriately. */
    290 
    291   cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
    292 
    293   /* Set the return type flag */
    294   switch (cif->rtype->type)
    295     {
    296     case FFI_TYPE_VOID:
    297     case FFI_TYPE_FLOAT:
    298     case FFI_TYPE_DOUBLE:
    299 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    300     case FFI_TYPE_LONGDOUBLE:
    301 #endif
    302       cif->flags = cif->rtype->type;
    303       break;
    304 
    305     case FFI_TYPE_STRUCT:
    306       if (cif->abi == FFI_V9 && cif->rtype->size > 32)
    307 	cif->flags = FFI_TYPE_VOID;
    308       else
    309 	cif->flags = FFI_TYPE_STRUCT;
    310       break;
    311 
    312     case FFI_TYPE_SINT8:
    313     case FFI_TYPE_UINT8:
    314     case FFI_TYPE_SINT16:
    315     case FFI_TYPE_UINT16:
    316       if (cif->abi == FFI_V9)
    317 	cif->flags = FFI_TYPE_INT;
    318       else
    319 	cif->flags = cif->rtype->type;
    320       break;
    321 
    322     case FFI_TYPE_SINT64:
    323     case FFI_TYPE_UINT64:
    324       if (cif->abi == FFI_V9)
    325 	cif->flags = FFI_TYPE_INT;
    326       else
    327 	cif->flags = FFI_TYPE_SINT64;
    328       break;
    329 
    330     default:
    331       cif->flags = FFI_TYPE_INT;
    332       break;
    333     }
    334   return FFI_OK;
    335 }
    336 
    337 int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
    338 {
    339   ffi_type **ptr = &arg->elements[0];
    340 
    341   while (*ptr != NULL)
    342     {
    343       if (off & ((*ptr)->alignment - 1))
    344 	off = ALIGN(off, (*ptr)->alignment);
    345 
    346       switch ((*ptr)->type)
    347 	{
    348 	case FFI_TYPE_STRUCT:
    349 	  off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
    350 	  off = ALIGN(off, FFI_SIZEOF_ARG);
    351 	  break;
    352 	case FFI_TYPE_FLOAT:
    353 	case FFI_TYPE_DOUBLE:
    354 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    355 	case FFI_TYPE_LONGDOUBLE:
    356 #endif
    357 	  memmove(ret + off, flt + off, (*ptr)->size);
    358 	  off += (*ptr)->size;
    359 	  break;
    360 	default:
    361 	  memmove(ret + off, intg + off, (*ptr)->size);
    362 	  off += (*ptr)->size;
    363 	  break;
    364 	}
    365       ptr++;
    366     }
    367   return off;
    368 }
    369 
    370 
    371 #ifdef SPARC64
    372 extern int ffi_call_v9(void *, extended_cif *, unsigned,
    373 		       unsigned, unsigned *, void (*fn)(void));
    374 #else
    375 extern int ffi_call_v8(void *, extended_cif *, unsigned,
    376 		       unsigned, unsigned *, void (*fn)(void));
    377 #endif
    378 
    379 #ifndef __GNUC__
    380 void ffi_flush_icache (void *, size_t);
    381 #endif
    382 
    383 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
    384 {
    385   extended_cif ecif;
    386   void *rval = rvalue;
    387 
    388   ecif.cif = cif;
    389   ecif.avalue = avalue;
    390 
    391   /* If the return value is a struct and we don't have a return	*/
    392   /* value address then we need to make one		        */
    393 
    394   ecif.rvalue = rvalue;
    395   if (cif->rtype->type == FFI_TYPE_STRUCT)
    396     {
    397       if (cif->rtype->size <= 32)
    398 	rval = alloca(64);
    399       else
    400 	{
    401 	  rval = NULL;
    402 	  if (rvalue == NULL)
    403 	    ecif.rvalue = alloca(cif->rtype->size);
    404 	}
    405     }
    406 
    407   switch (cif->abi)
    408     {
    409     case FFI_V8:
    410 #ifdef SPARC64
    411       /* We don't yet support calling 32bit code from 64bit */
    412       FFI_ASSERT(0);
    413 #else
    414       if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
    415 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    416 	  || cif->flags == FFI_TYPE_LONGDOUBLE
    417 #endif
    418 	  ))
    419 	{
    420 	  /* For v8, we need an "unimp" with size of returning struct */
    421 	  /* behind "call", so we alloc some executable space for it. */
    422 	  /* l7 is used, we need to make sure v8.S doesn't use %l7.   */
    423 	  unsigned int *call_struct = NULL;
    424 	  ffi_closure_alloc(32, (void **)&call_struct);
    425 	  if (call_struct)
    426 	    {
    427 	      unsigned long f = (unsigned long)fn;
    428 	      call_struct[0] = 0xae10001f;		 /* mov   %i7, %l7	 */
    429 	      call_struct[1] = 0xbe10000f;		 /* mov   %o7, %i7	 */
    430 	      call_struct[2] = 0x03000000 | f >> 10;     /* sethi %hi(fn), %g1	 */
    431 	      call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
    432 	      call_struct[4] = 0x01000000;		 /* nop			 */
    433 	      if (cif->rtype->size < 0x7f)
    434 		call_struct[5] = cif->rtype->size;	 /* unimp		 */
    435 	      else
    436 		call_struct[5] = 0x01000000;	     	 /* nop			 */
    437 	      call_struct[6] = 0x81c7e008;		 /* ret			 */
    438 	      call_struct[7] = 0xbe100017;		 /* mov   %l7, %i7	 */
    439 #ifdef __GNUC__
    440 	      asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
    441 			    "r" (call_struct) : "memory");
    442 	      /* SPARC v8 requires 5 instructions for flush to be visible */
    443 	      asm volatile ("nop; nop; nop; nop; nop");
    444 #else
    445 	      ffi_flush_icache (call_struct, 32);
    446 #endif
    447 	      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
    448 			  cif->flags, rvalue, call_struct);
    449 	      ffi_closure_free(call_struct);
    450 	    }
    451 	  else
    452 	    {
    453 	      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
    454 			  cif->flags, rvalue, fn);
    455 	    }
    456 	}
    457       else
    458 	{
    459 	  ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
    460 		      cif->flags, rvalue, fn);
    461 	}
    462 #endif
    463       break;
    464     case FFI_V9:
    465 #ifdef SPARC64
    466       ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
    467 		  cif->flags, rval, fn);
    468       if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
    469 	ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
    470 #else
    471       /* And vice versa */
    472       FFI_ASSERT(0);
    473 #endif
    474       break;
    475     default:
    476       FFI_ASSERT(0);
    477       break;
    478     }
    479 }
    480 
    481 
    482 #ifdef SPARC64
    483 extern void ffi_closure_v9(void);
    484 #else
    485 extern void ffi_closure_v8(void);
    486 #endif
    487 
    488 ffi_status
    489 ffi_prep_closure_loc (ffi_closure* closure,
    490 		      ffi_cif* cif,
    491 		      void (*fun)(ffi_cif*, void*, void**, void*),
    492 		      void *user_data,
    493 		      void *codeloc)
    494 {
    495   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
    496   unsigned long fn;
    497 #ifdef SPARC64
    498   /* Trampoline address is equal to the closure address.  We take advantage
    499      of that to reduce the trampoline size by 8 bytes. */
    500   if (cif->abi != FFI_V9)
    501     return FFI_BAD_ABI;
    502   fn = (unsigned long) ffi_closure_v9;
    503   tramp[0] = 0x83414000;	/* rd	%pc, %g1	*/
    504   tramp[1] = 0xca586010;	/* ldx	[%g1+16], %g5	*/
    505   tramp[2] = 0x81c14000;	/* jmp	%g5		*/
    506   tramp[3] = 0x01000000;	/* nop			*/
    507   *((unsigned long *) &tramp[4]) = fn;
    508 #else
    509   unsigned long ctx = (unsigned long) codeloc;
    510   if (cif->abi != FFI_V8)
    511     return FFI_BAD_ABI;
    512   fn = (unsigned long) ffi_closure_v8;
    513   tramp[0] = 0x03000000 | fn >> 10;	/* sethi %hi(fn), %g1	*/
    514   tramp[1] = 0x05000000 | ctx >> 10;	/* sethi %hi(ctx), %g2	*/
    515   tramp[2] = 0x81c06000 | (fn & 0x3ff);	/* jmp   %g1+%lo(fn)	*/
    516   tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or    %g2, %lo(ctx)	*/
    517 #endif
    518 
    519   closure->cif = cif;
    520   closure->fun = fun;
    521   closure->user_data = user_data;
    522 
    523   /* Flush the Icache.  closure is 8 bytes aligned.  */
    524 #ifdef __GNUC__
    525 #ifdef SPARC64
    526   asm volatile ("flush	%0; flush %0+8" : : "r" (closure) : "memory");
    527 #else
    528   asm volatile ("iflush	%0; iflush %0+8" : : "r" (closure) : "memory");
    529   /* SPARC v8 requires 5 instructions for flush to be visible */
    530   asm volatile ("nop; nop; nop; nop; nop");
    531 #endif
    532 #else
    533   ffi_flush_icache (closure, 16);
    534 #endif
    535 
    536   return FFI_OK;
    537 }
    538 
    539 int
    540 ffi_closure_sparc_inner_v8(ffi_closure *closure,
    541   void *rvalue, unsigned long *gpr, unsigned long *scratch)
    542 {
    543   ffi_cif *cif;
    544   ffi_type **arg_types;
    545   void **avalue;
    546   int i, argn;
    547 
    548   cif = closure->cif;
    549   arg_types = cif->arg_types;
    550   avalue = alloca(cif->nargs * sizeof(void *));
    551 
    552   /* Copy the caller's structure return address so that the closure
    553      returns the data directly to the caller.  */
    554   if (cif->flags == FFI_TYPE_STRUCT
    555 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    556       || cif->flags == FFI_TYPE_LONGDOUBLE
    557 #endif
    558      )
    559     rvalue = (void *) gpr[0];
    560 
    561   /* Always skip the structure return address.  */
    562   argn = 1;
    563 
    564   /* Grab the addresses of the arguments from the stack frame.  */
    565   for (i = 0; i < cif->nargs; i++)
    566     {
    567       if (arg_types[i]->type == FFI_TYPE_STRUCT
    568 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    569 	  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
    570 #endif
    571          )
    572 	{
    573 	  /* Straight copy of invisible reference.  */
    574 	  avalue[i] = (void *)gpr[argn++];
    575 	}
    576       else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
    577 	       || arg_types[i]->type == FFI_TYPE_SINT64
    578 	       || arg_types[i]->type == FFI_TYPE_UINT64)
    579 	       /* gpr is 8-byte aligned.  */
    580 	       && (argn % 2) != 0)
    581 	{
    582 	  /* Align on a 8-byte boundary.  */
    583 	  scratch[0] = gpr[argn];
    584 	  scratch[1] = gpr[argn+1];
    585 	  avalue[i] = scratch;
    586 	  scratch -= 2;
    587 	  argn += 2;
    588 	}
    589       else
    590 	{
    591 	  /* Always right-justify.  */
    592 	  argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
    593 	  avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
    594 	}
    595     }
    596 
    597   /* Invoke the closure.  */
    598   (closure->fun) (cif, rvalue, avalue, closure->user_data);
    599 
    600   /* Tell ffi_closure_sparc how to perform return type promotions.  */
    601   return cif->rtype->type;
    602 }
    603 
    604 int
    605 ffi_closure_sparc_inner_v9(ffi_closure *closure,
    606   void *rvalue, unsigned long *gpr, double *fpr)
    607 {
    608   ffi_cif *cif;
    609   ffi_type **arg_types;
    610   void **avalue;
    611   int i, argn, fp_slot_max;
    612 
    613   cif = closure->cif;
    614   arg_types = cif->arg_types;
    615   avalue = alloca(cif->nargs * sizeof(void *));
    616 
    617   /* Copy the caller's structure return address so that the closure
    618      returns the data directly to the caller.  */
    619   if (cif->flags == FFI_TYPE_VOID
    620       && cif->rtype->type == FFI_TYPE_STRUCT)
    621     {
    622       rvalue = (void *) gpr[0];
    623       /* Skip the structure return address.  */
    624       argn = 1;
    625     }
    626   else
    627     argn = 0;
    628 
    629   fp_slot_max = 16 - argn;
    630 
    631   /* Grab the addresses of the arguments from the stack frame.  */
    632   for (i = 0; i < cif->nargs; i++)
    633     {
    634       if (arg_types[i]->type == FFI_TYPE_STRUCT)
    635 	{
    636 	  if (arg_types[i]->size > 16)
    637 	    {
    638 	      /* Straight copy of invisible reference.  */
    639 	      avalue[i] = (void *)gpr[argn++];
    640 	    }
    641 	  else
    642 	    {
    643 	      /* Left-justify.  */
    644 	      ffi_v9_layout_struct(arg_types[i],
    645 				   0,
    646 				   (char *) &gpr[argn],
    647 				   (char *) &gpr[argn],
    648 				   (char *) &fpr[argn]);
    649 	      avalue[i] = &gpr[argn];
    650 	      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
    651 	    }
    652 	}
    653       else
    654 	{
    655 	  /* Right-justify.  */
    656 	  argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
    657 
    658 	  /* Align on a 16-byte boundary.  */
    659 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    660 	  if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
    661 	    argn++;
    662 #endif
    663 	  if (i < fp_slot_max
    664 	      && (arg_types[i]->type == FFI_TYPE_FLOAT
    665 		  || arg_types[i]->type == FFI_TYPE_DOUBLE
    666 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
    667 		  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
    668 #endif
    669 		  ))
    670 	    avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
    671 	  else
    672 	    avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
    673 	}
    674     }
    675 
    676   /* Invoke the closure.  */
    677   (closure->fun) (cif, rvalue, avalue, closure->user_data);
    678 
    679   /* Tell ffi_closure_sparc how to perform return type promotions.  */
    680   return cif->rtype->type;
    681 }
    682