(root)/
gcc-13.2.0/
libffi/
src/
vax/
ffi.c
       1  /*
       2   * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
       3   *
       4   * Permission is hereby granted, free of charge, to any person obtaining
       5   * a copy of this software and associated documentation files (the
       6   * ``Software''), to deal in the Software without restriction, including
       7   * without limitation the rights to use, copy, modify, merge, publish,
       8   * distribute, sublicense, and/or sell copies of the Software, and to
       9   * permit persons to whom the Software is furnished to do so, subject to
      10   * the following conditions:
      11   * 
      12   * The above copyright notice and this permission notice shall be included
      13   * in all copies or substantial portions of the Software.
      14   * 
      15   * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
      16   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      17   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      18   * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
      19   * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
      20   * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      21   * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      22   */
      23  
      24  /*
      25   * vax Foreign Function Interface
      26   *
      27   * This file attempts to provide all the FFI entry points which can reliably
      28   * be implemented in C.
      29   */
      30  
      31  #include <ffi.h>
      32  #include <ffi_common.h>
      33  
      34  #include <stdlib.h>
      35  #include <unistd.h>
      36  
      37  #define CIF_FLAGS_CHAR		1	/* for struct only */
      38  #define CIF_FLAGS_SHORT		2	/* for struct only */
      39  #define CIF_FLAGS_INT		4
      40  #define CIF_FLAGS_DINT		8
      41  
      42  /*
      43   * Foreign Function Interface API
      44   */
      45  
      46  void ffi_call_elfbsd (extended_cif *, unsigned, unsigned, void *,
      47  		       void (*) ());
      48  void *ffi_prep_args (extended_cif *ecif, void *stack);
      49  
      50  void *
      51  ffi_prep_args (extended_cif *ecif, void *stack)
      52  {
      53    unsigned int i;
      54    void **p_argv;
      55    char *argp;
      56    ffi_type **p_arg;
      57    void *struct_value_ptr;
      58  
      59    argp = stack;
      60  
      61    if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
      62        && !ecif->cif->flags)
      63      struct_value_ptr = ecif->rvalue;
      64    else
      65      struct_value_ptr = NULL;
      66  
      67    p_argv = ecif->avalue;
      68  
      69    for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
      70         i != 0;
      71         i--, p_arg++)
      72      {
      73        size_t z;
      74  
      75        z = (*p_arg)->size;
      76        if (z < sizeof (int))
      77  	{
      78  	  switch ((*p_arg)->type)
      79  	    {
      80  	    case FFI_TYPE_SINT8:
      81  	      *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
      82  	      break;
      83  
      84  	    case FFI_TYPE_UINT8:
      85  	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
      86  	      break;
      87  
      88  	    case FFI_TYPE_SINT16:
      89  	      *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
      90  	      break;
      91  
      92  	    case FFI_TYPE_UINT16:
      93  	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
      94  	      break;
      95  
      96  	    case FFI_TYPE_STRUCT:
      97  	      memcpy (argp, *p_argv, z);
      98  	      break;
      99  
     100  	    default:
     101  	      FFI_ASSERT (0);
     102  	    }
     103  	  z = sizeof (int);
     104  	}
     105        else
     106  	{
     107  	  memcpy (argp, *p_argv, z);
     108  
     109  	  /* Align if necessary.  */
     110  	  if ((sizeof(int) - 1) & z)
     111  	    z = FFI_ALIGN(z, sizeof(int));
     112  	}
     113  
     114        p_argv++;
     115        argp += z;
     116      }
     117  
     118    return struct_value_ptr;
     119  }
     120  
     121  ffi_status
     122  ffi_prep_cif_machdep (ffi_cif *cif)
     123  {
     124    /* Set the return type flag */
     125    switch (cif->rtype->type)
     126      {
     127      case FFI_TYPE_VOID:
     128        cif->flags = 0;
     129        break;
     130  
     131      case FFI_TYPE_STRUCT:
     132        if (cif->rtype->elements[0]->type == FFI_TYPE_STRUCT &&
     133  	  cif->rtype->elements[1])
     134  	{
     135  	  cif->flags = 0;
     136  	  break;
     137  	}
     138  
     139        if (cif->rtype->size == sizeof (char))
     140  	cif->flags = CIF_FLAGS_CHAR;
     141        else if (cif->rtype->size == sizeof (short))
     142  	cif->flags = CIF_FLAGS_SHORT;
     143        else if (cif->rtype->size == sizeof (int))
     144  	cif->flags = CIF_FLAGS_INT;
     145        else if (cif->rtype->size == 2 * sizeof (int))
     146  	cif->flags = CIF_FLAGS_DINT;
     147        else
     148  	cif->flags = 0;
     149        break;
     150  
     151      default:
     152        if (cif->rtype->size <= sizeof (int))
     153  	cif->flags = CIF_FLAGS_INT;
     154        else
     155  	cif->flags = CIF_FLAGS_DINT;
     156        break;
     157      }
     158  
     159    return FFI_OK;
     160  }
     161  
     162  void
     163  ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
     164  {
     165    extended_cif ecif;
     166  
     167    ecif.cif = cif;
     168    ecif.avalue = avalue;
     169  
     170    /* If the return value is a struct and we don't have a return value
     171       address then we need to make one.  */
     172  
     173    if (rvalue == NULL
     174        && cif->rtype->type == FFI_TYPE_STRUCT
     175        && cif->flags == 0)
     176      ecif.rvalue = alloca (cif->rtype->size);
     177    else
     178      ecif.rvalue = rvalue;
     179  
     180    switch (cif->abi)
     181      {
     182      case FFI_ELFBSD:
     183        ffi_call_elfbsd (&ecif, cif->bytes, cif->flags, ecif.rvalue, fn);
     184        break;
     185  
     186      default:
     187        FFI_ASSERT (0);
     188        break;
     189      }
     190  }
     191  
     192  /*
     193   * Closure API
     194   */
     195  
     196  void ffi_closure_elfbsd (void);
     197  void ffi_closure_struct_elfbsd (void);
     198  unsigned int ffi_closure_elfbsd_inner (ffi_closure *, void *, char *);
     199  
     200  static void
     201  ffi_prep_closure_elfbsd (ffi_cif *cif, void **avalue, char *stackp)
     202  {
     203    unsigned int i;
     204    void **p_argv;
     205    ffi_type **p_arg;
     206  
     207    p_argv = avalue;
     208  
     209    for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++)
     210      {
     211        size_t z;
     212  
     213        z = (*p_arg)->size;
     214        *p_argv = stackp;
     215  
     216        /* Align if necessary */
     217        if ((sizeof (int) - 1) & z)
     218  	z = FFI_ALIGN(z, sizeof (int));
     219  
     220        p_argv++;
     221        stackp += z;
     222      }
     223  }
     224  
     225  unsigned int
     226  ffi_closure_elfbsd_inner (ffi_closure *closure, void *resp, char *stack)
     227  {
     228    ffi_cif *cif;
     229    void **arg_area;
     230  
     231    cif = closure->cif;
     232    arg_area = (void **) alloca (cif->nargs * sizeof (void *));
     233  
     234    ffi_prep_closure_elfbsd (cif, arg_area, stack);
     235  
     236    (closure->fun) (cif, resp, arg_area, closure->user_data);
     237  
     238    return cif->flags;
     239  }
     240  
     241  ffi_status
     242  ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif,
     243  		      void (*fun)(ffi_cif *, void *, void **, void *),
     244  		      void *user_data, void *codeloc)
     245  {
     246    char *tramp = (char *) codeloc;
     247    void *fn;
     248  
     249    FFI_ASSERT (cif->abi == FFI_ELFBSD);
     250  
     251    /* entry mask */
     252    *(unsigned short *)(tramp + 0) = 0x0000;
     253    /* movl #closure, r0 */
     254    tramp[2] = 0xd0;
     255    tramp[3] = 0x8f;
     256    *(unsigned int *)(tramp + 4) = (unsigned int) closure;
     257    tramp[8] = 0x50;
     258  
     259    if (cif->rtype->type == FFI_TYPE_STRUCT
     260        && !cif->flags)
     261      fn = &ffi_closure_struct_elfbsd;
     262    else
     263      fn = &ffi_closure_elfbsd;
     264  
     265    /* jmpl #fn */
     266    tramp[9] = 0x17;
     267    tramp[10] = 0xef;
     268    *(unsigned int *)(tramp + 11) = (unsigned int)fn + 2 -
     269  				  (unsigned int)tramp - 9 - 6;
     270  
     271    closure->cif = cif;
     272    closure->user_data = user_data;
     273    closure->fun = fun;
     274  
     275    return FFI_OK;
     276  }