(root)/
gcc-13.2.0/
libffi/
src/
or1k/
ffi.c
       1  /* -----------------------------------------------------------------------
       2     ffi.c - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de>
       3  
       4     OpenRISC 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,
      18     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      19     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      20     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      21     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      22     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      24     DEALINGS IN THE SOFTWARE.
      25     ----------------------------------------------------------------------- */
      26  
      27  #include <ffi.h>
      28  #include "ffi_common.h"
      29  
      30  /* ffi_prep_args is called by the assembly routine once stack space
      31     has been allocated for the function's arguments */
      32  
      33  void* ffi_prep_args(char *stack, extended_cif *ecif)
      34  {
      35    char *stacktemp = stack;
      36    int i, s;
      37    ffi_type **arg;
      38    int count = 0;
      39    int nfixedargs;
      40    
      41    nfixedargs = ecif->cif->nfixedargs;
      42    arg = ecif->cif->arg_types;
      43    void **argv = ecif->avalue;
      44  
      45    if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
      46      {
      47        *(void **) stack = ecif->rvalue;
      48        stack += 4;
      49        count = 4;
      50      } 
      51    for(i=0; i<ecif->cif->nargs; i++)
      52    {
      53  
      54      /* variadic args are saved on stack */
      55      if ((nfixedargs == 0) && (count < 24))
      56        {
      57          count = 24;
      58          stack = stacktemp + 24;        
      59        }
      60      nfixedargs--;
      61  
      62      s = 4;
      63      switch((*arg)->type) 
      64        {
      65        case FFI_TYPE_STRUCT:
      66          *(void **)stack = *argv;
      67          break;
      68  
      69        case FFI_TYPE_SINT8:
      70          *(signed int *) stack = (signed int)*(SINT8 *)(* argv);
      71          break;
      72  
      73        case FFI_TYPE_UINT8:
      74          *(unsigned int *) stack = (unsigned int)*(UINT8 *)(* argv);
      75          break;
      76  
      77        case FFI_TYPE_SINT16:
      78          *(signed int *) stack = (signed int)*(SINT16 *)(* argv);
      79          break;
      80  
      81        case FFI_TYPE_UINT16:
      82          *(unsigned int *) stack = (unsigned int)*(UINT16 *)(* argv);
      83          break;
      84  
      85        case FFI_TYPE_SINT32:
      86        case FFI_TYPE_UINT32:
      87        case FFI_TYPE_FLOAT:
      88        case FFI_TYPE_POINTER:
      89          *(int *)stack = *(int*)(*argv);
      90          break;
      91  
      92        default: /* 8 byte types */
      93          if (count == 20) /* never split arguments */
      94            {
      95              stack += 4;
      96              count += 4;
      97            }  
      98          s = (*arg)->size;
      99          memcpy(stack, *argv, s);
     100          break;
     101        }
     102  
     103      stack += s;
     104      count += s;
     105      argv++;
     106      arg++;
     107    }
     108    return stacktemp + ((count>24)?24:0);
     109  }
     110  
     111  extern void ffi_call_SYSV(unsigned,
     112                            extended_cif *,
     113                            void *(*)(int *, extended_cif *),
     114                            unsigned *,
     115                            void (*fn)(void),
     116                            unsigned);
     117  
     118  
     119  void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
     120  {
     121    int i;
     122    int size;
     123    ffi_type **arg;
     124  
     125    /* Calculate size to allocate on stack */
     126  
     127    for(i = 0, arg = cif->arg_types, size=0; i < cif->nargs; i++, arg++)
     128      {
     129        if ((*arg)->type == FFI_TYPE_STRUCT)
     130          size += 4;
     131        else
     132        if ((*arg)->size <= 4)
     133          size += 4;
     134        else
     135          size += 8;
     136      }
     137  
     138    /* for variadic functions more space is needed on the stack */
     139    if (cif->nargs != cif->nfixedargs)
     140      size += 24;
     141  
     142    if (cif->rtype->type == FFI_TYPE_STRUCT)
     143      size += 4;
     144  
     145  
     146    extended_cif ecif;
     147    ecif.cif = cif;
     148    ecif.avalue = avalue;
     149    ecif.rvalue = rvalue;
     150  
     151    switch (cif->abi) 
     152    {
     153      case FFI_SYSV:
     154        ffi_call_SYSV(size, &ecif, ffi_prep_args, rvalue, fn, cif->flags);
     155        break;
     156      default:
     157        FFI_ASSERT(0);
     158        break;
     159    }
     160  }
     161  
     162  
     163  void ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5, 
     164                        unsigned long r6, unsigned long r7, unsigned long r8)
     165  {
     166    register int *sp __asm__ ("r17");
     167    register int *r13 __asm__ ("r13");
     168  
     169    ffi_closure* closure = (ffi_closure*) r13;
     170    char *stack_args = sp;
     171  
     172    /* Lay the register arguments down in a continuous chunk of memory.  */
     173    unsigned register_args[6] =
     174      { r3, r4, r5, r6, r7, r8 };
     175  
     176    /* Pointer to a struct return value.  */
     177    void *struct_rvalue = (void *) r3;
     178  
     179    ffi_cif *cif = closure->cif;
     180    ffi_type **arg_types = cif->arg_types;
     181    void **avalue = alloca (cif->nargs * sizeof(void *));
     182    char *ptr = (char *) register_args;
     183    int count = 0;
     184    int nfixedargs = cif->nfixedargs;
     185    int i;
     186  
     187    /* preserve struct type return pointer passing */
     188  
     189    if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) 
     190    {
     191      ptr += 4;
     192      count = 4;
     193    }
     194  
     195    /* Find the address of each argument.  */
     196    for (i = 0; i < cif->nargs; i++)
     197      {
     198  
     199        /* variadic args are saved on stack */
     200        if ((nfixedargs == 0) && (count < 24))
     201          {
     202            ptr = stack_args;
     203            count = 24;
     204          }
     205        nfixedargs--;
     206  
     207        switch (arg_types[i]->type)
     208          {
     209          case FFI_TYPE_SINT8:
     210          case FFI_TYPE_UINT8:
     211            avalue[i] = ptr + 3;
     212            break;
     213  
     214          case FFI_TYPE_SINT16:
     215          case FFI_TYPE_UINT16:
     216            avalue[i] = ptr + 2;
     217            break;
     218  
     219          case FFI_TYPE_SINT32:
     220          case FFI_TYPE_UINT32:
     221          case FFI_TYPE_FLOAT:
     222          case FFI_TYPE_POINTER:
     223            avalue[i] = ptr;
     224            break;
     225  
     226          case FFI_TYPE_STRUCT:
     227            avalue[i] = *(void**)ptr;
     228            break;
     229  
     230          default:
     231            /* 8-byte values  */
     232  
     233            /* arguments are never splitted */
     234            if (ptr == &register_args[5])
     235              ptr = stack_args;
     236            avalue[i] = ptr;
     237            ptr += 4;
     238            count += 4;
     239            break;
     240          }
     241        ptr += 4;
     242        count += 4;
     243  
     244        /* If we've handled more arguments than fit in registers,
     245           start looking at the those passed on the stack.  */
     246  
     247        if (count == 24)
     248          ptr = stack_args;
     249      }
     250  
     251    if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
     252      {
     253        (closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
     254      } else
     255      {
     256        long long rvalue;
     257        (closure->fun) (cif, &rvalue, avalue, closure->user_data);
     258        if (cif->rtype)
     259          asm ("l.ori r12, %0, 0x0\n l.lwz r11, 0(r12)\n l.lwz r12, 4(r12)" : : "r" (&rvalue));      
     260      }
     261  }
     262  
     263  
     264  ffi_status
     265  ffi_prep_closure_loc (ffi_closure* closure,
     266                        ffi_cif* cif,
     267                        void (*fun)(ffi_cif*,void*,void**,void*),
     268                        void *user_data,
     269                        void *codeloc)
     270  {
     271    unsigned short *tramp = (unsigned short *) closure->tramp;
     272    unsigned long fn = (unsigned long) ffi_closure_SYSV;
     273    unsigned long cls = (unsigned long) codeloc;
     274  
     275    if (cif->abi != FFI_SYSV)
     276      return FFI_BAD_ABI;
     277  
     278    closure->cif = cif;
     279    closure->user_data = user_data;
     280    closure->fun = fun;
     281  
     282    /* write pointers to temporary registers */
     283    tramp[0] = (0x6 << 10) | (13 << 5); /* l.movhi r13, ... */
     284    tramp[1] = cls >> 16;
     285    tramp[2] = (0x2a << 10) | (13 << 5) | 13; /* l.ori r13, r13, ... */
     286    tramp[3] = cls & 0xFFFF;
     287  
     288    tramp[4] = (0x6 << 10) | (15 << 5); /* l.movhi r15, ... */
     289    tramp[5] = fn >> 16;
     290    tramp[6] = (0x2a << 10) | (15 << 5) | 15; /* l.ori r15, r15 ... */
     291    tramp[7] = fn & 0xFFFF;
     292  
     293    tramp[8] = (0x11 << 10); /* l.jr r15 */
     294    tramp[9] = 15 << 11;
     295  
     296    tramp[10] = (0x2a << 10) | (17 << 5) | 1; /* l.ori r17, r1, ... */
     297    tramp[11] = 0x0;
     298  
     299    return FFI_OK;
     300  }
     301  
     302  
     303  ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
     304  {
     305    cif->flags = 0;
     306  	
     307    /* structures are returned as pointers */
     308    if (cif->rtype->type == FFI_TYPE_STRUCT)
     309      cif->flags = FFI_TYPE_STRUCT;
     310    else 
     311    if (cif->rtype->size > 4)
     312      cif->flags = FFI_TYPE_UINT64;
     313  
     314    cif->nfixedargs = cif->nargs;
     315  
     316    return FFI_OK;
     317  }
     318  
     319  
     320  ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
     321           unsigned int nfixedargs, unsigned int ntotalargs)
     322  {
     323    ffi_status status;
     324  
     325    status = ffi_prep_cif_machdep (cif);
     326    cif->nfixedargs = nfixedargs;
     327    return status;
     328  }