Home | History | Annotate | Download | only in cris
      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 }
    387