(root)/
gcc-13.2.0/
libffi/
src/
arc/
ffi.c
       1  /* -----------------------------------------------------------------------
       2     ffi.c - Copyright (c) 2013  Synopsys, Inc. (www.synopsys.com)
       3     
       4     ARC 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, EXPRESS
      18     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      19     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      20     IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
      21     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      22     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      23     OTHER DEALINGS IN THE SOFTWARE.
      24     ----------------------------------------------------------------------- */
      25  
      26  #include <ffi.h>
      27  #include <ffi_common.h>
      28  
      29  #include <stdlib.h>
      30  #include <stdint.h>
      31  
      32  #include <sys/cachectl.h>
      33  
      34  /* for little endian ARC, the code is in fact stored as mixed endian for
      35     performance reasons */
      36  #if __BIG_ENDIAN__
      37  #define CODE_ENDIAN(x) (x)
      38  #else
      39  #define CODE_ENDIAN(x) ( (((uint32_t) (x)) << 16) | (((uint32_t) (x)) >> 16))
      40  #endif
      41  
      42  /* ffi_prep_args is called by the assembly routine once stack
      43     space has been allocated for the function's arguments.  */
      44  
      45  void
      46  ffi_prep_args (char *stack, extended_cif * ecif)
      47  {
      48    unsigned int i;
      49    void **p_argv;
      50    char *argp;
      51    ffi_type **p_arg;
      52  
      53    argp = stack;
      54  
      55    if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
      56      {
      57        *(void **) argp = ecif->rvalue;
      58        argp += 4;
      59      }
      60  
      61    p_argv = ecif->avalue;
      62  
      63    for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
      64         (i != 0); i--, p_arg++)
      65      {
      66        size_t z;
      67        int alignment;
      68  
      69        /* align alignment to 4 */
      70        alignment = (((*p_arg)->alignment - 1) | 3) + 1;
      71  
      72        /* Align if necessary.  */
      73        if ((alignment - 1) & (unsigned) argp)
      74  	argp = (char *) FFI_ALIGN (argp, alignment);
      75  
      76        z = (*p_arg)->size;
      77        if (z < sizeof (int))
      78  	{
      79  	  z = sizeof (int);
      80  
      81  	  switch ((*p_arg)->type)
      82  	    {
      83  	    case FFI_TYPE_SINT8:
      84  	      *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
      85  	      break;
      86  
      87  	    case FFI_TYPE_UINT8:
      88  	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) (*p_argv);
      89  	      break;
      90  
      91  	    case FFI_TYPE_SINT16:
      92  	      *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
      93  	      break;
      94  
      95  	    case FFI_TYPE_UINT16:
      96  	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) (*p_argv);
      97  	      break;
      98  
      99  	    case FFI_TYPE_STRUCT:
     100  	      memcpy (argp, *p_argv, (*p_arg)->size);
     101  	      break;
     102  
     103  	    default:
     104  	      FFI_ASSERT (0);
     105  	    }
     106  	}
     107        else if (z == sizeof (int))
     108  	{
     109  	  *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
     110  	}
     111        else
     112  	{
     113  	  if ((*p_arg)->type == FFI_TYPE_STRUCT)
     114  	    {
     115  	      memcpy (argp, *p_argv, z);
     116  	    }
     117  	  else
     118  	    {
     119  	      /* Double or long long 64bit.  */
     120  	      memcpy (argp, *p_argv, z);
     121  	    }
     122  	}
     123        p_argv++;
     124        argp += z;
     125      }
     126  
     127    return;
     128  }
     129  
     130  /* Perform machine dependent cif processing.  */
     131  ffi_status
     132  ffi_prep_cif_machdep (ffi_cif * cif)
     133  {
     134    /* Set the return type flag.  */
     135    switch (cif->rtype->type)
     136      {
     137      case FFI_TYPE_VOID:
     138        cif->flags = (unsigned) cif->rtype->type;
     139        break;
     140  
     141      case FFI_TYPE_STRUCT:
     142        cif->flags = (unsigned) cif->rtype->type;
     143        break;
     144  
     145      case FFI_TYPE_SINT64:
     146      case FFI_TYPE_UINT64:
     147      case FFI_TYPE_DOUBLE:
     148        cif->flags = FFI_TYPE_DOUBLE;
     149        break;
     150  
     151      case FFI_TYPE_FLOAT:
     152      default:
     153        cif->flags = FFI_TYPE_INT;
     154        break;
     155      }
     156  
     157    return FFI_OK;
     158  }
     159  
     160  extern void ffi_call_ARCompact (void (*)(char *, extended_cif *),
     161  				extended_cif *, unsigned, unsigned,
     162  				unsigned *, void (*fn) (void));
     163  
     164  void
     165  ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
     166  {
     167    extended_cif ecif;
     168  
     169    ecif.cif = cif;
     170    ecif.avalue = avalue;
     171  
     172    /* If the return value is a struct and we don't have
     173       a return value address then we need to make one.  */
     174    if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
     175      {
     176        ecif.rvalue = alloca (cif->rtype->size);
     177      }
     178    else
     179      ecif.rvalue = rvalue;
     180  
     181    switch (cif->abi)
     182      {
     183      case FFI_ARCOMPACT:
     184        ffi_call_ARCompact (ffi_prep_args, &ecif, cif->bytes,
     185  			  cif->flags, ecif.rvalue, fn);
     186        break;
     187  
     188      default:
     189        FFI_ASSERT (0);
     190        break;
     191      }
     192  }
     193  
     194  int
     195  ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue,
     196  			     ffi_arg * args)
     197  {
     198    void **arg_area, **p_argv;
     199    ffi_cif *cif = closure->cif;
     200    char *argp = (char *) args;
     201    ffi_type **p_argt;
     202    int i;
     203  
     204    arg_area = (void **) alloca (cif->nargs * sizeof (void *));
     205  
     206    /* handle hidden argument */
     207    if (cif->flags == FFI_TYPE_STRUCT)
     208      {
     209        rvalue = *(void **) argp;
     210        argp += 4;
     211      }
     212  
     213    p_argv = arg_area;
     214  
     215    for (i = 0, p_argt = cif->arg_types; i < cif->nargs;
     216         i++, p_argt++, p_argv++)
     217      {
     218        size_t z;
     219        int alignment;
     220  
     221        /* align alignment to 4 */
     222        alignment = (((*p_argt)->alignment - 1) | 3) + 1;
     223  
     224        /* Align if necessary.  */
     225        if ((alignment - 1) & (unsigned) argp)
     226  	argp = (char *) FFI_ALIGN (argp, alignment);
     227  
     228        z = (*p_argt)->size;
     229        *p_argv = (void *) argp;
     230        argp += z;
     231      }
     232  
     233    (closure->fun) (cif, rvalue, arg_area, closure->user_data);
     234  
     235    return cif->flags;
     236  }
     237  
     238  extern void ffi_closure_ARCompact (void);
     239  
     240  ffi_status
     241  ffi_prep_closure_loc (ffi_closure * closure, ffi_cif * cif,
     242  		      void (*fun) (ffi_cif *, void *, void **, void *),
     243  		      void *user_data, void *codeloc)
     244  {
     245    uint32_t *tramp = (uint32_t *) & (closure->tramp[0]);
     246  
     247    switch (cif->abi)
     248      {
     249      case FFI_ARCOMPACT:
     250        FFI_ASSERT (tramp == codeloc);
     251        tramp[0] = CODE_ENDIAN (0x200a1fc0);	/* mov r8, pcl  */
     252        tramp[1] = CODE_ENDIAN (0x20200f80);	/* j [long imm] */
     253        tramp[2] = CODE_ENDIAN (ffi_closure_ARCompact);
     254        break;
     255  
     256      default:
     257        return FFI_BAD_ABI;
     258      }
     259  
     260    closure->cif = cif;
     261    closure->fun = fun;
     262    closure->user_data = user_data;
     263    cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, BCACHE);
     264  
     265    return FFI_OK;
     266  }