This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

Re: [patch/libffi/hppa] Fix handling of 3 and 5-7 byte struct returns


> This fixes all the libffi test failures on hppa-linux.  Please check
> in if ok.

Installed as floows with a few minor changes to address formatting
and compilation warnings in ffi.c.

Tested on hppa-unknown-linux-gnu, 4.0 and head.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

2005-07-05  Randolph Chung  <tausq@debian.org>

	* src/pa/ffi.c (ffi_struct_type): Rename FFI_TYPE_SMALL_STRUCT1
	as FFI_TYPE_SMALL_STRUCT3.  Break out handling for 5-7 byte
	structures.  Kill compilation warnings.
	(ffi_closure_inner_LINUX): Print return values as hex in debug
	message.  Rename FFI_TYPE_SMALL_STRUCT1 as FFI_TYPE_SMALL_STRUCT3.
	Properly handle 5-7 byte structure returns.
	* src/pa/ffitarget.h (FFI_TYPE_SMALL_STRUCT1)
	(FFI_TYPE_SMALL_STRUCT2): Remove.
	(FFI_TYPE_SMALL_STRUCT3, FFI_TYPE_SMALL_STRUCT5)
	(FFI_TYPE_SMALL_STRUCT6, FFI_TYPE_SMALL_STRUCT7): Define.
	* src/pa/linux.S: Mark source file as using PA1.1 assembly.
	(checksmst1, checksmst2): Remove.
	(checksmst3): Optimize handling of 3-byte struct returns.
	(checksmst567): Properly handle 5-7 byte struct returns.

Index: src/pa/ffi.c
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/pa/ffi.c,v
retrieving revision 1.1
diff -u -3 -p -r1.1 ffi.c
--- src/pa/ffi.c	19 Mar 2004 22:34:17 -0000	1.1
+++ src/pa/ffi.c	6 Jul 2005 03:22:05 -0000
@@ -27,6 +27,7 @@
 #include <ffi_common.h>
 
 #include <stdlib.h>
+#include <stdio.h>
 
 #define ROUND_UP(v, a)  (((size_t)(v) + (a) - 1) & ~((a) - 1))
 #define ROUND_DOWN(v, a)  (((size_t)(v) - (a) + 1) & ~((a) - 1))
@@ -53,11 +54,15 @@ static inline int ffi_struct_type(ffi_ty
   else if (sz == 2)
     return FFI_TYPE_UINT16;
   else if (sz == 3)
-    return FFI_TYPE_SMALL_STRUCT1;
+    return FFI_TYPE_SMALL_STRUCT3;
   else if (sz == 4)
     return FFI_TYPE_UINT32;
-  else if (sz <= 6)
-    return FFI_TYPE_SMALL_STRUCT2;
+  else if (sz == 5)
+    return FFI_TYPE_SMALL_STRUCT5;
+  else if (sz == 6)
+    return FFI_TYPE_SMALL_STRUCT6;
+  else if (sz == 7)
+    return FFI_TYPE_SMALL_STRUCT7;
   else if (sz <= 8)
     return FFI_TYPE_UINT64;
   else
@@ -491,34 +496,32 @@ UINT32 ffi_closure_inner_LINUX(ffi_closu
   /* Invoke the closure.  */
   (closure->fun) (cif, rvalue, avalue, closure->user_data);
 
-  debug(3, "after calling function, ret[0] = %d, ret[1] = %d\n", ret[0], ret[1]);
+  debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], ret[1]);
 
   /* Store the result */
   switch (cif->flags)
     {
     case FFI_TYPE_UINT8:
-      *(stack - FIRST_ARG_SLOT) = *(UINT8 *)&ret[0];
+      *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
       break;
     case FFI_TYPE_SINT8:
-      *(stack - FIRST_ARG_SLOT) = *(SINT8 *)&ret[0];
+      *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
       break;
     case FFI_TYPE_UINT16:
-      *(stack - FIRST_ARG_SLOT) = *(UINT16 *)&ret[0];
+      *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
       break;
     case FFI_TYPE_SINT16:
-      *(stack - FIRST_ARG_SLOT) = *(SINT16 *)&ret[0];
+      *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
       break;
     case FFI_TYPE_INT:
-    case FFI_TYPE_UINT32:
-      *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
-      break;
     case FFI_TYPE_SINT32:
-      *(stack - FIRST_ARG_SLOT) = *(SINT32 *)&ret[0];
+    case FFI_TYPE_UINT32:
+      *(stack - FIRST_ARG_SLOT) = ret[0];
       break;
     case FFI_TYPE_SINT64:
     case FFI_TYPE_UINT64:
-      *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
-      *(stack - FIRST_ARG_SLOT - 1) = *(UINT32 *)&ret[1];
+      *(stack - FIRST_ARG_SLOT) = ret[0];
+      *(stack - FIRST_ARG_SLOT - 1) = ret[1];
       break;
 
     case FFI_TYPE_DOUBLE:
@@ -533,15 +536,34 @@ UINT32 ffi_closure_inner_LINUX(ffi_closu
       /* Don't need a return value, done by caller.  */
       break;
 
-    case FFI_TYPE_SMALL_STRUCT1:
+    case FFI_TYPE_SMALL_STRUCT3:
       tmp = (void*)(stack -  FIRST_ARG_SLOT);
       tmp += 4 - cif->rtype->size;
       memcpy((void*)tmp, &ret[0], cif->rtype->size);
       break;
 
-    case FFI_TYPE_SMALL_STRUCT2:
-      *(stack - FIRST_ARG_SLOT) = ret[0];
-      *(stack - FIRST_ARG_SLOT - 1) = ret[1];
+    case FFI_TYPE_SMALL_STRUCT5:
+    case FFI_TYPE_SMALL_STRUCT6:
+    case FFI_TYPE_SMALL_STRUCT7:
+      {
+	unsigned int ret2[2];
+	int off;
+
+	/* Right justify ret[0] and ret[1] */
+	switch (cif->flags)
+	  {
+	    case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
+	    case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
+	    case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
+	    default: off = 0; break;
+	  }
+
+	memset (ret2, 0, sizeof (ret2));
+	memcpy ((char *)ret2 + off, ret, 8 - off);
+
+	*(stack - FIRST_ARG_SLOT) = ret2[0];
+	*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
+      }
       break;
 
     case FFI_TYPE_POINTER:
Index: src/pa/ffitarget.h
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/pa/ffitarget.h,v
retrieving revision 1.1
diff -u -3 -p -r1.1 ffitarget.h
--- src/pa/ffitarget.h	19 Mar 2004 22:34:17 -0000	1.1
+++ src/pa/ffitarget.h	6 Jul 2005 03:22:05 -0000
@@ -51,7 +51,9 @@ typedef enum ffi_abi {
 
 #define FFI_TRAMPOLINE_SIZE 32
 
-#define FFI_TYPE_SMALL_STRUCT1 -1
-#define FFI_TYPE_SMALL_STRUCT2 -2
+#define FFI_TYPE_SMALL_STRUCT3 -1
+#define FFI_TYPE_SMALL_STRUCT5 -2
+#define FFI_TYPE_SMALL_STRUCT6 -3
+#define FFI_TYPE_SMALL_STRUCT7 -4
 #endif
 
Index: src/pa/linux.S
===================================================================
RCS file: /cvs/gcc/gcc/libffi/src/pa/linux.S,v
retrieving revision 1.2
diff -u -3 -p -r1.2 linux.S
--- src/pa/linux.S	20 Mar 2004 11:58:01 -0000	1.2
+++ src/pa/linux.S	6 Jul 2005 03:22:05 -0000
@@ -28,6 +28,7 @@
 #include <ffi.h>
 
 	.text
+	.level 1.1
 	.align 4
 
 	/* void ffi_call_LINUX(void (*)(char *, extended_cif *),
@@ -105,21 +106,46 @@ ffi_call_LINUX:
 
 	/* Store the result according to the return type.  */
 
-checksmst1:
-	comib,<>,n FFI_TYPE_SMALL_STRUCT1, %r21, checksmst2
-	/* There is maybe a better way to handle 3 byte structs.  */
-	sh2add %ret0,0,%ret0
-	sh2add %ret0,0,%ret0
-	sh2add %ret0,0,%ret0
-	sh2add %ret0,0,%ret0
+checksmst3:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, checksmst567
+	/* 3-byte structs are returned in ret0 as ??xxyyzz.  Shift
+	   left 8 bits to write to the result structure.  */
+	zdep %ret0, 23, 24, %r22
 	b done
-	stw %ret0, 0(%r20)
+	stw %r22, 0(%r20)
 
-checksmst2:
-	comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, checkint8
-	/* Up to now I don't have a way to handle 6/7 byte structs.
-	   The values are left bounded in the registers. In the struct
-	   itself they are left bounded.  */
+checksmst567:
+	/* 5-7 byte values are returned right justified:
+	      ret0     ret1
+	   5: ??????aa bbccddee
+	   6: ????aabb ccddeeff
+	   7: ??aabbcc ddeeffgg
+
+	   To store this in the result, write the first 4 bytes into a temp
+	   register using shrpw (t1 = aabbccdd), followed by a rotation of
+	   ret1:
+
+	      ret0     ret1	   ret1
+	   5: ??????aa bbccddee -> eebbccdd (rotate 8)
+	   6: ????aabb ccddeeff -> eeffccdd (rotate 16)
+	   7: ??aabbcc ddeeffgg -> eeffggdd (rotate 24)
+
+	   then we write (t1, ret1) into the result.  */
+
+	addi,<> -FFI_TYPE_SMALL_STRUCT5,%r21,%r0
+	ldi 8, %r22
+	addi,<> -FFI_TYPE_SMALL_STRUCT6,%r21,%r0
+	ldi 16, %r22
+	addi,<> -FFI_TYPE_SMALL_STRUCT7,%r21,%r0
+	ldi 24, %r22
+
+	/* This relies on all the FFI_TYPE_*_STRUCT* defines being <0 */
+	cmpib,<=,n 0, %r21, checkint8
+	mtsar %r22
+
+	shrpw %ret0, %ret1, %sar, %ret0  /* ret0 = aabbccdd */
+	shrpw %ret1, %ret1, %sar, %ret1  /* rotate ret1 */
+	
 	stw %ret0, 0(%r20)
 	b done
 	stw %ret1, 4(%r20)


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