Home | History | Annotate | Download | only in sh
      1 /* -----------------------------------------------------------------------
      2    ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Kaz Kojima
      3            Copyright (c) 2008 Red Hat, Inc.
      4 
      5    SuperH 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 #define NGREGARG 4
     34 #if defined(__SH4__)
     35 #define NFREGARG 8
     36 #endif
     37 
     38 #if defined(__HITACHI__)
     39 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
     40 #else
     41 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
     42 #endif
     43 
     44 /* If the structure has essentialy an unique element, return its type.  */
     45 static int
     46 simple_type (ffi_type *arg)
     47 {
     48   if (arg->type != FFI_TYPE_STRUCT)
     49     return arg->type;
     50   else if (arg->elements[1])
     51     return FFI_TYPE_STRUCT;
     52 
     53   return simple_type (arg->elements[0]);
     54 }
     55 
     56 static int
     57 return_type (ffi_type *arg)
     58 {
     59   unsigned short type;
     60 
     61   if (arg->type != FFI_TYPE_STRUCT)
     62     return arg->type;
     63 
     64   type = simple_type (arg->elements[0]);
     65   if (! arg->elements[1])
     66     {
     67       switch (type)
     68 	{
     69 	case FFI_TYPE_SINT8:
     70 	case FFI_TYPE_UINT8:
     71 	case FFI_TYPE_SINT16:
     72 	case FFI_TYPE_UINT16:
     73 	case FFI_TYPE_SINT32:
     74 	case FFI_TYPE_UINT32:
     75 	  return FFI_TYPE_INT;
     76 
     77 	default:
     78 	  return type;
     79 	}
     80     }
     81 
     82   /* gcc uses r0/r1 pair for some kind of structures.  */
     83   if (arg->size <= 2 * sizeof (int))
     84     {
     85       int i = 0;
     86       ffi_type *e;
     87 
     88       while ((e = arg->elements[i++]))
     89 	{
     90 	  type = simple_type (e);
     91 	  switch (type)
     92 	    {
     93 	    case FFI_TYPE_SINT32:
     94 	    case FFI_TYPE_UINT32:
     95 	    case FFI_TYPE_INT:
     96 	    case FFI_TYPE_FLOAT:
     97 	      return FFI_TYPE_UINT64;
     98 
     99 	    default:
    100 	      break;
    101 	    }
    102 	}
    103     }
    104 
    105   return FFI_TYPE_STRUCT;
    106 }
    107 
    108 /* ffi_prep_args is called by the assembly routine once stack space
    109    has been allocated for the function's arguments */
    110 
    111 void ffi_prep_args(char *stack, extended_cif *ecif)
    112 {
    113   register unsigned int i;
    114   register int tmp;
    115   register unsigned int avn;
    116   register void **p_argv;
    117   register char *argp;
    118   register ffi_type **p_arg;
    119   int greg, ireg;
    120 #if defined(__SH4__)
    121   int freg = 0;
    122 #endif
    123 
    124   tmp = 0;
    125   argp = stack;
    126 
    127   if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
    128     {
    129       *(void **) argp = ecif->rvalue;
    130       argp += 4;
    131       ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
    132     }
    133   else
    134     ireg = 0;
    135 
    136   /* Set arguments for registers.  */
    137   greg = ireg;
    138   avn = ecif->cif->nargs;
    139   p_argv = ecif->avalue;
    140 
    141   for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
    142     {
    143       size_t z;
    144 
    145       z = (*p_arg)->size;
    146       if (z < sizeof(int))
    147 	{
    148 	  if (greg++ >= NGREGARG)
    149 	    continue;
    150 
    151 	  z = sizeof(int);
    152 	  switch ((*p_arg)->type)
    153 	    {
    154 	    case FFI_TYPE_SINT8:
    155 	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
    156 	      break;
    157 
    158 	    case FFI_TYPE_UINT8:
    159 	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
    160 	      break;
    161 
    162 	    case FFI_TYPE_SINT16:
    163 	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
    164 	      break;
    165 
    166 	    case FFI_TYPE_UINT16:
    167 	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
    168 	      break;
    169 
    170 	    case FFI_TYPE_STRUCT:
    171 	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
    172 	      break;
    173 
    174 	    default:
    175 	      FFI_ASSERT(0);
    176 	    }
    177 	  argp += z;
    178 	}
    179       else if (z == sizeof(int))
    180 	{
    181 #if defined(__SH4__)
    182 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
    183 	    {
    184 	      if (freg++ >= NFREGARG)
    185 		continue;
    186 	    }
    187 	  else
    188 #endif
    189 	    {
    190 	      if (greg++ >= NGREGARG)
    191 		continue;
    192 	    }
    193 	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
    194 	  argp += z;
    195 	}
    196 #if defined(__SH4__)
    197       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
    198 	{
    199 	  if (freg + 1 >= NFREGARG)
    200 	    continue;
    201 	  freg = (freg + 1) & ~1;
    202 	  freg += 2;
    203 	  memcpy (argp, *p_argv, z);
    204 	  argp += z;
    205 	}
    206 #endif
    207       else
    208 	{
    209 	  int n = (z + sizeof (int) - 1) / sizeof (int);
    210 #if defined(__SH4__)
    211 	  if (greg + n - 1 >= NGREGARG)
    212 	    continue;
    213 #else
    214 	  if (greg >= NGREGARG)
    215 	    continue;
    216 #endif
    217 	  greg += n;
    218 	  memcpy (argp, *p_argv, z);
    219 	  argp += n * sizeof (int);
    220 	}
    221     }
    222 
    223   /* Set arguments on stack.  */
    224   greg = ireg;
    225 #if defined(__SH4__)
    226   freg = 0;
    227 #endif
    228   p_argv = ecif->avalue;
    229 
    230   for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
    231     {
    232       size_t z;
    233 
    234       z = (*p_arg)->size;
    235       if (z < sizeof(int))
    236 	{
    237 	  if (greg++ < NGREGARG)
    238 	    continue;
    239 
    240 	  z = sizeof(int);
    241 	  switch ((*p_arg)->type)
    242 	    {
    243 	    case FFI_TYPE_SINT8:
    244 	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
    245 	      break;
    246 
    247 	    case FFI_TYPE_UINT8:
    248 	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
    249 	      break;
    250 
    251 	    case FFI_TYPE_SINT16:
    252 	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
    253 	      break;
    254 
    255 	    case FFI_TYPE_UINT16:
    256 	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
    257 	      break;
    258 
    259 	    case FFI_TYPE_STRUCT:
    260 	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
    261 	      break;
    262 
    263 	    default:
    264 	      FFI_ASSERT(0);
    265 	    }
    266 	  argp += z;
    267 	}
    268       else if (z == sizeof(int))
    269 	{
    270 #if defined(__SH4__)
    271 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
    272 	    {
    273 	      if (freg++ < NFREGARG)
    274 		continue;
    275 	    }
    276 	  else
    277 #endif
    278 	    {
    279 	      if (greg++ < NGREGARG)
    280 		continue;
    281 	    }
    282 	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
    283 	  argp += z;
    284 	}
    285 #if defined(__SH4__)
    286       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
    287 	{
    288 	  if (freg + 1 < NFREGARG)
    289 	    {
    290 	      freg = (freg + 1) & ~1;
    291 	      freg += 2;
    292 	      continue;
    293 	    }
    294 	  memcpy (argp, *p_argv, z);
    295 	  argp += z;
    296 	}
    297 #endif
    298       else
    299 	{
    300 	  int n = (z + sizeof (int) - 1) / sizeof (int);
    301 	  if (greg + n - 1 < NGREGARG)
    302 	    {
    303 	      greg += n;
    304 	      continue;
    305 	    }
    306 #if (! defined(__SH4__))
    307 	  else if (greg < NGREGARG)
    308 	    {
    309 	      greg = NGREGARG;
    310 	      continue;
    311 	    }
    312 #endif
    313 	  memcpy (argp, *p_argv, z);
    314 	  argp += n * sizeof (int);
    315 	}
    316     }
    317 
    318   return;
    319 }
    320 
    321 /* Perform machine dependent cif processing */
    322 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
    323 {
    324   int i, j;
    325   int size, type;
    326   int n, m;
    327   int greg;
    328 #if defined(__SH4__)
    329   int freg = 0;
    330 #endif
    331 
    332   cif->flags = 0;
    333 
    334   greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
    335 	  STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
    336 
    337 #if defined(__SH4__)
    338   for (i = j = 0; i < cif->nargs && j < 12; i++)
    339     {
    340       type = (cif->arg_types)[i]->type;
    341       switch (type)
    342 	{
    343 	case FFI_TYPE_FLOAT:
    344 	  if (freg >= NFREGARG)
    345 	    continue;
    346 	  freg++;
    347 	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
    348 	  j++;
    349 	  break;
    350 
    351 	case FFI_TYPE_DOUBLE:
    352 	  if ((freg + 1) >= NFREGARG)
    353 	    continue;
    354 	  freg = (freg + 1) & ~1;
    355 	  freg += 2;
    356 	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
    357 	  j++;
    358 	  break;
    359 
    360 	default:
    361 	  size = (cif->arg_types)[i]->size;
    362 	  n = (size + sizeof (int) - 1) / sizeof (int);
    363 	  if (greg + n - 1 >= NGREGARG)
    364 		continue;
    365 	  greg += n;
    366 	  for (m = 0; m < n; m++)
    367 	    cif->flags += FFI_TYPE_INT << (2 * j++);
    368 	  break;
    369 	}
    370     }
    371 #else
    372   for (i = j = 0; i < cif->nargs && j < 4; i++)
    373     {
    374       size = (cif->arg_types)[i]->size;
    375       n = (size + sizeof (int) - 1) / sizeof (int);
    376       if (greg >= NGREGARG)
    377 	continue;
    378       else if (greg + n - 1 >= NGREGARG)
    379 	n = NGREGARG - greg;
    380       greg += n;
    381       for (m = 0; m < n; m++)
    382         cif->flags += FFI_TYPE_INT << (2 * j++);
    383     }
    384 #endif
    385 
    386   /* Set the return type flag */
    387   switch (cif->rtype->type)
    388     {
    389     case FFI_TYPE_STRUCT:
    390       cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
    391       break;
    392 
    393     case FFI_TYPE_VOID:
    394     case FFI_TYPE_FLOAT:
    395     case FFI_TYPE_DOUBLE:
    396     case FFI_TYPE_SINT64:
    397     case FFI_TYPE_UINT64:
    398       cif->flags += (unsigned) cif->rtype->type << 24;
    399       break;
    400 
    401     default:
    402       cif->flags += FFI_TYPE_INT << 24;
    403       break;
    404     }
    405 
    406   return FFI_OK;
    407 }
    408 
    409 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
    410 			  unsigned, unsigned, unsigned *, void (*fn)(void));
    411 
    412 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
    413 {
    414   extended_cif ecif;
    415   UINT64 trvalue;
    416 
    417   ecif.cif = cif;
    418   ecif.avalue = avalue;
    419 
    420   /* If the return value is a struct and we don't have a return	*/
    421   /* value address then we need to make one		        */
    422 
    423   if (cif->rtype->type == FFI_TYPE_STRUCT
    424       && return_type (cif->rtype) != FFI_TYPE_STRUCT)
    425     ecif.rvalue = &trvalue;
    426   else if ((rvalue == NULL) &&
    427       (cif->rtype->type == FFI_TYPE_STRUCT))
    428     {
    429       ecif.rvalue = alloca(cif->rtype->size);
    430     }
    431   else
    432     ecif.rvalue = rvalue;
    433 
    434   switch (cif->abi)
    435     {
    436     case FFI_SYSV:
    437       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
    438 		    fn);
    439       break;
    440     default:
    441       FFI_ASSERT(0);
    442       break;
    443     }
    444 
    445   if (rvalue
    446       && cif->rtype->type == FFI_TYPE_STRUCT
    447       && return_type (cif->rtype) != FFI_TYPE_STRUCT)
    448     memcpy (rvalue, &trvalue, cif->rtype->size);
    449 }
    450 
    451 extern void ffi_closure_SYSV (void);
    452 #if defined(__SH4__)
    453 extern void __ic_invalidate (void *line);
    454 #endif
    455 
    456 ffi_status
    457 ffi_prep_closure_loc (ffi_closure* closure,
    458 		      ffi_cif* cif,
    459 		      void (*fun)(ffi_cif*, void*, void**, void*),
    460 		      void *user_data,
    461 		      void *codeloc)
    462 {
    463   unsigned int *tramp;
    464   unsigned int insn;
    465 
    466   FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
    467 
    468   tramp = (unsigned int *) &closure->tramp[0];
    469   /* Set T bit if the function returns a struct pointed with R2.  */
    470   insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
    471 	  ? 0x0018 /* sett */
    472 	  : 0x0008 /* clrt */);
    473 
    474 #ifdef __LITTLE_ENDIAN__
    475   tramp[0] = 0xd301d102;
    476   tramp[1] = 0x0000412b | (insn << 16);
    477 #else
    478   tramp[0] = 0xd102d301;
    479   tramp[1] = 0x412b0000 | insn;
    480 #endif
    481   *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
    482   *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
    483 
    484   closure->cif = cif;
    485   closure->fun = fun;
    486   closure->user_data = user_data;
    487 
    488 #if defined(__SH4__)
    489   /* Flush the icache.  */
    490   __ic_invalidate(codeloc);
    491 #endif
    492 
    493   return FFI_OK;
    494 }
    495 
    496 /* Basically the trampoline invokes ffi_closure_SYSV, and on
    497  * entry, r3 holds the address of the closure.
    498  * After storing the registers that could possibly contain
    499  * parameters to be passed into the stack frame and setting
    500  * up space for a return value, ffi_closure_SYSV invokes the
    501  * following helper function to do most of the work.
    502  */
    503 
    504 #ifdef __LITTLE_ENDIAN__
    505 #define OFS_INT8	0
    506 #define OFS_INT16	0
    507 #else
    508 #define OFS_INT8	3
    509 #define OFS_INT16	2
    510 #endif
    511 
    512 int
    513 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
    514 			 unsigned long *pgr, unsigned long *pfr,
    515 			 unsigned long *pst)
    516 {
    517   void **avalue;
    518   ffi_type **p_arg;
    519   int i, avn;
    520   int ireg, greg = 0;
    521 #if defined(__SH4__)
    522   int freg = 0;
    523 #endif
    524   ffi_cif *cif;
    525 
    526   cif = closure->cif;
    527   avalue = alloca(cif->nargs * sizeof(void *));
    528 
    529   /* Copy the caller's structure return value address so that the closure
    530      returns the data directly to the caller.  */
    531   if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
    532     {
    533       rvalue = (void *) *pgr++;
    534       ireg = 1;
    535     }
    536   else
    537     ireg = 0;
    538 
    539   cif = closure->cif;
    540   greg = ireg;
    541   avn = cif->nargs;
    542 
    543   /* Grab the addresses of the arguments from the stack frame.  */
    544   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
    545     {
    546       size_t z;
    547 
    548       z = (*p_arg)->size;
    549       if (z < sizeof(int))
    550 	{
    551 	  if (greg++ >= NGREGARG)
    552 	    continue;
    553 
    554 	  z = sizeof(int);
    555 	  switch ((*p_arg)->type)
    556 	    {
    557 	    case FFI_TYPE_SINT8:
    558 	    case FFI_TYPE_UINT8:
    559 	      avalue[i] = (((char *)pgr) + OFS_INT8);
    560 	      break;
    561 
    562 	    case FFI_TYPE_SINT16:
    563 	    case FFI_TYPE_UINT16:
    564 	      avalue[i] = (((char *)pgr) + OFS_INT16);
    565 	      break;
    566 
    567 	    case FFI_TYPE_STRUCT:
    568 	      avalue[i] = pgr;
    569 	      break;
    570 
    571 	    default:
    572 	      FFI_ASSERT(0);
    573 	    }
    574 	  pgr++;
    575 	}
    576       else if (z == sizeof(int))
    577 	{
    578 #if defined(__SH4__)
    579 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
    580 	    {
    581 	      if (freg++ >= NFREGARG)
    582 		continue;
    583 	      avalue[i] = pfr;
    584 	      pfr++;
    585 	    }
    586 	  else
    587 #endif
    588 	    {
    589 	      if (greg++ >= NGREGARG)
    590 		continue;
    591 	      avalue[i] = pgr;
    592 	      pgr++;
    593 	    }
    594 	}
    595 #if defined(__SH4__)
    596       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
    597 	{
    598 	  if (freg + 1 >= NFREGARG)
    599 	    continue;
    600 	  if (freg & 1)
    601 	    pfr++;
    602 	  freg = (freg + 1) & ~1;
    603 	  freg += 2;
    604 	  avalue[i] = pfr;
    605 	  pfr += 2;
    606 	}
    607 #endif
    608       else
    609 	{
    610 	  int n = (z + sizeof (int) - 1) / sizeof (int);
    611 #if defined(__SH4__)
    612 	  if (greg + n - 1 >= NGREGARG)
    613 	    continue;
    614 #else
    615 	  if (greg >= NGREGARG)
    616 	    continue;
    617 #endif
    618 	  greg += n;
    619 	  avalue[i] = pgr;
    620 	  pgr += n;
    621 	}
    622     }
    623 
    624   greg = ireg;
    625 #if defined(__SH4__)
    626   freg = 0;
    627 #endif
    628 
    629   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
    630     {
    631       size_t z;
    632 
    633       z = (*p_arg)->size;
    634       if (z < sizeof(int))
    635 	{
    636 	  if (greg++ < NGREGARG)
    637 	    continue;
    638 
    639 	  z = sizeof(int);
    640 	  switch ((*p_arg)->type)
    641 	    {
    642 	    case FFI_TYPE_SINT8:
    643 	    case FFI_TYPE_UINT8:
    644 	      avalue[i] = (((char *)pst) + OFS_INT8);
    645 	      break;
    646 
    647 	    case FFI_TYPE_SINT16:
    648 	    case FFI_TYPE_UINT16:
    649 	      avalue[i] = (((char *)pst) + OFS_INT16);
    650 	      break;
    651 
    652 	    case FFI_TYPE_STRUCT:
    653 	      avalue[i] = pst;
    654 	      break;
    655 
    656 	    default:
    657 	      FFI_ASSERT(0);
    658 	    }
    659 	  pst++;
    660 	}
    661       else if (z == sizeof(int))
    662 	{
    663 #if defined(__SH4__)
    664 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
    665 	    {
    666 	      if (freg++ < NFREGARG)
    667 		continue;
    668 	    }
    669 	  else
    670 #endif
    671 	    {
    672 	      if (greg++ < NGREGARG)
    673 		continue;
    674 	    }
    675 	  avalue[i] = pst;
    676 	  pst++;
    677 	}
    678 #if defined(__SH4__)
    679       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
    680 	{
    681 	  if (freg + 1 < NFREGARG)
    682 	    {
    683 	      freg = (freg + 1) & ~1;
    684 	      freg += 2;
    685 	      continue;
    686 	    }
    687 	  avalue[i] = pst;
    688 	  pst += 2;
    689 	}
    690 #endif
    691       else
    692 	{
    693 	  int n = (z + sizeof (int) - 1) / sizeof (int);
    694 	  if (greg + n - 1 < NGREGARG)
    695 	    {
    696 	      greg += n;
    697 	      continue;
    698 	    }
    699 #if (! defined(__SH4__))
    700 	  else if (greg < NGREGARG)
    701 	    {
    702 	      greg += n;
    703 	      pst += greg - NGREGARG;
    704 	      continue;
    705 	    }
    706 #endif
    707 	  avalue[i] = pst;
    708 	  pst += n;
    709 	}
    710     }
    711 
    712   (closure->fun) (cif, rvalue, avalue, closure->user_data);
    713 
    714   /* Tell ffi_closure_SYSV how to perform return type promotions.  */
    715   return return_type (cif->rtype);
    716 }
    717