Moved arm files
authorgreen <green>
Sun, 22 Apr 2001 18:08:11 +0000 (18:08 +0000)
committergreen <green>
Sun, 22 Apr 2001 18:08:11 +0000 (18:08 +0000)
libffi/arm/ffi.c [new file with mode: 0644]
libffi/arm/sysv.S [new file with mode: 0644]

diff --git a/libffi/arm/ffi.c b/libffi/arm/ffi.c
new file mode 100644 (file)
index 0000000..0ede742
--- /dev/null
@@ -0,0 +1,183 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998  Cygnus Solutions
+   
+   ARM Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register int tmp;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  tmp = 0;
+  argp = stack;
+
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
+    *(void **) argp = ecif->rvalue;
+    argp += 4;
+  }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0) && (avn != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp) {
+       argp = (char *) ALIGN(argp, (*p_arg)->alignment);
+      }
+
+      if (avn != 0) 
+       {
+         avn--;
+         z = (*p_arg)->size;
+         if (z < sizeof(int))
+           {
+             z = sizeof(int);
+             switch ((*p_arg)->type)
+               {
+               case FFI_TYPE_SINT8:
+                 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT8:
+                 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_SINT16:
+                 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT16:
+                 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_STRUCT:
+                 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+                 break;
+
+               default:
+                 FFI_ASSERT(0);
+               }
+           }
+         else if (z == sizeof(int))
+           {
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+           }
+         else
+           {
+             memcpy(argp, *p_argv, z);
+           }
+         p_argv++;
+         argp += z;
+       }
+    }
+  
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
+                         /*@out@*/ extended_cif *, 
+                         unsigned, unsigned, 
+                         /*@out@*/ unsigned *, 
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
diff --git a/libffi/arm/sysv.S b/libffi/arm/sysv.S
new file mode 100644 (file)
index 0000000..84744d7
--- /dev/null
@@ -0,0 +1,111 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1998 Cygnus Solutions
+   
+   ARM Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+       
+.text
+
+       # a1:   ffi_prep_args
+       # a2:   &ecif
+       # a3:   cif->bytes
+       # a4:   fig->flags
+       # sp+0: ecif.rvalue
+       # sp+4: fn
+
+       # This assumes we are using gas.
+ENTRY(ffi_call_SYSV)
+       # Save registers
+        stmfd sp!, {a1-a4, fp, lr}
+       mov   fp, sp
+
+       # Make room for all of the new args.
+       sub   sp, fp, a3
+
+       # Place all of the ffi_prep_args in position
+       mov   ip, a1
+       mov   a1, sp
+       #     a2 already set
+
+       # And call
+       mov   lr, pc
+       mov   pc, ip
+
+       # move first 4 parameters in registers
+       ldr   a1, [sp, #0]
+       ldr   a2, [sp, #4]
+       ldr   a3, [sp, #8]
+        ldr   a4, [sp, #12]
+
+       # and adjust stack
+       ldr   ip, [fp, #8]
+        cmp   ip, #16
+       movge ip, #16
+        add   sp, sp, ip
+
+       # call function
+       mov   lr, pc
+       ldr   pc, [fp, #28]
+
+       # Remove the space we pushed for the args
+       mov   sp, fp
+
+       # Load a3 with the pointer to storage for the return value
+       ldr   a3, [sp, #24]
+
+       # Load a4 with the return type code 
+       ldr   a4, [sp, #12]
+
+       # If the return value pointer is NULL, assume no return value.
+       cmp   a3, #0
+       beq   epilogue
+
+# return INT
+       cmp   a4, #FFI_TYPE_INT
+       streq a1, [a3]
+       beq   epilogue
+
+# return FLOAT
+       cmp     a4, #FFI_TYPE_FLOAT
+       stfeqs  f0, [a3]
+       beq     epilogue
+
+# return DOUBLE or LONGDOUBLE
+       cmp     a4, #FFI_TYPE_DOUBLE
+       stfeqd  f0, [a3]
+
+epilogue:
+        ldmfd sp!, {a1-a4, fp, pc}
+
+.ffi_call_SYSV_end:
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+