github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/cris/ffi.c (about)

     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) 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 = 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  }