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