Back to index

plt-scheme  4.2.1
ffi.c
Go to the documentation of this file.
00001 /* -----------------------------------------------------------------------
00002    ffi.c - Copyright (c) 2004  Renesas Technology
00003    
00004    M32R Foreign Function Interface 
00005 
00006    Permission is hereby granted, free of charge, to any person obtaining
00007    a copy of this software and associated documentation files (the
00008    ``Software''), to deal in the Software without restriction, including
00009    without limitation the rights to use, copy, modify, merge, publish,
00010    distribute, sublicense, and/or sell copies of the Software, and to
00011    permit persons to whom the Software is furnished to do so, subject to
00012    the following conditions:
00013 
00014    The above copyright notice and this permission notice shall be included
00015    in all copies or substantial portions of the Software.
00016 
00017    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00019    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00020    IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
00021    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00022    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00023    OTHER DEALINGS IN THE SOFTWARE.
00024    ----------------------------------------------------------------------- */
00025 
00026 #include <ffi.h>
00027 #include <ffi_common.h>
00028 
00029 #include <stdlib.h>
00030 
00031 /* ffi_prep_args is called by the assembly routine once stack
00032    space has been allocated for the function's arguments.  */
00033 
00034 void ffi_prep_args(char *stack, extended_cif *ecif)
00035 {
00036   unsigned int i;
00037   int tmp;
00038   unsigned int avn;
00039   void **p_argv;
00040   char *argp;
00041   ffi_type **p_arg;
00042 
00043   tmp = 0;
00044   argp = stack;
00045 
00046   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
00047     {
00048       *(void **) argp = ecif->rvalue;
00049       argp += 4;
00050     }
00051 
00052   avn = ecif->cif->nargs;
00053   p_argv = ecif->avalue;
00054 
00055   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
00056        (i != 0) && (avn != 0);
00057        i--, p_arg++)
00058     {
00059       size_t z;
00060 
00061       /* Align if necessary.  */
00062       if (((*p_arg)->alignment - 1) & (unsigned) argp)
00063        argp = (char *) ALIGN (argp, (*p_arg)->alignment);
00064 
00065       if (avn != 0) 
00066        {
00067          avn--;
00068          z = (*p_arg)->size;
00069          if (z < sizeof (int))
00070            {
00071              z = sizeof (int);
00072 
00073              switch ((*p_arg)->type)
00074               {
00075               case FFI_TYPE_SINT8:
00076                 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
00077                 break;
00078                 
00079               case FFI_TYPE_UINT8:
00080                 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
00081                 break;
00082                 
00083               case FFI_TYPE_SINT16:
00084                 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
00085                 break;
00086                 
00087               case FFI_TYPE_UINT16:
00088                 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
00089                 break;
00090                 
00091               case FFI_TYPE_STRUCT:
00092                 z = (*p_arg)->size;
00093                 if ((*p_arg)->alignment != 1)
00094                   memcpy (argp, *p_argv, z);
00095                 else
00096                   memcpy (argp + 4 - z, *p_argv, z);
00097                 z = sizeof (int);
00098                 break;
00099 
00100               default:
00101                 FFI_ASSERT(0);
00102               }
00103            }
00104          else if (z == sizeof (int))
00105            {
00106               *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
00107            }
00108          else
00109            {
00110              if ((*p_arg)->type == FFI_TYPE_STRUCT)
00111                {
00112                 if (z > 8)
00113                   {
00114                     *(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
00115                     z = sizeof(void *);
00116                   }
00117                 else
00118                   {
00119                      memcpy(argp, *p_argv, z);
00120                     z = 8;
00121                   }
00122                }
00123              else
00124                {
00125                 /* Double or long long 64bit.  */
00126                  memcpy (argp, *p_argv, z);
00127                }
00128            }
00129          p_argv++;
00130          argp += z;
00131        }
00132     }
00133   
00134   return;
00135 }
00136 
00137 /* Perform machine dependent cif processing.  */
00138 ffi_status
00139 ffi_prep_cif_machdep(ffi_cif *cif)
00140 {
00141   /* Set the return type flag.  */
00142   switch (cif->rtype->type)
00143     {
00144     case FFI_TYPE_VOID:
00145       cif->flags = (unsigned) cif->rtype->type;
00146       break;
00147 
00148     case FFI_TYPE_STRUCT:
00149       if (cif->rtype->size <= 4)
00150        cif->flags = FFI_TYPE_INT;
00151 
00152       else if (cif->rtype->size <= 8)
00153        cif->flags = FFI_TYPE_DOUBLE;
00154 
00155       else
00156        cif->flags = (unsigned) cif->rtype->type;
00157       break;
00158 
00159     case FFI_TYPE_SINT64:
00160     case FFI_TYPE_UINT64:
00161     case FFI_TYPE_DOUBLE:
00162       cif->flags = FFI_TYPE_DOUBLE;
00163       break;
00164 
00165     case FFI_TYPE_FLOAT:
00166     default:
00167       cif->flags = FFI_TYPE_INT;
00168       break;
00169     }
00170 
00171   return FFI_OK;
00172 }
00173 
00174 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
00175                        unsigned, unsigned, unsigned *, void (*fn)());
00176 
00177 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
00178 {
00179   extended_cif ecif;
00180 
00181   ecif.cif = cif;
00182   ecif.avalue = avalue;
00183   
00184   /* If the return value is a struct and we don't have
00185      a return value address then we need to make one.  */
00186   if ((rvalue == NULL) && 
00187       (cif->rtype->type == FFI_TYPE_STRUCT))
00188     {
00189       ecif.rvalue = alloca (cif->rtype->size);
00190     }
00191   else
00192     ecif.rvalue = rvalue;    
00193   
00194   switch (cif->abi) 
00195     {
00196     case FFI_SYSV:
00197       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
00198                   cif->flags, ecif.rvalue, fn);
00199       if (cif->rtype->type == FFI_TYPE_STRUCT)
00200        {
00201          int size = cif->rtype->size;
00202          int align = cif->rtype->alignment;
00203 
00204          if (size < 4)
00205            {
00206              if (align == 1)
00207                *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
00208            }
00209          else if (4 < size && size < 8)
00210            {
00211              if (align == 1)
00212               {
00213                 memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
00214               }
00215              else if (align == 2)
00216               {
00217                 if (size & 1)
00218                   size += 1;
00219 
00220                 if (size != 8)
00221                   memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
00222               }
00223            }
00224        }
00225       break;
00226 
00227     default:
00228       FFI_ASSERT(0);
00229       break;
00230     }
00231 }