(root)/
gcc-13.2.0/
libffi/
src/
m68k/
ffi.c
       1  /* -----------------------------------------------------------------------
       2     ffi.c
       3  
       4     m68k Foreign Function Interface
       5     ----------------------------------------------------------------------- */
       6  
       7  #include <ffi.h>
       8  #include <ffi_common.h>
       9  
      10  #include <stdlib.h>
      11  #include <unistd.h>
      12  #ifdef __rtems__
      13  void rtems_cache_flush_multiple_data_lines( const void *, size_t );
      14  #else
      15  #include <sys/syscall.h>
      16  #ifdef __MINT__
      17  #include <mint/mintbind.h>
      18  #include <mint/ssystem.h>
      19  #else
      20  #include <asm/cachectl.h>
      21  #endif
      22  #endif
      23  
      24  void ffi_call_SYSV (extended_cif *,
      25  		    unsigned, unsigned,
      26  		    void *, void (*fn) ());
      27  void *ffi_prep_args (void *stack, extended_cif *ecif);
      28  void ffi_closure_SYSV (ffi_closure *);
      29  void ffi_closure_struct_SYSV (ffi_closure *);
      30  unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
      31  				     void *resp, void *args);
      32  
      33  /* ffi_prep_args is called by the assembly routine once stack space has
      34     been allocated for the function's arguments.  */
      35  
      36  void *
      37  ffi_prep_args (void *stack, extended_cif *ecif)
      38  {
      39    unsigned int i;
      40    void **p_argv;
      41    char *argp;
      42    ffi_type **p_arg;
      43    void *struct_value_ptr;
      44  
      45    argp = stack;
      46  
      47    if (
      48  #ifdef __MINT__
      49        (ecif->cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
      50  #endif
      51        (((ecif->cif->rtype->type == FFI_TYPE_STRUCT)
      52          && !ecif->cif->flags)))
      53      struct_value_ptr = ecif->rvalue;
      54    else
      55      struct_value_ptr = NULL;
      56  
      57    p_argv = ecif->avalue;
      58  
      59    for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
      60         i != 0;
      61         i--, p_arg++)
      62      {
      63        size_t z = (*p_arg)->size;
      64        int type = (*p_arg)->type;
      65  
      66        if (z < sizeof (int))
      67  	{
      68  	  switch (type)
      69  	    {
      70  	    case FFI_TYPE_SINT8:
      71  	      *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
      72  	      break;
      73  
      74  	    case FFI_TYPE_UINT8:
      75  	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
      76  	      break;
      77  
      78  	    case FFI_TYPE_SINT16:
      79  	      *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
      80  	      break;
      81  
      82  	    case FFI_TYPE_UINT16:
      83  	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
      84  	      break;
      85  
      86  	    case FFI_TYPE_STRUCT:
      87  #ifdef __MINT__
      88  	      if (z == 1 || z == 2)
      89  		memcpy (argp + 2, *p_argv, z);
      90                else
      91  		memcpy (argp, *p_argv, z);
      92  #else
      93  	      memcpy (argp + sizeof (int) - z, *p_argv, z);
      94  #endif
      95  	      break;
      96  
      97  	    default:
      98  	      FFI_ASSERT (0);
      99  	    }
     100  	  z = sizeof (int);
     101  	}
     102        else
     103  	{
     104  	  memcpy (argp, *p_argv, z);
     105  
     106  	  /* Align if necessary.  */
     107  	  if ((sizeof(int) - 1) & z)
     108  	    z = FFI_ALIGN(z, sizeof(int));
     109  	}
     110  
     111        p_argv++;
     112        argp += z;
     113      }
     114  
     115    return struct_value_ptr;
     116  }
     117  
     118  #define CIF_FLAGS_INT		1
     119  #define CIF_FLAGS_DINT		2
     120  #define CIF_FLAGS_FLOAT		4
     121  #define CIF_FLAGS_DOUBLE	8
     122  #define CIF_FLAGS_LDOUBLE	16
     123  #define CIF_FLAGS_POINTER	32
     124  #define CIF_FLAGS_STRUCT1	64
     125  #define CIF_FLAGS_STRUCT2	128
     126  #define CIF_FLAGS_SINT8		256
     127  #define CIF_FLAGS_SINT16	512
     128  
     129  /* Perform machine dependent cif processing */
     130  ffi_status
     131  ffi_prep_cif_machdep (ffi_cif *cif)
     132  {
     133    /* Set the return type flag */
     134    switch (cif->rtype->type)
     135      {
     136      case FFI_TYPE_VOID:
     137        cif->flags = 0;
     138        break;
     139  
     140      case FFI_TYPE_STRUCT:
     141        if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
     142            cif->rtype->elements[1])
     143          {
     144            cif->flags = 0;
     145            break;
     146          }
     147  
     148        switch (cif->rtype->size)
     149  	{
     150  	case 1:
     151  #ifdef __MINT__
     152  	  cif->flags = CIF_FLAGS_STRUCT2;
     153  #else
     154  	  cif->flags = CIF_FLAGS_STRUCT1;
     155  #endif
     156  	  break;
     157  	case 2:
     158  	  cif->flags = CIF_FLAGS_STRUCT2;
     159  	  break;
     160  #ifdef __MINT__
     161  	case 3:
     162  #endif
     163  	case 4:
     164  	  cif->flags = CIF_FLAGS_INT;
     165  	  break;
     166  #ifdef __MINT__
     167  	case 7:
     168  #endif
     169  	case 8:
     170  	  cif->flags = CIF_FLAGS_DINT;
     171  	  break;
     172  	default:
     173  	  cif->flags = 0;
     174  	  break;
     175  	}
     176        break;
     177  
     178      case FFI_TYPE_FLOAT:
     179        cif->flags = CIF_FLAGS_FLOAT;
     180        break;
     181  
     182      case FFI_TYPE_DOUBLE:
     183        cif->flags = CIF_FLAGS_DOUBLE;
     184        break;
     185  
     186  #if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
     187      case FFI_TYPE_LONGDOUBLE:
     188  #ifdef __MINT__
     189        cif->flags = 0;
     190  #else
     191        cif->flags = CIF_FLAGS_LDOUBLE;
     192  #endif
     193        break;
     194  #endif
     195  
     196      case FFI_TYPE_POINTER:
     197        cif->flags = CIF_FLAGS_POINTER;
     198        break;
     199  
     200      case FFI_TYPE_SINT64:
     201      case FFI_TYPE_UINT64:
     202        cif->flags = CIF_FLAGS_DINT;
     203        break;
     204  
     205      case FFI_TYPE_SINT16:
     206        cif->flags = CIF_FLAGS_SINT16;
     207        break;
     208  
     209      case FFI_TYPE_SINT8:
     210        cif->flags = CIF_FLAGS_SINT8;
     211        break;
     212  
     213      default:
     214        cif->flags = CIF_FLAGS_INT;
     215        break;
     216      }
     217  
     218    return FFI_OK;
     219  }
     220  
     221  void
     222  ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
     223  {
     224    extended_cif ecif;
     225  
     226    ecif.cif = cif;
     227    ecif.avalue = avalue;
     228  
     229    /* If the return value is a struct and we don't have a return value
     230       address then we need to make one.  */
     231  
     232    if (rvalue == NULL
     233        && cif->rtype->type == FFI_TYPE_STRUCT
     234        && cif->rtype->size > 8)
     235      ecif.rvalue = alloca (cif->rtype->size);
     236    else
     237      ecif.rvalue = rvalue;
     238  
     239    switch (cif->abi)
     240      {
     241      case FFI_SYSV:
     242        ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
     243  		     ecif.rvalue, fn);
     244        break;
     245  
     246      default:
     247        FFI_ASSERT (0);
     248        break;
     249      }
     250  }
     251  
     252  static void
     253  ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
     254  {
     255    unsigned int i;
     256    void **p_argv;
     257    char *argp;
     258    ffi_type **p_arg;
     259  
     260    argp = stack;
     261    p_argv = avalue;
     262  
     263    for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
     264      {
     265        size_t z;
     266  
     267        z = (*p_arg)->size;
     268  #ifdef __MINT__
     269        if (cif->flags &&
     270            cif->rtype->type == FFI_TYPE_STRUCT &&
     271            (z == 1 || z == 2))
     272   	{
     273  	  *p_argv = (void *) (argp + 2);
     274  
     275  	  z = 4;
     276  	}
     277        else
     278        if (cif->flags &&
     279            cif->rtype->type == FFI_TYPE_STRUCT &&
     280            (z == 3 || z == 4))
     281   	{
     282  	  *p_argv = (void *) (argp);
     283  
     284  	  z = 4;
     285  	}
     286        else
     287  #endif
     288        if (z <= 4)
     289  	{
     290  	  *p_argv = (void *) (argp + 4 - z);
     291  
     292  	  z = 4;
     293  	}
     294        else
     295  	{
     296  	  *p_argv = (void *) argp;
     297  
     298  	  /* Align if necessary */
     299  	  if ((sizeof(int) - 1) & z)
     300  	    z = FFI_ALIGN(z, sizeof(int));
     301  	}
     302  
     303        p_argv++;
     304        argp += z;
     305      }
     306  }
     307  
     308  unsigned int
     309  ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
     310  {
     311    ffi_cif *cif;
     312    void **arg_area;
     313  
     314    cif = closure->cif;
     315    arg_area = (void**) alloca (cif->nargs * sizeof (void *));
     316  
     317    ffi_prep_incoming_args_SYSV(args, arg_area, cif);
     318  
     319    (closure->fun) (cif, resp, arg_area, closure->user_data);
     320  
     321    return cif->flags;
     322  }
     323  
     324  ffi_status
     325  ffi_prep_closure_loc (ffi_closure* closure,
     326  		      ffi_cif* cif,
     327  		      void (*fun)(ffi_cif*,void*,void**,void*),
     328  		      void *user_data,
     329  		      void *codeloc)
     330  {
     331    if (cif->abi != FFI_SYSV)
     332      return FFI_BAD_ABI;
     333  
     334    *(unsigned short *)closure->tramp = 0x207c;
     335    *(void **)(closure->tramp + 2) = codeloc;
     336    *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
     337  
     338    if (
     339  #ifdef __MINT__
     340        (cif->rtype->type == FFI_TYPE_LONGDOUBLE) ||
     341  #endif
     342        (((cif->rtype->type == FFI_TYPE_STRUCT)
     343           && !cif->flags)))
     344      *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
     345    else
     346      *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
     347  
     348  #ifdef __rtems__
     349    rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
     350  #elif defined(__MINT__)
     351    Ssystem(S_FLUSHCACHE, codeloc, FFI_TRAMPOLINE_SIZE);
     352  #else
     353    syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
     354  	  FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
     355  #endif
     356  
     357    closure->cif  = cif;
     358    closure->user_data = user_data;
     359    closure->fun  = fun;
     360  
     361    return FFI_OK;
     362  }