(root)/
gcc-13.2.0/
libffi/
src/
cris/
ffi.c
       1  /* -----------------------------------------------------------------------
       2     ffi.c - Copyright (c) 1998 Cygnus Solutions
       3             Copyright (c) 2004 Simon Posnjak
       4  	   Copyright (c) 2005 Axis Communications AB
       5  	   Copyright (C) 2007 Free Software Foundation, Inc.
       6  
       7     CRIS Foreign Function Interface
       8  
       9     Permission is hereby granted, free of charge, to any person obtaining
      10     a copy of this software and associated documentation files (the
      11     ``Software''), to deal in the Software without restriction, including
      12     without limitation the rights to use, copy, modify, merge, publish,
      13     distribute, sublicense, and/or sell copies of the Software, and to
      14     permit persons to whom the Software is furnished to do so, subject to
      15     the following conditions:
      16  
      17     The above copyright notice and this permission notice shall be included
      18     in all copies or substantial portions of the Software.
      19  
      20     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      22     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      23     IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
      24     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      25     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      26     OTHER DEALINGS IN THE SOFTWARE.
      27     ----------------------------------------------------------------------- */
      28  
      29  #include <ffi.h>
      30  #include <ffi_common.h>
      31  
      32  #define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG)
      33  
      34  static ffi_status
      35  initialize_aggregate_packed_struct (ffi_type * arg)
      36  {
      37    ffi_type **ptr;
      38  
      39    FFI_ASSERT (arg != NULL);
      40  
      41    FFI_ASSERT (arg->elements != NULL);
      42    FFI_ASSERT (arg->size == 0);
      43    FFI_ASSERT (arg->alignment == 0);
      44  
      45    ptr = &(arg->elements[0]);
      46  
      47    while ((*ptr) != NULL)
      48      {
      49        if (((*ptr)->size == 0)
      50  	  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
      51  	return FFI_BAD_TYPEDEF;
      52  
      53        FFI_ASSERT (ffi_type_test ((*ptr)));
      54  
      55        arg->size += (*ptr)->size;
      56  
      57        arg->alignment = (arg->alignment > (*ptr)->alignment) ?
      58  	arg->alignment : (*ptr)->alignment;
      59  
      60        ptr++;
      61      }
      62  
      63    if (arg->size == 0)
      64      return FFI_BAD_TYPEDEF;
      65    else
      66      return FFI_OK;
      67  }
      68  
      69  int
      70  ffi_prep_args (char *stack, extended_cif * ecif)
      71  {
      72    unsigned int i;
      73    unsigned int struct_count = 0;
      74    void **p_argv;
      75    char *argp;
      76    ffi_type **p_arg;
      77  
      78    argp = stack;
      79  
      80    p_argv = ecif->avalue;
      81  
      82    for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
      83         (i != 0); i--, p_arg++)
      84      {
      85        size_t z;
      86  
      87        switch ((*p_arg)->type)
      88  	{
      89  	case FFI_TYPE_STRUCT:
      90  	  {
      91  	    z = (*p_arg)->size;
      92  	    if (z <= 4)
      93  	      {
      94  		memcpy (argp, *p_argv, z);
      95  		z = 4;
      96  	      }
      97  	    else if (z <= 8)
      98  	      {
      99  		memcpy (argp, *p_argv, z);
     100  		z = 8;
     101  	      }
     102  	    else
     103  	      {
     104  		unsigned int uiLocOnStack;
     105  		z = sizeof (void *);
     106  		uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
     107  		struct_count = struct_count + (*p_arg)->size;
     108  		*(unsigned int *) argp =
     109  		  (unsigned int) (UINT32 *) (stack + uiLocOnStack);
     110  		memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
     111  	      }
     112  	    break;
     113  	  }
     114  	default:
     115  	  z = (*p_arg)->size;
     116  	  if (z < sizeof (int))
     117  	    {
     118  	      switch ((*p_arg)->type)
     119  		{
     120  		case FFI_TYPE_SINT8:
     121  		  *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
     122  		  break;
     123  
     124  		case FFI_TYPE_UINT8:
     125  		  *(unsigned int *) argp =
     126  		    (unsigned int) *(UINT8 *) (*p_argv);
     127  		  break;
     128  
     129  		case FFI_TYPE_SINT16:
     130  		  *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
     131  		  break;
     132  
     133  		case FFI_TYPE_UINT16:
     134  		  *(unsigned int *) argp =
     135  		    (unsigned int) *(UINT16 *) (*p_argv);
     136  		  break;
     137  
     138  		default:
     139  		  FFI_ASSERT (0);
     140  		}
     141  	      z = sizeof (int);
     142  	    }
     143  	  else if (z == sizeof (int))
     144  	    *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
     145  	  else
     146  	    memcpy (argp, *p_argv, z);
     147  	  break;
     148  	}
     149        p_argv++;
     150        argp += z;
     151      }
     152  
     153    return (struct_count);
     154  }
     155  
     156  ffi_status FFI_HIDDEN
     157  ffi_prep_cif_core (ffi_cif * cif,
     158  	           ffi_abi abi, unsigned int isvariadic,
     159  		   unsigned int nfixedargs, unsigned int ntotalargs,
     160  	           ffi_type * rtype, ffi_type ** atypes)
     161  {
     162    unsigned bytes = 0;
     163    unsigned int i;
     164    ffi_type **ptr;
     165  
     166    FFI_ASSERT (cif != NULL);
     167    FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
     168    FFI_ASSERT(nfixedargs <= ntotalargs);
     169    FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI);
     170  
     171    cif->abi = abi;
     172    cif->arg_types = atypes;
     173    cif->nargs = ntotalargs;
     174    cif->rtype = rtype;
     175  
     176    cif->flags = 0;
     177  
     178    if ((cif->rtype->size == 0)
     179        && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
     180      return FFI_BAD_TYPEDEF;
     181  
     182    FFI_ASSERT_VALID_TYPE (cif->rtype);
     183  
     184    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
     185      {
     186        if (((*ptr)->size == 0)
     187  	  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
     188  	return FFI_BAD_TYPEDEF;
     189  
     190        FFI_ASSERT_VALID_TYPE (*ptr);
     191  
     192        if (((*ptr)->alignment - 1) & bytes)
     193  	bytes = FFI_ALIGN (bytes, (*ptr)->alignment);
     194        if ((*ptr)->type == FFI_TYPE_STRUCT)
     195  	{
     196  	  if ((*ptr)->size > 8)
     197  	    {
     198  	      bytes += (*ptr)->size;
     199  	      bytes += sizeof (void *);
     200  	    }
     201  	  else
     202  	    {
     203  	      if ((*ptr)->size > 4)
     204  		bytes += 8;
     205  	      else
     206  		bytes += 4;
     207  	    }
     208  	}
     209        else
     210  	bytes += STACK_ARG_SIZE ((*ptr)->size);
     211      }
     212  
     213    cif->bytes = bytes;
     214  
     215    return ffi_prep_cif_machdep (cif);
     216  }
     217  
     218  ffi_status
     219  ffi_prep_cif_machdep (ffi_cif * cif)
     220  {
     221    switch (cif->rtype->type)
     222      {
     223      case FFI_TYPE_VOID:
     224      case FFI_TYPE_STRUCT:
     225      case FFI_TYPE_FLOAT:
     226      case FFI_TYPE_DOUBLE:
     227      case FFI_TYPE_SINT64:
     228      case FFI_TYPE_UINT64:
     229        cif->flags = (unsigned) cif->rtype->type;
     230        break;
     231  
     232      default:
     233        cif->flags = FFI_TYPE_INT;
     234        break;
     235      }
     236  
     237    return FFI_OK;
     238  }
     239  
     240  extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
     241  			   extended_cif *,
     242  			   unsigned, unsigned, unsigned *, void (*fn) ())
     243       __attribute__ ((__visibility__ ("hidden")));
     244  
     245  void
     246  ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
     247  {
     248    extended_cif ecif;
     249  
     250    ecif.cif = cif;
     251    ecif.avalue = avalue;
     252  
     253    if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
     254      {
     255        ecif.rvalue = alloca (cif->rtype->size);
     256      }
     257    else
     258      ecif.rvalue = rvalue;
     259  
     260    switch (cif->abi)
     261      {
     262      case FFI_SYSV:
     263        ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
     264  		     cif->flags, ecif.rvalue, fn);
     265        break;
     266      default:
     267        FFI_ASSERT (0);
     268        break;
     269      }
     270  }
     271  
     272  /* Because the following variables are not exported outside libffi, we
     273     mark them hidden.  */
     274  
     275  /* Assembly code for the jump stub.  */
     276  extern const char ffi_cris_trampoline_template[]
     277   __attribute__ ((__visibility__ ("hidden")));
     278  
     279  /* Offset into ffi_cris_trampoline_template of where to put the
     280     ffi_prep_closure_inner function.  */
     281  extern const int ffi_cris_trampoline_fn_offset
     282   __attribute__ ((__visibility__ ("hidden")));
     283  
     284  /* Offset into ffi_cris_trampoline_template of where to put the
     285     closure data.  */
     286  extern const int ffi_cris_trampoline_closure_offset
     287   __attribute__ ((__visibility__ ("hidden")));
     288  
     289  /* This function is sibling-called (jumped to) by the closure
     290     trampoline.  We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
     291     PARAMS[4] to simplify handling of a straddling parameter.  A copy
     292     of R9 is at PARAMS[5] and SP at PARAMS[6].  These parameters are
     293     put at the appropriate place in CLOSURE which is then executed and
     294     the return value is passed back to the caller.  */
     295  
     296  static unsigned long long
     297  ffi_prep_closure_inner (void **params, ffi_closure* closure)
     298  {
     299    char *register_args = (char *) params;
     300    void *struct_ret = params[5];
     301    char *stack_args = params[6];
     302    char *ptr = register_args;
     303    ffi_cif *cif = closure->cif;
     304    ffi_type **arg_types = cif->arg_types;
     305  
     306    /* Max room needed is number of arguments as 64-bit values.  */
     307    void **avalue = alloca (closure->cif->nargs * sizeof(void *));
     308    int i;
     309    int doing_regs;
     310    long long llret = 0;
     311  
     312    /* Find the address of each argument.  */
     313    for (i = 0, doing_regs = 1; i < cif->nargs; i++)
     314      {
     315        /* Types up to and including 8 bytes go by-value.  */
     316        if (arg_types[i]->size <= 4)
     317  	{
     318  	  avalue[i] = ptr;
     319  	  ptr += 4;
     320  	}
     321        else if (arg_types[i]->size <= 8)
     322  	{
     323  	  avalue[i] = ptr;
     324  	  ptr += 8;
     325  	}
     326        else
     327  	{
     328  	  FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
     329  
     330  	  /* Passed by-reference, so copy the pointer.  */
     331  	  avalue[i] = *(void **) ptr;
     332  	  ptr += 4;
     333  	}
     334  
     335        /* If we've handled more arguments than fit in registers, start
     336  	 looking at the those passed on the stack.  Step over the
     337  	 first one if we had a straddling parameter.  */
     338        if (doing_regs && ptr >= register_args + 4*4)
     339  	{
     340  	  ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
     341  	  doing_regs = 0;
     342  	}
     343      }
     344  
     345    /* Invoke the closure.  */
     346    (closure->fun) (cif,
     347  
     348  		  cif->rtype->type == FFI_TYPE_STRUCT
     349  		  /* The caller allocated space for the return
     350  		     structure, and passed a pointer to this space in
     351  		     R9.  */
     352  		  ? struct_ret
     353  
     354  		  /* We take advantage of being able to ignore that
     355  		     the high part isn't set if the return value is
     356  		     not in R10:R11, but in R10 only.  */
     357  		  : (void *) &llret,
     358  
     359  		  avalue, closure->user_data);
     360  
     361    return llret;
     362  }
     363  
     364  /* API function: Prepare the trampoline.  */
     365  
     366  ffi_status
     367  ffi_prep_closure_loc (ffi_closure* closure,
     368  		      ffi_cif* cif,
     369  		      void (*fun)(ffi_cif *, void *, void **, void*),
     370  		      void *user_data,
     371  		      void *codeloc)
     372  {
     373    void *innerfn = ffi_prep_closure_inner;
     374    FFI_ASSERT (cif->abi == FFI_SYSV);
     375    closure->cif  = cif;
     376    closure->user_data = user_data;
     377    closure->fun  = fun;
     378    memcpy (closure->tramp, ffi_cris_trampoline_template,
     379  	  FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
     380    memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
     381  	  &innerfn, sizeof (void *));
     382    memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
     383  	  &codeloc, sizeof (void *));
     384  
     385    return FFI_OK;
     386  }