OSDN Git Service

Port to sparc 32 and 64 Linux.
authorgreen <green@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 17 Apr 2000 02:15:32 +0000 (02:15 +0000)
committergreen <green@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 17 Apr 2000 02:15:32 +0000 (02:15 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@33196 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
libffi/ChangeLog
libffi/Makefile.am
libffi/Makefile.in
libffi/configure
libffi/configure.in
libffi/include/ffi.h.in
libffi/src/ffitest.c
libffi/src/prep_cif.c
libffi/src/sparc/ffi.c
libffi/src/sparc/v8.S
libffi/src/sparc/v9.S [new file with mode: 0644]
libffi/src/types.c

index 6376b75..037726e 100644 (file)
@@ -1,3 +1,38 @@
+2000-04-14  Jakub Jelinek  <jakub@redhat.com>
+
+        * include/ffi.h.in (SPARC64): Define for 64bit SPARC builds.
+       Set SPARC FFI_DEFAULT_ABI based on SPARC64 define.
+       * src/sparc/ffi.c (ffi_prep_args_v8): Renamed from ffi_prep_args.
+       Replace all void * sizeofs with sizeof(int).
+       Only compare type with FFI_TYPE_LONGDOUBLE if LONGDOUBLE is
+       different than DOUBLE.
+       Remove FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases (handled elsewhere).
+       (ffi_prep_args_v9): New function.
+       (ffi_prep_cif_machdep): Handle V9 ABI and long long on V8.
+       (ffi_V9_return_struct): New function.
+       (ffi_call): Handle FFI_V9 ABI from 64bit code and FFI_V8 ABI from
+       32bit code (not yet cross-arch calls).
+       * src/sparc/v8.S: Add struct return delay nop.
+       Handle long long.
+       * src/sparc/v9.S: New file.
+       * src/prep_cif.c (ffi_prep_cif): Return structure pointer
+       is used on sparc64 only for structures larger than 32 bytes.
+       Pass by reference for structures is done for structure arguments
+       larger than 16 bytes.
+       * src/ffitest.c (main): Use 64bit rint on sparc64.
+       Run long long tests on sparc.
+       * src/types.c (FFI_TYPE_POINTER): Pointer is 64bit on alpha and
+       sparc64.
+       (FFI_TYPE_LONGDOUBLE): long double is 128 bit aligned to 128 bits
+       on sparc64.
+       * configure.in (sparc-*-linux*): New supported target.
+       (sparc64-*-linux*): Likewise.
+       * configure: Rebuilt.
+       * Makefile.am: Add v9.S to SPARC files.
+       * Makefile.in: Likewise.
+       (LINK): Surround $(CCLD) into double quotes, so that multilib
+       compiles work correctly.
+
 2000-04-04  Alexandre Petit-Bianco  <apbianco@cygnus.com>
 
        * configure: Rebuilt.
index cbb0561..8f51eb3 100644 (file)
@@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = cygnus
 
 EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
                src/mips/n32.s src/mips/o32.S src/mips/o32.s \
-               src/sparc/ffi.c src/sparc/v8.S \
+               src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S \
                src/x86/ffi.c src/x86/sysv.S \
                src/alpha/ffi.c src/alpha/osf.S \
                src/m68k/ffi.c src/m68k/sysv.S \
@@ -40,7 +40,7 @@ ffitest_LDADD = libffi.la
 TARGET_SRC_MIPS_GCC = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
 TARGET_SRC_MIPS_SGI = src/mips/ffi.c src/mips/o32.s src/mips/n32.s
 TARGET_SRC_X86 = src/x86/ffi.c src/x86/sysv.S
-TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S
+TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
 TARGET_SRC_ALPHA = src/alpha/ffi.c src/alpha/osf.S
 TARGET_SRC_IA64 = src/ia64/ffi.c src/ia64/unix.S
 TARGET_SRC_M68K = src/m68k/ffi.c src/m68k/sysv.S
index 2bf459c..078daf4 100644 (file)
@@ -84,7 +84,7 @@ AUTOMAKE_OPTIONS = cygnus
 
 EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
                src/mips/n32.s src/mips/o32.S src/mips/o32.s \
-               src/sparc/ffi.c src/sparc/v8.S \
+               src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S \
                src/x86/ffi.c src/x86/sysv.S \
                src/alpha/ffi.c src/alpha/osf.S \
                src/m68k/ffi.c src/m68k/sysv.S \
@@ -115,7 +115,7 @@ ffitest_LDADD = libffi.la
 TARGET_SRC_MIPS_GCC = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
 TARGET_SRC_MIPS_SGI = src/mips/ffi.c src/mips/o32.s src/mips/n32.s
 TARGET_SRC_X86 = src/x86/ffi.c src/x86/sysv.S
-TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S
+TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S 
 TARGET_SRC_ALPHA = src/alpha/ffi.c src/alpha/osf.S
 TARGET_SRC_IA64 = src/ia64/ffi.c src/ia64/unix.S
 TARGET_SRC_M68K = src/m68k/ffi.c src/m68k/sysv.S
@@ -164,7 +164,7 @@ libffi_la_LIBADD =
 @POWERPC_TRUE@am_libffi_la_OBJECTS =  debug.lo prep_cif.lo types.lo \
 @POWERPC_TRUE@raw_api.lo java_raw_api.lo ffi.lo sysv.lo
 @SPARC_TRUE@am_libffi_la_OBJECTS =  debug.lo prep_cif.lo types.lo \
-@SPARC_TRUE@raw_api.lo java_raw_api.lo ffi.lo v8.lo
+@SPARC_TRUE@raw_api.lo java_raw_api.lo ffi.lo v8.lo v9.lo
 @X86_TRUE@am_libffi_la_OBJECTS =  debug.lo prep_cif.lo types.lo \
 @X86_TRUE@raw_api.lo java_raw_api.lo ffi.lo sysv.lo
 libffi_la_OBJECTS =  $(am_libffi_la_OBJECTS)
@@ -179,7 +179,7 @@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CF
 LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 CFLAGS = @CFLAGS@
 CCLD = $(CC)
-LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) --mode=link "$(CCLD)" $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
 DIST_SOURCES =  $(libffi_la_SOURCES) $(ffitest_SOURCES)
 DIST_COMMON =  README ./stamp-h.in ChangeLog Makefile.am Makefile.in \
 acconfig.h aclocal.m4 config.guess config.sub configure configure.in \
@@ -299,6 +299,7 @@ sysv.lo: src/arm/sysv.S
 o32.lo: src/mips/o32.S
 n32.lo: src/mips/n32.S
 v8.lo: src/sparc/v8.S
+v9.lo: src/sparc/v9.S
 
 libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES)
        $(LINK) -rpath $(toolexeclibdir) $(libffi_la_LDFLAGS) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
index dbd1f2e..d876117 100755 (executable)
@@ -1630,6 +1630,8 @@ i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
 sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
 sparc-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc-*-linux*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc64-*-linux*) TARGET=SPARC; TARGETDIR=sparc;;
 alpha*-*-linux* | alpha*-*-osf*) TARGET=ALPHA; TARGETDIR=alpha;;
 ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
 m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
index db643ec..38d8473 100644 (file)
@@ -50,6 +50,8 @@ i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;;
 i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
 sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
 sparc-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc-*-linux*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc64-*-linux*) TARGET=SPARC; TARGETDIR=sparc;;
 alpha*-*-linux* | alpha*-*-osf*) TARGET=ALPHA; TARGETDIR=alpha;;
 ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
 m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
index 655cc1c..6be7e23 100644 (file)
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------*-C-*-
    libffi @VERSION@ - Copyright (c) 1996-1999  Cygnus Solutions
 
-   $Id: ffi.h.in,v 1.3 1999/09/01 23:16:34 tromey Exp $
+   $Id: ffi.h.in,v 1.4 2000/02/25 19:13:44 tromey Exp $
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -160,6 +160,12 @@ extern "C" {
 #define SIZEOF_ARG SIZEOF_VOID_P
 #endif
 
+#ifdef SPARC
+#if defined(__arch64__) || defined(__sparcv9)
+#define SPARC64
+#endif
+#endif
+
 #ifndef LIBFFI_ASM
 
 /* ---- Generic type definitions ----------------------------------------- */
@@ -176,9 +182,13 @@ typedef enum ffi_abi {
   /* ---- Sparc -------------------- */
 #ifdef SPARC
   FFI_V8,
-  FFI_DEFAULT_ABI = FFI_V8,
   FFI_V8PLUS,
   FFI_V9,
+#ifdef SPARC64
+  FFI_DEFAULT_ABI = FFI_V9,
+#else
+  FFI_DEFAULT_ABI = FFI_V8,
+#endif
 #endif
 
   /* ---- Intel x86 ---------------- */
index 3dd0989..d4a687c 100644 (file)
@@ -224,7 +224,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
   signed int si1;
   signed int si2;
 
-#if defined(ALPHA) || defined(IA64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
+#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
   long long rint;
 #else
   int rint;
@@ -295,7 +295,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
 
   /* return value tests */
   {
-#if defined(MIPS) || defined(SPARC) /* || defined(ARM) */
+#if defined(MIPS) /* || defined(ARM) */
     puts ("long long tests not run. This is a known bug on this architecture.");
 #else
     args[0] = &ffi_type_sint64;
index 4c731b9..3f21411 100644 (file)
@@ -107,7 +107,11 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
 
 #ifndef M68K
   /* Make space for the return structure pointer */
-  if (cif->rtype->type == FFI_TYPE_STRUCT)
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+#ifdef SPARC
+      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
+#endif
+      )
     bytes = STACK_ARG_SIZE(sizeof(void*));
 #endif
 
@@ -121,8 +125,10 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
        return FFI_BAD_TYPEDEF;
 
 #ifdef SPARC
-      if ((*ptr)->type == FFI_TYPE_STRUCT
-         || (*ptr)->type == FFI_TYPE_LONGDOUBLE)
+      if (((*ptr)->type == FFI_TYPE_STRUCT
+          && ((*ptr)->size > 16 || cif->abi != FFI_V9))
+         || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
+             && cif->abi != FFI_V9))
        bytes += sizeof(void*);
       else
 #endif
@@ -140,4 +146,3 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
   /* Perform machine dependent cif processing */
   return ffi_prep_cif_machdep(cif);
 }
-
index 8ca6710..6470636 100644 (file)
@@ -33,7 +33,7 @@
 /* ffi_prep_args is called by the assembly routine once stack space
    has been allocated for the function's arguments */
 
-void ffi_prep_args(char *stack, extended_cif *ecif)
+void ffi_prep_args_v8(char *stack, extended_cif *ecif)
 {
   int i;
   int tmp;
@@ -45,16 +45,16 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
   tmp = 0;
 
   /* Skip 16 words for the window save area */
-  argp = stack + 16*sizeof(void*);
+  argp = stack + 16*sizeof(int);
 
   /* This should only really be done when we are returning a structure,
      however, it's faster just to do it all the time...
 
   if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
-  *(void **) argp = ecif->rvalue;
+  *(int *) argp = (long)ecif->rvalue;
 
   /* And 1 word for the  structure return value. */
-  argp += sizeof(void*);
+  argp += sizeof(int);
 
 #ifdef USING_PURIFY
   /* Purify will probably complain in our assembly routine, unless we
@@ -81,10 +81,13 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
        {
          avn--;
          if ((*p_arg)->type == FFI_TYPE_STRUCT
-             || (*p_arg)->type == FFI_TYPE_LONGDOUBLE)
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+             || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
+#endif
+             )
            {
-             *(unsigned int *) argp = (unsigned int)(* p_argv);
-             z = sizeof(void*);
+             *(unsigned int *) argp = (unsigned long)(* p_argv);
+             z = sizeof(int);
            }
          else
            {
@@ -109,15 +112,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
                    case FFI_TYPE_UINT16:
                      *(unsigned int *) argp = *(UINT16 *)(* p_argv);
                      break;
-                     
-                   case FFI_TYPE_SINT32:
-                     *(signed int *) argp = *(SINT32 *)(* p_argv);
-                     break;
-                     
-                   case FFI_TYPE_UINT32:
-                     *(unsigned int *) argp = *(UINT32 *)(* p_argv);
-                     break;
-                     
+
                    default:
                      FFI_ASSERT(0);
                    }
@@ -135,82 +130,295 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
   return;
 }
 
+int ffi_prep_args_v9(char *stack, extended_cif *ecif)
+{
+  int i, ret = 0;
+  int tmp;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  tmp = 0;
+
+  /* Skip 16 words for the window save area */
+  argp = stack + 16*sizeof(long long);
+
+#ifdef USING_PURIFY
+  /* Purify will probably complain in our assembly routine, unless we
+     zero out this memory. */
+
+  ((long long*)argp)[0] = 0;
+  ((long long*)argp)[1] = 0;
+  ((long long*)argp)[2] = 0;
+  ((long long*)argp)[3] = 0;
+  ((long long*)argp)[4] = 0;
+  ((long long*)argp)[5] = 0;
+#endif
+
+  p_argv = ecif->avalue;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
+      ecif->cif->rtype->size > 32)
+    {
+      *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
+      tmp = 1;
+    }
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
+       i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      switch ((*p_arg)->type)
+       {
+       case FFI_TYPE_STRUCT:
+         if (z > 16)
+           {
+             /* For structures larger than 16 bytes we pass reference.  */
+             *(unsigned long long *) argp = (unsigned long)* p_argv;
+             argp += sizeof(long long);
+             tmp++;
+             p_argv++;
+             continue;
+           }
+         /* FALLTHROUGH */
+       case FFI_TYPE_FLOAT:
+       case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+#endif
+         ret = 1; /* We should promote into FP regs as well as integer.  */
+         break;
+       }
+      if (z < sizeof(long long))
+       {
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed long long *) argp = *(SINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT8:
+             *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT16:
+             *(signed long long *) argp = *(SINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT16:
+             *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT32:
+             *(signed long long *) argp = *(SINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT32:
+             *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_FLOAT:
+             *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
+             break;
+
+           case FFI_TYPE_STRUCT:
+             memcpy(argp, *p_argv, z);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         z = sizeof(long long);
+         tmp++;
+       }
+      else if (z == sizeof(long long))
+       {
+         memcpy(argp, *p_argv, z);
+         z = sizeof(long long);
+         tmp++;
+       }
+      else
+       {
+         if ((tmp & 1) && (*p_arg)->alignment > 8)
+           {
+             tmp++;
+             argp += sizeof(long long);
+           }
+         memcpy(argp, *p_argv, z);
+         z = 2 * sizeof(long long);
+         tmp += 2;
+       }
+      p_argv++;
+      argp += z;
+    }
+
+  return ret;
+}
+
 /* Perform machine dependent cif processing */
 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 {
-  /* If we are returning a struct, this will already have been added.
-     Otherwise we need to add it because it's always got to be there! */
+  int wordsize;
+
+  if (cif->abi != FFI_V9)
+    {
+      wordsize = 4;
 
-  if (cif->rtype->type != FFI_TYPE_STRUCT)
-    cif->bytes += sizeof(void*);
+      /* If we are returning a struct, this will already have been added.
+        Otherwise we need to add it because it's always got to be there! */
 
-  /* sparc call frames require that space is allocated for 6 args,
-     even if they aren't used. Make that space if necessary. */
+      if (cif->rtype->type != FFI_TYPE_STRUCT)
+       cif->bytes += wordsize;
+
+      /* sparc call frames require that space is allocated for 6 args,
+        even if they aren't used. Make that space if necessary. */
   
-  if (cif->bytes < 4*6+4)
-    cif->bytes = 4*6+4;
+      if (cif->bytes < 4*6+4)
+       cif->bytes = 4*6+4;
+    }
+  else
+    {
+      wordsize = 8;
+
+      /* sparc call frames require that space is allocated for 6 args,
+        even if they aren't used. Make that space if necessary. */
+  
+      if (cif->bytes < 8*6)
+       cif->bytes = 8*6;
+    }
 
   /* Adjust cif->bytes. to include 16 words for the window save area,
      and maybe the struct/union return pointer area, */
 
-  cif->bytes += 64;
+  cif->bytes += 16 * wordsize;
 
-  /* The stack must be double word aligned, so round bytes up
+  /* The stack must be 2 word aligned, so round bytes up
      appropriately. */
 
-  cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*));
+  cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
 
   /* Set the return type flag */
   switch (cif->rtype->type)
     {
     case FFI_TYPE_VOID:
-    case FFI_TYPE_STRUCT:
-      cif->flags = cif->rtype->type;
-      break;
-
     case FFI_TYPE_FLOAT:
-      cif->flags = FFI_TYPE_FLOAT;
+    case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+#endif
+      cif->flags = cif->rtype->type;
       break;
 
-    case FFI_TYPE_DOUBLE:
-      cif->flags = FFI_TYPE_DOUBLE;
+    case FFI_TYPE_STRUCT:
+      if (cif->abi == FFI_V9 && cif->rtype->size > 32)
+       cif->flags = FFI_TYPE_VOID;
+      else
+       cif->flags = FFI_TYPE_STRUCT;
       break;
 
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      if (cif->abi != FFI_V9)
+       {
+         cif->flags = FFI_TYPE_SINT64;
+         break;
+       }
+      /* FALLTHROUGH */
     default:
       cif->flags = FFI_TYPE_INT;
       break;
     }
-
   return FFI_OK;
 }
 
+int ffi_V9_return_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
+{
+  ffi_type **ptr = &arg->elements[0];
+
+  while (*ptr != NULL)
+    {
+      if (off & ((*ptr)->alignment - 1))
+       off = ALIGN(off, (*ptr)->alignment);
+
+      switch ((*ptr)->type)
+       {
+       case FFI_TYPE_STRUCT:
+         off = ffi_V9_return_struct(*ptr, off, ret, intg, flt);
+         break;
+       case FFI_TYPE_FLOAT:
+       case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+#endif
+         memcpy(ret + off, flt + off, (*ptr)->size);
+         off += (*ptr)->size;
+         break;
+       default:
+         memcpy(ret + off, intg + off, (*ptr)->size);
+         off += (*ptr)->size;
+         break;
+       }
+      ptr++;
+    }
+  return off;
+}
+
 extern int ffi_call_V8(void *, extended_cif *, unsigned, 
                       unsigned, unsigned *, void (*fn)());
+extern int ffi_call_V9(void *, extended_cif *, unsigned, 
+                      unsigned, unsigned *, void (*fn)());
 
 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
 {
   extended_cif ecif;
+  void *rval = rvalue;
 
   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))
-    ecif.rvalue = alloca(cif->rtype->size);
-  else
-    ecif.rvalue = rvalue;
-    
+
+  ecif.rvalue = rvalue;
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      if (cif->rtype->size <= 32)
+       rval = alloca(64);
+      else
+       {
+         rval = NULL;
+         if (rvalue == NULL)
+           ecif.rvalue = alloca(cif->rtype->size);
+       }
+    }
+
   switch (cif->abi) 
     {
     case FFI_V8:
-      ffi_call_V8(ffi_prep_args, &ecif, cif->bytes, 
+#ifdef SPARC64
+      /* We don't yet support calling 32bit code from 64bit */
+      FFI_ASSERT(0);
+#else
+      ffi_call_V8(ffi_prep_args_v8, &ecif, cif->bytes, 
                  cif->flags, rvalue, fn);
+#endif
+      break;
+    case FFI_V9:
+#ifdef SPARC64
+      ffi_call_V9(ffi_prep_args_v9, &ecif, cif->bytes,
+                 cif->flags, rval, fn);
+      if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
+       ffi_V9_return_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
+#else
+      /* And vice versa */
+      FFI_ASSERT(0);
+#endif
       break;
     default:
       FFI_ASSERT(0);
       break;
     }
+
 }
index da0dbe6..e4b2ba9 100644 (file)
@@ -56,6 +56,7 @@ _ffi_call_V8:
        ld      [%l0+ARGS+20], %o5
        call    %i5
        mov     %l0, %sp        ! (delay) switch to frame
+       nop                     ! STRUCT returning functions skip 12 instead of 8 bytes
 
        ! If the return value pointer is NULL, assume no return value.
        tst     %i4
@@ -70,6 +71,9 @@ _ffi_call_V8:
        be,a    done
        st      %f0, [%i4+0]    ! (delay)
 
+       cmp     %i3, FFI_TYPE_SINT64
+       be      longlong
+
        cmp     %i3, FFI_TYPE_DOUBLE
        bne     done
        nop
@@ -80,6 +84,12 @@ done:
        ret
        restore
 
+longlong:
+       st      %o0, [%i4+0]
+       st      %o1, [%i4+4]
+       ret
+       restore
+
 .ffi_call_V8_end:
         .size    ffi_call_V8,.ffi_call_V8_end-ffi_call_V8
 
diff --git a/libffi/src/sparc/v9.S b/libffi/src/sparc/v9.S
new file mode 100644 (file)
index 0000000..3849434
--- /dev/null
@@ -0,0 +1,127 @@
+/* -----------------------------------------------------------------------
+   v9.S - Copyright (c) 2000 Cygnus Solutions
+   
+   Sparc 64bit Foreign Function Interface 
+
+   $Id:$
+
+   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 SPARC64
+/* Only compile this in for 64bit builds, because otherwise the object file
+   will have inproper architecture due to used instructions.  */
+
+#define STACKFRAME 128         /* Minimum stack framesize for SPARC */
+#define STACK_BIAS 2047
+#define ARGS (128)             /* Offset of register area in frame */
+
+.text
+        .align 8
+.globl ffi_call_V9
+.globl _ffi_call_V9
+
+ffi_call_V9:
+_ffi_call_V9:
+       save    %sp, -STACKFRAME, %sp
+       
+       sub     %sp, %i2, %sp   ! alloca() space in stack for frame to set up
+       add     %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of 
+                                               ! frame to set up
+
+       mov     %l0, %o0        ! call routine to set up frame
+       call    %i0
+        mov    %i1, %o1        ! (delay)
+       brz,pt  %o0, 1f
+        ldx    [%l0+ARGS], %o0 ! call foreign function
+
+       ldd     [%l0+ARGS], %f0
+       ldd     [%l0+ARGS+8], %f2
+       ldd     [%l0+ARGS+16], %f4
+       ldd     [%l0+ARGS+24], %f6
+       ldd     [%l0+ARGS+32], %f8
+       ldd     [%l0+ARGS+40], %f10
+       ldd     [%l0+ARGS+48], %f12
+       ldd     [%l0+ARGS+56], %f14
+       ldd     [%l0+ARGS+64], %f16
+       ldd     [%l0+ARGS+72], %f18
+       ldd     [%l0+ARGS+80], %f20
+       ldd     [%l0+ARGS+88], %f22
+       ldd     [%l0+ARGS+96], %f24
+       ldd     [%l0+ARGS+104], %f26
+       ldd     [%l0+ARGS+112], %f28
+       ldd     [%l0+ARGS+120], %f30
+
+1:     ldx     [%l0+ARGS+8], %o1
+       ldx     [%l0+ARGS+16], %o2
+       ldx     [%l0+ARGS+24], %o3
+       ldx     [%l0+ARGS+32], %o4
+       ldx     [%l0+ARGS+40], %o5
+       call    %i5
+        sub    %l0, STACK_BIAS, %sp    ! (delay) switch to frame
+
+       ! If the return value pointer is NULL, assume no return value.
+       brz,pn  %i4, done
+        nop
+
+       cmp     %i3, FFI_TYPE_INT
+       be,a,pt %icc, done
+        stx    %o0, [%i4]      ! (delay)
+
+       cmp     %i3, FFI_TYPE_FLOAT
+       be,a,pn %icc, done
+        st     %f0, [%i4+0]    ! (delay)
+
+       cmp     %i3, FFI_TYPE_DOUBLE
+       be,a,pn %icc, done
+        std    %f0, [%i4+0]    ! (delay)
+
+       cmp     %i3, FFI_TYPE_STRUCT
+       be,pn   %icc, dostruct
+
+        cmp    %i3, FFI_TYPE_LONGDOUBLE
+       bne,pt  %icc, done
+        nop
+       std     %f0, [%i4+0]
+       std     %f2, [%i4+8]
+
+done:  ret
+        restore
+
+dostruct:
+       /* This will not work correctly for unions. */
+       stx     %o0, [%i4+0]
+       stx     %o1, [%i4+8]
+       stx     %o2, [%i4+16]
+       stx     %o3, [%i4+24]
+       std     %f0, [%i4+32]
+       std     %f2, [%i4+40]
+       std     %f4, [%i4+48]
+       std     %f6, [%i4+56]
+       ret
+        restore
+
+.ffi_call_V9_end:
+        .size    ffi_call_V9,.ffi_call_V9_end-ffi_call_V9
+
+#endif
index abf276d..43aab91 100644 (file)
@@ -42,9 +42,17 @@ FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
 FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
 FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
 FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
-FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
 FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
 
+#if defined ALPHA || defined SPARC64
+
+FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
+
+#endif
 
 #ifdef X86
 
@@ -87,8 +95,17 @@ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
 #elif defined SPARC
 
 FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+
+#ifdef SPARC64
+
+FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
+
+#else
+
 FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
 
+#endif
+
 #else
 
 FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);