This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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]

Fix ppc64 structs ABI issue


A number of the gdb.base/structs.exp tests fail for 64-bit Power
because GDB does not implement the currently specified and implemented
ABI
<http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html>.
There are two specific ABI problems:

* GDB is expecting GCC bugs fixed in 3.4 and had comments that appear
  to relate to an ABI version 1.5 or older (the revision history for
  1.6 says "structure passing" as what's fixed).

* GDB fails to allow for the rule about single-element structs
  containing floating point values (version 1.8 says "single element
  FP structs", presumably the ABI was fixed to agree with the
  implementation), with a comment describing this as a GCC bug
  instead.  (Said comment also appeared as the sole contents of an if,

  if (write_pass)
    /* comment */
  next statement;

so it seems that statement was unintentionally conditional.)

I think the right thing to do here is to implement the ABI as it now
is documented and implemented, and not try to allow for the bugs of
very old compilers.  This is what this patch does.

The ABI rule on single-element structs applies to those where the
floating-point value is at any level of nesting of single-element
structs, but does not apply to unions.

This patch is relative to a tree with both Daniel's ABI detection
patch and my IBM long double patch
<http://sourceware.org/ml/gdb-patches/2007-10/msg00687.html>.  Tested
with cross to powerpc-linux-gnu, -m64.  OK to commit once those
previous patches are in?

2007-10-25  Joseph Myers  <joseph@codesourcery.com>
	    Daniel Jacobowitz  <dan@codesourcery.com>

	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Right-align
	struct values smaller than one doubleword; left-align those
	larger.  Pass structs containing a single floating-point value in
	registers.

diff -rupN gdb-mainline/gdb/ppc-sysv-tdep.c gdb-mainline.ppc64/gdb/ppc-sysv-tdep.c
--- gdb-mainline/gdb/ppc-sysv-tdep.c	2007-10-25 15:08:22.000000000 -0700
+++ gdb-mainline.ppc64/gdb/ppc-sysv-tdep.c	2007-10-25 16:24:51.000000000 -0700
@@ -939,22 +939,17 @@ ppc64_sysv_abi_push_dummy_call (struct g
 		      if (len > tdep->wordsize)
 			len = tdep->wordsize;
 		      memset (regval, 0, sizeof regval);
-		      /* WARNING: cagney/2003-09-21: As best I can
-		         tell, the ABI specifies that the value should
-		         be left aligned.  Unfortunately, GCC doesn't
-		         do this - it instead right aligns even sized
-		         values and puts odd sized values on the
-		         stack.  Work around that by putting both a
-		         left and right aligned value into the
-		         register (hopefully no one notices :-^).
-		         Arrrgh!  */
-		      /* Left aligned (8 byte values such as pointers
-		         fill the buffer).  */
-		      memcpy (regval, val + byte, len);
-		      /* Right aligned (but only if even).  */
-		      if (len == 1 || len == 2 || len == 4)
+		      /* The ABI (version 1.9) specifies that values
+			 smaller than one doubleword are right-aligned
+			 and those larger are left-aligned.  GCC
+			 versions before 3.4 implemented this
+			 incorrectly; see
+			 <http://gcc.gnu.org/gcc-3.4/powerpc-abi.html>.  */
+		      if (byte == 0)
 			memcpy (regval + tdep->wordsize - len,
 				val + byte, len);
+		      else
+			memcpy (regval, val + byte, len);
 		      regcache_cooked_write (regcache, greg, regval);
 		    }
 		  greg++;
@@ -968,11 +963,57 @@ ppc64_sysv_abi_push_dummy_call (struct g
 		   value to memory.  Fortunately, doing this
 		   simplifies the code.  */
 		write_memory (gparam, val, TYPE_LENGTH (type));
-	      if (write_pass)
-		/* WARNING: cagney/2004-06-20: It appears that GCC
-		   likes to put structures containing a single
-		   floating-point member in an FP register instead of
-		   general general purpose.  */
+	      if (freg <= 13
+		  && TYPE_CODE (type) == TYPE_CODE_STRUCT
+		  && TYPE_NFIELDS (type) == 1
+		  && TYPE_LENGTH (type) <= 16)
+		{
+		  /* The ABI (version 1.9) specifies that structs
+		     containing a single floating-point value, at any
+		     level of nesting of single-member structs, are
+		     passed in floating-point registers.  */
+		  while (TYPE_CODE (type) == TYPE_CODE_STRUCT
+			 && TYPE_NFIELDS (type) == 1)
+		    type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+		  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+		    {
+		      if (TYPE_LENGTH (type) <= 8)
+			{
+			  if (write_pass)
+			    {
+			      gdb_byte regval[MAX_REGISTER_SIZE];
+			      struct type *regtype
+				= register_type (gdbarch,
+						 tdep->ppc_fp0_regnum);
+			      convert_typed_floating (val, type, regval,
+						      regtype);
+			      regcache_cooked_write (regcache,
+						     (tdep->ppc_fp0_regnum
+						      + freg),
+						     regval);
+			    }
+			  freg++;
+			}
+		      else if (TYPE_LENGTH (type) == 16
+			       && (gdbarch_long_double_format (current_gdbarch)
+				   == floatformats_ibm_long_double))
+			{
+			  if (write_pass)
+			    {
+			      regcache_cooked_write (regcache,
+						     (tdep->ppc_fp0_regnum
+						      + freg),
+						     val);
+			      if (freg <= 12)
+				regcache_cooked_write (regcache,
+						       (tdep->ppc_fp0_regnum
+							+ freg + 1),
+						       val + 8);
+			    }
+			  freg += 2;
+			}
+		    }
+		}
 	      /* Always consume parameter stack space.  */
 	      gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
 	    }

-- 
Joseph S. Myers
joseph@codesourcery.com


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