(root)/
gcc-13.2.0/
libffi/
src/
sh/
ffi.c
       1  /* -----------------------------------------------------------------------
       2     ffi.c - Copyright (c) 2002-2008, 2012 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 essentially 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    if (cif->abi != FFI_SYSV)
     467      return FFI_BAD_ABI;
     468  
     469    tramp = (unsigned int *) &closure->tramp[0];
     470    /* Set T bit if the function returns a struct pointed with R2.  */
     471    insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
     472  	  ? 0x0018 /* sett */
     473  	  : 0x0008 /* clrt */);
     474  
     475  #ifdef __LITTLE_ENDIAN__
     476    tramp[0] = 0xd301d102;
     477    tramp[1] = 0x0000412b | (insn << 16);
     478  #else
     479    tramp[0] = 0xd102d301;
     480    tramp[1] = 0x412b0000 | insn;
     481  #endif
     482    *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
     483    *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
     484  
     485    closure->cif = cif;
     486    closure->fun = fun;
     487    closure->user_data = user_data;
     488  
     489  #if defined(__SH4__)
     490    /* Flush the icache.  */
     491    __ic_invalidate(codeloc);
     492  #endif
     493  
     494    return FFI_OK;
     495  }
     496  
     497  /* Basically the trampoline invokes ffi_closure_SYSV, and on 
     498   * entry, r3 holds the address of the closure.
     499   * After storing the registers that could possibly contain
     500   * parameters to be passed into the stack frame and setting
     501   * up space for a return value, ffi_closure_SYSV invokes the 
     502   * following helper function to do most of the work.
     503   */
     504  
     505  #ifdef __LITTLE_ENDIAN__
     506  #define OFS_INT8	0
     507  #define OFS_INT16	0
     508  #else
     509  #define OFS_INT8	3
     510  #define OFS_INT16	2
     511  #endif
     512  
     513  int
     514  ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, 
     515  			 unsigned long *pgr, unsigned long *pfr, 
     516  			 unsigned long *pst)
     517  {
     518    void **avalue;
     519    ffi_type **p_arg;
     520    int i, avn;
     521    int ireg, greg = 0;
     522  #if defined(__SH4__)
     523    int freg = 0;
     524  #endif
     525    ffi_cif *cif; 
     526  
     527    cif = closure->cif;
     528    avalue = alloca(cif->nargs * sizeof(void *));
     529  
     530    /* Copy the caller's structure return value address so that the closure
     531       returns the data directly to the caller.  */
     532    if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
     533      {
     534        rvalue = (void *) *pgr++;
     535        ireg = 1;
     536      }
     537    else
     538      ireg = 0;
     539  
     540    cif = closure->cif;
     541    greg = ireg;
     542    avn = cif->nargs;
     543  
     544    /* Grab the addresses of the arguments from the stack frame.  */
     545    for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
     546      {
     547        size_t z;
     548  
     549        z = (*p_arg)->size;
     550        if (z < sizeof(int))
     551  	{
     552  	  if (greg++ >= NGREGARG)
     553  	    continue;
     554  
     555  	  z = sizeof(int);
     556  	  switch ((*p_arg)->type)
     557  	    {
     558  	    case FFI_TYPE_SINT8:
     559  	    case FFI_TYPE_UINT8:
     560  	      avalue[i] = (((char *)pgr) + OFS_INT8);
     561  	      break;
     562    
     563  	    case FFI_TYPE_SINT16:
     564  	    case FFI_TYPE_UINT16:
     565  	      avalue[i] = (((char *)pgr) + OFS_INT16);
     566  	      break;
     567    
     568  	    case FFI_TYPE_STRUCT:
     569  	      avalue[i] = pgr;
     570  	      break;
     571  
     572  	    default:
     573  	      FFI_ASSERT(0);
     574  	    }
     575  	  pgr++;
     576  	}
     577        else if (z == sizeof(int))
     578  	{
     579  #if defined(__SH4__)
     580  	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
     581  	    {
     582  	      if (freg++ >= NFREGARG)
     583  		continue;
     584  	      avalue[i] = pfr;
     585  	      pfr++;
     586  	    }
     587  	  else
     588  #endif
     589  	    {
     590  	      if (greg++ >= NGREGARG)
     591  		continue;
     592  	      avalue[i] = pgr;
     593  	      pgr++;
     594  	    }
     595  	}
     596  #if defined(__SH4__)
     597        else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
     598  	{
     599  	  if (freg + 1 >= NFREGARG)
     600  	    continue;
     601  	  if (freg & 1)
     602  	    pfr++;
     603  	  freg = (freg + 1) & ~1;
     604  	  freg += 2;
     605  	  avalue[i] = pfr;
     606  	  pfr += 2;
     607  	}
     608  #endif
     609        else
     610  	{
     611  	  int n = (z + sizeof (int) - 1) / sizeof (int);
     612  #if defined(__SH4__)
     613  	  if (greg + n - 1 >= NGREGARG)
     614  	    continue;
     615  #else
     616  	  if (greg >= NGREGARG)
     617  	    continue;
     618  #endif
     619  	  greg += n;
     620  	  avalue[i] = pgr;
     621  	  pgr += n;
     622  	}
     623      }
     624  
     625    greg = ireg;
     626  #if defined(__SH4__)
     627    freg = 0;
     628  #endif
     629  
     630    for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
     631      {
     632        size_t z;
     633  
     634        z = (*p_arg)->size;
     635        if (z < sizeof(int))
     636  	{
     637  	  if (greg++ < NGREGARG)
     638  	    continue;
     639  
     640  	  z = sizeof(int);
     641  	  switch ((*p_arg)->type)
     642  	    {
     643  	    case FFI_TYPE_SINT8:
     644  	    case FFI_TYPE_UINT8:
     645  	      avalue[i] = (((char *)pst) + OFS_INT8);
     646  	      break;
     647    
     648  	    case FFI_TYPE_SINT16:
     649  	    case FFI_TYPE_UINT16:
     650  	      avalue[i] = (((char *)pst) + OFS_INT16);
     651  	      break;
     652    
     653  	    case FFI_TYPE_STRUCT:
     654  	      avalue[i] = pst;
     655  	      break;
     656  
     657  	    default:
     658  	      FFI_ASSERT(0);
     659  	    }
     660  	  pst++;
     661  	}
     662        else if (z == sizeof(int))
     663  	{
     664  #if defined(__SH4__)
     665  	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
     666  	    {
     667  	      if (freg++ < NFREGARG)
     668  		continue;
     669  	    }
     670  	  else
     671  #endif
     672  	    {
     673  	      if (greg++ < NGREGARG)
     674  		continue;
     675  	    }
     676  	  avalue[i] = pst;
     677  	  pst++;
     678  	}
     679  #if defined(__SH4__)
     680        else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
     681  	{
     682  	  if (freg + 1 < NFREGARG)
     683  	    {
     684  	      freg = (freg + 1) & ~1;
     685  	      freg += 2;
     686  	      continue;
     687  	    }
     688  	  avalue[i] = pst;
     689  	  pst += 2;
     690  	}
     691  #endif
     692        else
     693  	{
     694  	  int n = (z + sizeof (int) - 1) / sizeof (int);
     695  	  if (greg + n - 1 < NGREGARG)
     696  	    {
     697  	      greg += n;
     698  	      continue;
     699  	    }
     700  #if (! defined(__SH4__))
     701  	  else if (greg < NGREGARG)
     702  	    {
     703  	      greg += n;
     704  	      pst += greg - NGREGARG;
     705  	      continue;
     706  	    }
     707  #endif
     708  	  avalue[i] = pst;
     709  	  pst += n;
     710  	}
     711      }
     712  
     713    (closure->fun) (cif, rvalue, avalue, closure->user_data);
     714  
     715    /* Tell ffi_closure_SYSV how to perform return type promotions.  */
     716    return return_type (cif->rtype);
     717  }