This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] libffi longdouble for darwin


Hi all,

the longer promised patch comes here. I hope to have it mostly right to implement longdouble support on darwin (maybe even on AIX).

I'm still not finished with all the test cases but I'd like to see this patch in 3.5 and so I have to hurry somehow. The test cases needs some polishing. Testing was a bit difficult since the libc does not support longdouble and so I had to tweak a bit.

I based my work on the ppc64 ABI (by Alanm, DJE et.al.) And on what's currently implemented on darwin.

Tested on a G4.

David, if you say AIX behaves the same way as darwin regarding size and alignment of longdoubles I adjust the file src/types.c. I could not test so far on AIX.

Comments and corrections welcome.

Andreas

2004-09-01 Andreas Tobler <a.tobler@schweiz.ch>

	* src/powerpc/ffi_darwin.c: Add flag for longdouble return values.
	(ffi_prep_args): Handle longdouble arguments.
	(ffi_prep_cif_machdep): Set flags for longdouble. Calculate space for
	longdouble.
	(ffi_closure_helper_DARWIN): Add closure handling for longdouble.
	* src/powerpc/darwin.S (_ffi_call_DARWIN): Add handling of longdouble
	values.
	* src/powerpc/darwin_closure.S (_ffi_closure_ASM): Likewise.
	* src/types.c: Defined longdouble size and alignment for darwin.
Index: src/types.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/types.c,v
retrieving revision 1.15
diff -u -r1.15 types.c
--- src/types.c	16 Mar 2004 19:17:33 -0000	1.15
+++ src/types.c	1 Sep 2004 20:43:04 -0000
@@ -80,11 +80,16 @@
 #endif
 FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
 
-#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
+#elif defined ARM || defined SH || defined POWERPC_AIX
 
 FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
 FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
 
+#elif defined POWERPC_DARWIN
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
+
 #elif defined SPARC
 
 FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
Index: src/powerpc/darwin.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/darwin.S,v
retrieving revision 1.9
diff -u -r1.9 darwin.S
--- src/powerpc/darwin.S	27 Apr 2004 01:45:19 -0000	1.9
+++ src/powerpc/darwin.S	1 Sep 2004 20:43:04 -0000
@@ -1,5 +1,6 @@
 /* -----------------------------------------------------------------------
    darwin.S - Copyright (c) 2000 John Hornkvist
+	      Copyright (c) 2004 Free Software Foundation, Inc.
 
    PowerPC Assembly glue.
 
@@ -142,12 +143,23 @@
 	blr
 
 L(fp_return_value):
+	/* Do we have long double to store?  */
+	bf	31,L(fd_return_value)
+	stfd	f1,0(r30)
+	stfd	f2,8(r30)
+	b	L(done_return_value)
+
+L(fd_return_value):
+	/* Do we have double to store?  */
 	bf	28,L(float_return_value)
 	stfd	f1,0(r30)
 	b	L(done_return_value)
+
 L(float_return_value):
+	/* We only have a float to store.  */
 	stfs	f1,0(r30)
 	b	L(done_return_value)
+
 LFE1:
 /* END(_ffi_call_DARWIN)  */
 
@@ -218,6 +230,6 @@
 	.align 2
 LEFDE1:
 .data
-        .align 2
+	.align 2
 LLFB0$non_lazy_ptr:
-        .long   LFB0
+	.long   LFB0
Index: src/powerpc/darwin_closure.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/darwin_closure.S,v
retrieving revision 1.8
diff -u -r1.8 darwin_closure.S
--- src/powerpc/darwin_closure.S	27 Apr 2004 01:45:19 -0000	1.8
+++ src/powerpc/darwin_closure.S	1 Sep 2004 20:43:04 -0000
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   darwin_closure.S - Copyright (c) 2002 2003 Free Software Foundation,
+   darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
    Inc. based on ppc_closure.S
 
    PowerPC Assembly glue.
@@ -42,8 +42,8 @@
 	/* 24 Bytes (Linkage Area)
 	   32 Bytes (outgoing parameter area, always reserved)
 	   104 Bytes (13*8 from FPR)
-	   8 Bytes (result)
-	   168 Bytes  */
+	   16 Bytes (result)
+	   176 Bytes  */
 
 	stwu	r1,-176(r1)	/* skip over caller save area
 				keep stack aligned to 16.  */
@@ -150,9 +150,9 @@
 /* case FFI_TYPE_LONGDOUBLE  */
 Lret_type4:
 	lfd	f1,0(r5)
+	lfd	f2,8(r5)
 	b	Lfinish
 	nop
-	nop
 
 /* case FFI_TYPE_UINT8  */
 Lret_type5:
@@ -301,4 +301,4 @@
 .data
 	.align 2
 LLFB1$non_lazy_ptr:
-        .long LFB1
+	.long LFB1
Index: src/powerpc/ffi_darwin.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/powerpc/ffi_darwin.c,v
retrieving revision 1.12
diff -u -r1.12 ffi_darwin.c
--- src/powerpc/ffi_darwin.c	30 Jun 2004 09:55:13 -0000	1.12
+++ src/powerpc/ffi_darwin.c	1 Sep 2004 20:43:05 -0000
@@ -38,6 +38,7 @@
   FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7  */
   FLAG_RETURNS_FP       = 1 << (31-29),
   FLAG_RETURNS_64BITS   = 1 << (31-28),
+  FLAG_RETURNS_128BITS  = 1 << (31-31),
 
   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI  */
@@ -86,7 +87,7 @@
   const unsigned flags = ecif->cif->flags;
 
   /* 'stacktop' points at the previous backchain pointer.  */
-  unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
+  unsigned *const stacktop = stack + (bytes / sizeof(unsigned));
 
   /* 'fpr_base' points at the space for fpr1, and grows upwards as
      we use FPR registers.  */
@@ -95,7 +96,7 @@
 
 
   /* 'next_arg' grows up as we put parameters in it.  */
-  unsigned *next_arg = stack + 6; /* 6 reserved posistions.  */
+  unsigned *next_arg = stack + 6; /* 6 reserved positions.  */
 
   int i = ecif->cif->nargs;
   double double_tmp;
@@ -137,6 +138,7 @@
 	  fparg_count++;
 	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
 	  break;
+
 	case FFI_TYPE_DOUBLE:
 	  double_tmp = *(double *)*p_argv;
 	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
@@ -148,6 +150,24 @@
 	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
 	  break;
 
+	case FFI_TYPE_LONGDOUBLE:
+	  double_tmp = ((double *)*p_argv)[0];
+	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+	    *(double *)next_arg = double_tmp;
+	  else
+	    *fpr_base++ = double_tmp;
+	  next_arg += 2;
+	  fparg_count++;
+	  double_tmp = ((double *)*p_argv)[1];
+	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+	    *(double *)next_arg = double_tmp;
+	  else
+	    *fpr_base++ = double_tmp;
+	  next_arg += 2;
+	  fparg_count++;
+	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+	  break;
+
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_SINT64:
 	  *(long long *)next_arg = *(long long *)*p_argv;
@@ -167,10 +187,6 @@
 	  goto putgpr;
 
 	case FFI_TYPE_STRUCT:
-
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	case FFI_TYPE_LONGDOUBLE:
-#endif
 	  dest_cpy = (char *) next_arg;
 
 	  /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
@@ -240,10 +256,11 @@
        as the first argument.  */
   switch (cif->rtype->type)
     {
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
     case FFI_TYPE_LONGDOUBLE:
-#endif
-      /* Fall through.  */
+      flags |= FLAG_RETURNS_128BITS;
+      flags |= FLAG_RETURNS_FP;
+      break;
+
     case FFI_TYPE_DOUBLE:
       flags |= FLAG_RETURNS_64BITS;
       /* Fall through.  */
@@ -272,9 +289,8 @@
 
   /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
      first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
-     goes on the stack.  Structures and long doubles (if not equivalent
-     to double) are passed as a pointer to a copy of the structure.
-     Stuff on the stack needs to keep proper alignment.  */
+     goes on the stack.  Structures are passed as a pointer to a copy of
+     the structure. Stuff on the stack needs to keep proper alignment.  */
   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
     {
       switch ((*ptr)->type)
@@ -289,6 +305,16 @@
 	    intarg_count++;
 	  break;
 
+	case FFI_TYPE_LONGDOUBLE:
+	  fparg_count += 2;
+	  /* If this FP arg is going on the stack, it must be
+	     8-byte-aligned.  */
+	  if (fparg_count > NUM_FPR_ARG_REGISTERS
+	      && intarg_count%2 != 0)
+	    intarg_count++;
+	  intarg_count +=2;
+	  break;
+
 	case FFI_TYPE_UINT64:
 	case FFI_TYPE_SINT64:
 	  /* 'long long' arguments are passed as two words, but
@@ -302,9 +328,6 @@
 	  break;
 
 	case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-	case FFI_TYPE_LONGDOUBLE:
-#endif
 	  size_al = (*ptr)->size;
 	  /* If the first member of the struct is a double, then align
 	     the struct to double-word.
@@ -409,8 +432,8 @@
    points to one of these.  */
 
 typedef struct aix_fd_struct {
-    void *code_pointer;
-    void *toc;
+  void *code_pointer;
+  void *toc;
 } aix_fd;
 
 /* here I'd like to add the stack frame layout we use in darwin_closure.S
@@ -572,6 +595,13 @@
      pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
      pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM.  */
 
+  typedef double ldbits[2];
+
+  union ldu
+  {
+    ldbits lb;
+    long double ld;
+  };
 
   void **          avalue;
   ffi_type **      arg_types;
@@ -581,6 +611,7 @@
   ffi_cif *        cif;
   double           temp;
   unsigned         size_al;
+  union ldu        temp_ld;
 
   cif = closure->cif;
   avalue = alloca(cif->nargs * sizeof(void *));
@@ -689,6 +720,32 @@
 	  pgr += 2;
 	  break;
 
+	case FFI_TYPE_LONGDOUBLE:
+	  /* A long double value consumes four GPRs and two FPRs.
+	     There are 13 64bit floating point registers.  */
+	  if (nf < NUM_FPR_ARG_REGISTERS - 1)
+	    {
+	      avalue[i] = pfr;
+	      pfr += 2;
+	    }
+	  /* Here we have the situation where one part of the long double
+	     is stored in fpr13 and the other part is already on the stack.
+	     We use a union to pass the long double to avalue[i].  */
+	  else if (nf == NUM_FPR_ARG_REGISTERS - 1)
+	    {
+	      memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
+	      memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
+	      avalue[i] = &temp_ld.ld;
+	    }
+	  else
+	    {
+	      avalue[i] = pgr;
+	    }
+	  nf += 2;
+	  ng += 4;
+	  pgr += 4;
+	  break;
+
 	default:
 	  FFI_ASSERT(0);
 	}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]