This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi 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 5/8] sparc: Handle more cases of structure return directly


---
 src/sparc/ffi.c      |   4 +-
 src/sparc/ffi64.c    |  40 +++++++++++++++---
 src/sparc/internal.h |  24 ++++++-----
 src/sparc/v8.S       |  77 +++++++++++++++++------------------
 src/sparc/v9.S       | 112 ++++++++++++++++++++++++++++++---------------------
 5 files changed, 152 insertions(+), 105 deletions(-)

diff --git a/src/sparc/ffi.c b/src/sparc/ffi.c
index 7542847..1b8f48e 100644
--- a/src/sparc/ffi.c
+++ b/src/sparc/ffi.c
@@ -59,10 +59,10 @@ ffi_prep_cif_machdep(ffi_cif *cif)
       flags = SPARC_RET_VOID;
       break;
     case FFI_TYPE_FLOAT:
-      flags = SPARC_RET_FLOAT;
+      flags = SPARC_RET_F_1;
       break;
     case FFI_TYPE_DOUBLE:
-      flags = SPARC_RET_DOUBLE;
+      flags = SPARC_RET_F_2;
       break;
     case FFI_TYPE_LONGDOUBLE:
     case FFI_TYPE_STRUCT:
diff --git a/src/sparc/ffi64.c b/src/sparc/ffi64.c
index 65ae438..ab3ed09 100644
--- a/src/sparc/ffi64.c
+++ b/src/sparc/ffi64.c
@@ -66,7 +66,6 @@ ffi_struct_float_mask (ffi_type *struct_type, int size_mask)
 	{
 	case FFI_TYPE_STRUCT:
 	  size_mask = ffi_struct_float_mask (t, size_mask);
-	  size_mask = ALIGN(size_mask, FFI_SIZEOF_ARG);
 	  continue;
 	case FFI_TYPE_FLOAT:
 	case FFI_TYPE_DOUBLE:
@@ -154,13 +153,13 @@ ffi_prep_cif_machdep(ffi_cif *cif)
       flags = SPARC_RET_VOID;
       break;
     case FFI_TYPE_FLOAT:
-      flags = SPARC_RET_FLOAT;
+      flags = SPARC_RET_F_1;
       break;
     case FFI_TYPE_DOUBLE:
-      flags = SPARC_RET_DOUBLE;
+      flags = SPARC_RET_F_2;
       break;
     case FFI_TYPE_LONGDOUBLE:
-      flags = SPARC_RET_LDOUBLE;
+      flags = SPARC_RET_F_4;
       break;
 
     case FFI_TYPE_STRUCT:
@@ -171,8 +170,37 @@ ffi_prep_cif_machdep(ffi_cif *cif)
 	}
       else
 	{
-	  flags = ffi_struct_float_mask (rtype, 0) << SPARC_FLTMASK_SHIFT;
-	  flags |= SPARC_RET_STRUCT;
+	  int size_mask = ffi_struct_float_mask (rtype, 0);
+	  int word_size = (size_mask >> 2) & 0x3f;
+	  int all_mask = (1 << word_size) - 1;
+	  int fp_mask = size_mask >> 8;
+
+	  flags = (size_mask << SPARC_FLTMASK_SHIFT) | SPARC_RET_STRUCT;
+
+	  /* For special cases of all-int or all-fp, we can return
+	     the value directly without popping through a struct copy.  */
+	  if (fp_mask == 0)
+	    {
+	      if (rtype->alignment >= 8)
+		{
+		  if (rtype->size == 8)
+		    flags = SPARC_RET_INT64;
+		  else if (rtype->size == 16)
+		    flags = SPARC_RET_INT128;
+		}
+	    }
+	  else if (fp_mask == all_mask)
+	    switch (word_size)
+	      {
+	      case 1: flags = SPARC_RET_F_1; break;
+	      case 2: flags = SPARC_RET_F_2; break;
+	      case 3: flags = SPARC_RET_F_3; break;
+	      case 4: flags = SPARC_RET_F_4; break;
+	      /* 5 word structures skipped; handled via RET_STRUCT.  */
+	      case 6: flags = SPARC_RET_F_6; break;
+	      /* 7 word structures skipped; handled via RET_STRUCT.  */
+	      case 8: flags = SPARC_RET_F_8; break;
+	      }
 	}
       break;
 
diff --git a/src/sparc/internal.h b/src/sparc/internal.h
index 3018928..b4494d9 100644
--- a/src/sparc/internal.h
+++ b/src/sparc/internal.h
@@ -1,17 +1,21 @@
 #define SPARC_RET_VOID		0
 #define SPARC_RET_STRUCT	1
-#define SPARC_RET_FLOAT		2
-#define SPARC_RET_DOUBLE	3
-#define SPARC_RET_UINT8		4
-#define SPARC_RET_SINT8		5
-#define SPARC_RET_UINT16	6
-#define SPARC_RET_SINT16	7
+#define SPARC_RET_UINT8		2
+#define SPARC_RET_SINT8		3
+#define SPARC_RET_UINT16	4
+#define SPARC_RET_SINT16	5
+#define SPARC_RET_UINT32	6
+#define SPARC_RET_SINT32	7	/* v9 only */
 #define SPARC_RET_INT64		8
-#define SPARC_RET_UINT32	9
+#define SPARC_RET_INT128	9	/* v9 only */
 
-/* These two are only used for V9.  */
-#define SPARC_RET_SINT32	10
-#define SPARC_RET_LDOUBLE	11
+/* Note that F_7 is missing, and is handled by SPARC_RET_STRUCT.  */
+#define SPARC_RET_F_8		10
+#define SPARC_RET_F_6		11	/* v9 only */
+#define SPARC_RET_F_4		12
+#define SPARC_RET_F_2		13
+#define SPARC_RET_F_3		14	/* v9 only */
+#define SPARC_RET_F_1		15
 
 #define SPARC_FLAG_RET_MASK	15
 #define SPARC_FLAG_RET_IN_MEM	32
diff --git a/src/sparc/v8.S b/src/sparc/v8.S
index b0d50a3..4adcf6d 100644
--- a/src/sparc/v8.S
+++ b/src/sparc/v8.S
@@ -118,15 +118,6 @@ E SPARC_RET_VOID
 	 restore
 E SPARC_RET_STRUCT
 	unimp
-E SPARC_RET_FLOAT
-	st	%f0, [%i2]
-	ret
-	 restore
-E SPARC_RET_DOUBLE
-	std	%f0, [%i2]
-	ret
-	 restore
-	nop
 E SPARC_RET_UINT8
 	and	%o0, 0xff, %o0
 	st	%o0, [%i2]
@@ -144,28 +135,34 @@ E SPARC_RET_SINT16
 	sll	%o0, 16, %o0
 	b	7f
 	 sra	%o0, 16, %o0
-E SPARC_RET_INT64
-	std	%o0, [%i2]
-	ret
-	 restore
 E SPARC_RET_UINT32
 7:	st	%o0, [%i2]
 	ret
 	 restore
-
-	! Unused entries.  Don't allow bad data to do worse things.
-E 10
+E SPARC_RET_SINT32
 	unimp
-E 11
+E SPARC_RET_INT64
+	std	%o0, [%i2]
+	ret
+	 restore
+E SPARC_RET_INT128
 	unimp
-E 12
+E SPARC_RET_F_8
 	unimp
-E 13
+E SPARC_RET_F_6
 	unimp
-E 14
+E SPARC_RET_F_4
 	unimp
-E 15
+E SPARC_RET_F_2
+	std	%f0, [%i2]
+	ret
+	 restore
+E SPARC_RET_F_3
 	unimp
+E SPARC_RET_F_1
+	st	%f0, [%i2]
+	ret
+	 restore
 
 	! Struct returning functions expect and skip the unimp here.
 	.align	8
@@ -234,14 +231,6 @@ E SPARC_RET_VOID
 E SPARC_RET_STRUCT
 	jmp	%i7+12
 	 restore
-E SPARC_RET_FLOAT
-	ld	[%fp-8], %f0
-	ret
-	 restore
-E SPARC_RET_DOUBLE
-	ldd	[%fp-8], %f0
-	ret
-	 restore
 E SPARC_RET_UINT8
 	ldub	[%fp-8+3], %i0
 	ret
@@ -258,28 +247,34 @@ E SPARC_RET_SINT16
 	ldsh	[%fp-8+2], %i0
 	ret
 	 restore
-E SPARC_RET_INT64
-	ldd	[%fp-8], %i0
-	ret
-	 restore
 E SPARC_RET_UINT32
 	ld	[%fp-8], %i0
 	ret
 	 restore
-
-	! Unused entries.  Don't allow bad data to do worse things.
-E 10
+E SPARC_RET_SINT32
 	unimp
-E 11
+E SPARC_RET_INT64
+	ldd	[%fp-8], %i0
+	ret
+	 restore
+E SPARC_RET_INT128
 	unimp
-E 12
+E SPARC_RET_F_8
 	unimp
-E 13
+E SPARC_RET_F_6
 	unimp
-E 14
+E SPARC_RET_F_4
 	unimp
-E 15
+E SPARC_RET_F_2
+	ldd	[%fp-8], %f0
+	ret
+	 restore
+E SPARC_RET_F_3
 	unimp
+E SPARC_RET_F_1
+	ld	[%fp-8], %f0
+	ret
+	 restore
 
 	cfi_endproc
 	.size	C(ffi_closure_v8), . - C(ffi_closure_v8)
diff --git a/src/sparc/v9.S b/src/sparc/v9.S
index 3d91f2d..d893d2f 100644
--- a/src/sparc/v9.S
+++ b/src/sparc/v9.S
@@ -114,12 +114,6 @@ E SPARC_RET_STRUCT
 	sub	%sp, 64, %sp
 	b	8f
 	 stx	%o0, [%l2]
-E SPARC_RET_FLOAT
-	return	%i7+8
-	 st	%f0, [%o2]
-E SPARC_RET_DOUBLE
-	return	%i7+8
-	 std	%f0, [%o2]
 E SPARC_RET_UINT8
 	and	%o0, 0xff, %i0
 	return	%i7+8
@@ -139,10 +133,6 @@ E SPARC_RET_SINT16
 	sra	%o0, 16, %i0
 	return	%i7+8
 	 stx	%o0, [%o2]
-E SPARC_RET_INT64
-	stx	%o0, [%i2]
-	return	%i7+8
-	 nop
 E SPARC_RET_UINT32
 	srl	%o0, 0, %i0
 	return	%i7+8
@@ -151,20 +141,40 @@ E SPARC_RET_SINT32
 	sra	%o0, 0, %i0
 	return	%i7+8
 	 stx	%o0, [%o2]
-E SPARC_RET_LDOUBLE
-	std	%f0, [%i2]
+E SPARC_RET_INT64
+	stx	%o0, [%i2]
+	return	%i7+8
+	 nop
+E SPARC_RET_INT128
+	stx	%o0, [%i2]
+	stx	%o1, [%i2+8]
+	return	%i7+8
+	 nop
+E SPARC_RET_F_8
+	st	%f7, [%i2+7*4]
+	nop
+	st	%f6, [%i2+6*4]
+	nop
+E SPARC_RET_F_6
+	st	%f5, [%i2+5*4]
+	nop
+	st	%f4, [%i2+4*4]
+	nop
+E SPARC_RET_F_4
+	std	%f2, [%i2+2*4]
+	return	%i7+8
+	 std	%f0, [%o2]
+E SPARC_RET_F_2
 	return	%i7+8
-	 std	%f2, [%o2+8]
-
-	! Unused entries.  Don't allow bad data to do worse things.
-E 12
-	unimp
-E 13
-	unimp
-E 14
-	unimp
-E 15
-	unimp
+	 std	%f0, [%o2]
+E SPARC_RET_F_3
+	st	%f2, [%i2+2*4]
+	nop
+	st	%f1, [%i2+1*4]
+	nop
+E SPARC_RET_F_1
+	return	%i7+8
+	 st	%f0, [%o2]
 
 	! Finish the SPARC_RET_STRUCT sequence.
 	.align	8
@@ -264,14 +274,6 @@ E SPARC_RET_STRUCT
 	ldd	[FP-160], %f0
 	b	8f
 	 ldx	[FP-152], %i1
-E SPARC_RET_FLOAT
-	ld	[FP-160], %f0
-	return	%i7+8
-	 nop
-E SPARC_RET_DOUBLE
-	ldd	[FP-160], %f0
-	return	%i7+8
-	 nop
 E SPARC_RET_UINT8
 	ldub	[FP-160+7], %i0
 	return	%i7+8
@@ -288,10 +290,6 @@ E SPARC_RET_SINT16
 	ldsh	[FP-160+6], %i0
 	return	%i7+8
 	 nop
-E SPARC_RET_INT64
-	ldx	[FP-160], %i0
-	return	%i7+8
-	 nop
 E SPARC_RET_UINT32
 	lduw	[FP-160+4], %i0
 	return	%i7+8
@@ -300,21 +298,43 @@ E SPARC_RET_SINT32
 	ldsw	[FP-160+4], %i0
 	return	%i7+8
 	 nop
-E SPARC_RET_LDOUBLE
+E SPARC_RET_INT64
+	ldx	[FP-160], %i0
+	return	%i7+8
+	 nop
+E SPARC_RET_INT128
+	ldx	[FP-160], %i0
+	ldx	[FP-160+8], %i1
+	return	%i7+8
+	 nop
+E SPARC_RET_F_8
+	ld	[FP-160+7*4], %f7
+	nop
+	ld	[FP-160+6*4], %f6
+	nop
+E SPARC_RET_F_6
+	ld	[FP-160+5*4], %f5
+	nop
+	ld	[FP-160+4*4], %f4
+	nop
+E SPARC_RET_F_4
 	ldd	[FP-160], %f0
 	ldd	[FP-160+8], %f2
 	return	%i7+8
 	 nop
-
-	! Unused entries.  Don't allow bad data to do worse things.
-E 12
-	unimp
-E 13
-	unimp
-E 14
-	unimp
-E 15
-	unimp
+E SPARC_RET_F_2
+	ldd	[FP-160], %f0
+	return	%i7+8
+	 nop
+E SPARC_RET_F_3
+	ld	[FP-160+2*4], %f2
+	nop
+	ld	[FP-160+1*4], %f1
+	nop
+E SPARC_RET_F_1
+	ld	[FP-160], %f0
+	return	%i7+8
+	 nop
 
 	! Finish the SPARC_RET_STRUCT sequence.
 	.align	8
-- 
1.9.3


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