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]

[PATCH] Fix complex argument handling in ppc64 dummy function call


Handle complex arguments for dummy function call on PPC64. I refactored the
code to extract the float logic into a function to reuse it for complex 
arguments as well - ABI defines that complex arguments are to be handled as 
if 2 float arguments were given.

This patch fixes the following PPC64 testcases:

? -FAIL: gdb.base/callfuncs.exp: p t_float_complex_values(fc1, fc2)
? -FAIL: gdb.base/callfuncs.exp: p t_float_complex_many_args(fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4, fc1, fc2, fc3, fc4)
? -FAIL: gdb.base/callfuncs.exp: p t_double_complex_values(dc1, dc2)
  -FAIL: gdb.base/callfuncs.exp: p t_double_complex_many_args(dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4, dc1, dc2, dc3, dc4)
? -FAIL: gdb.base/callfuncs.exp: p t_long_double_complex_values(ldc1, ldc2)
  -FAIL: gdb.base/callfuncs.exp: p t_long_double_complex_many_args(ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4, ldc1, ldc2, ldc3, ldc4)

No regressions detected on PPC32 and PPC64.

Cheers,
Tiago

gdb/ChangeLog
2013-02-05  Tiago Sturmer Daitx  <tdaitx@linux.vnet.ibm.com>

	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Handle complex 
	arguments.
	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_float): New functions to handle 
	float arguments.
 

diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
index 0ffeab9..690d65d 100644
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -1101,6 +1101,76 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
   return 1;
 }
 
+static void
+ppc64_sysv_abi_push_float (struct gdbarch *gdbarch, struct regcache *regcache,
+			   struct gdbarch_tdep *tdep, struct type *type, 
+			   const bfd_byte *val, int freg, int greg,
+			   CORE_ADDR gparam)
+{
+  gdb_byte regval[MAX_REGISTER_SIZE];
+  const gdb_byte *p;
+
+  if (TYPE_LENGTH (type) <= 8)
+    {
+      /* Version 1.7 of the 64-bit PowerPC ELF ABI says:
+
+	 "Single precision floating point values are mapped to
+	 the first word in a single doubleword."
+
+	 And version 1.9 says:
+
+	 "Single precision floating point values are mapped to
+	 the second word in a single doubleword."
+
+	 GDB then writes single precision floating point values
+	 at both words in a doubleword, to support both ABIs.  */
+      if (TYPE_LENGTH (type) == 4)
+	{
+	  memcpy (regval, val, 4);
+	  memcpy (regval + 4, val, 4);
+	  p = regval;
+	}
+      else
+	p = val;
+
+      /* Write value in the stack's parameter save area.  */
+      write_memory (gparam, p, 8);
+
+      /* Floats and Doubles go in f1 .. f13.  They also consume a left aligned 
+	 GREG, and can end up in memory.  */
+      if (freg <= 13)
+	{
+	  struct type *regtype;
+	  regtype = register_type (gdbarch, tdep->ppc_fp0_regnum + freg);
+
+	  convert_typed_floating (val, type, regval, regtype);
+	  regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, regval);
+	}
+      if (greg <= 10)
+	regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, regval);
+    }
+  else
+    {
+      /* IBM long double stored in two doublewords of the
+	 parameter save area and corresponding registers.  */
+      if (!tdep->soft_float && freg <= 13)
+	{
+	  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);
+	}
+      if (greg <= 10)
+	{
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, val);
+	  if (greg <= 9)
+	    regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 1,
+				   val + 8);
+	}
+      write_memory (gparam, val, TYPE_LENGTH (type));
+    }
+}
+
 /* Pass the arguments in either registers, or in the stack.  Using the
    ppc 64 bit SysV ABI.
 
@@ -1218,53 +1288,9 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
 
 	  if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) <= 8)
 	    {
-	      /* Floats and Doubles go in f1 .. f13.  They also
-	         consume a left aligned GREG,, and can end up in
-	         memory.  */
 	      if (write_pass)
-		{
-		  gdb_byte regval[MAX_REGISTER_SIZE];
-		  const gdb_byte *p;
-
-		  /* Version 1.7 of the 64-bit PowerPC ELF ABI says:
-
-		     "Single precision floating point values are mapped to
-		     the first word in a single doubleword."
-
-		     And version 1.9 says:
-
-		     "Single precision floating point values are mapped to
-		     the second word in a single doubleword."
-
-		     GDB then writes single precision floating point values
-		     at both words in a doubleword, to support both ABIs.  */
-		  if (TYPE_LENGTH (type) == 4)
-		    {
-		      memcpy (regval, val, 4);
-		      memcpy (regval + 4, val, 4);
-		      p = regval;
-		    }
-		  else
-		    p = val;
-
-		  /* Write value in the stack's parameter save area.  */
-		  write_memory (gparam, p, 8);
-
-		  if (freg <= 13)
-		    {
-		      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);
-		    }
-		  if (greg <= 10)
-		    regcache_cooked_write (regcache,
-					   tdep->ppc_gp0_regnum + greg,
-					   regval);
-		}
+		  ppc64_sysv_abi_push_float (gdbarch, regcache, tdep, type,
+					     val, freg, greg, gparam);
 
 	      freg++;
 	      greg++;
@@ -1276,36 +1302,55 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
 		   && (gdbarch_long_double_format (gdbarch)
 		       == floatformats_ibm_long_double))
 	    {
-	      /* IBM long double stored in two doublewords of the
-		 parameter save area and corresponding registers.  */
 	      if (write_pass)
-		{
-		  if (!tdep->soft_float && freg <= 13)
-		    {
-		      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);
-		    }
-		  if (greg <= 10)
-		    {
-		      regcache_cooked_write (regcache,
-					     tdep->ppc_gp0_regnum + greg,
-					     val);
-		      if (greg <= 9)
-			regcache_cooked_write (regcache,
-					       tdep->ppc_gp0_regnum + greg + 1,
-					       val + 8);
-		    }
-		  write_memory (gparam, val, TYPE_LENGTH (type));
-		}
+		ppc64_sysv_abi_push_float (gdbarch, regcache, tdep, type, 
+					   val, freg, greg, gparam);
 	      freg += 2;
 	      greg += 2;
 	      gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
 	    }
+          else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX
+              && (TYPE_LENGTH (type) == 8 || TYPE_LENGTH (type) == 16))
+            {
+              int i;
+              for (i = 0; i < 2; i++)
+                {
+                  if (write_pass)
+		    {
+		      struct type *target_type;
+		      target_type = check_typedef (TYPE_TARGET_TYPE (type));
+		      ppc64_sysv_abi_push_float (gdbarch, regcache, tdep, 
+						 target_type, val + i * 
+						 TYPE_LENGTH (target_type),
+						 freg, greg, gparam);
+		    }
+                  freg++;
+                  greg++;
+                  /* Always consume parameter stack space.  */
+                  gparam = align_up(gparam + 8, tdep->wordsize);
+                }
+            }
+          else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX
+                   && TYPE_LENGTH (type) == 32
+                   && (gdbarch_long_double_format (gdbarch)
+                       == floatformats_ibm_long_double))
+            {
+              int i;
+              for (i = 0; i < 2; i++)
+                {
+		  struct type *target_type;
+		  target_type = check_typedef (TYPE_TARGET_TYPE (type));
+                  if (write_pass)
+		    ppc64_sysv_abi_push_float (gdbarch, regcache, tdep, 
+					       target_type, val + i * 
+					       TYPE_LENGTH (target_type),
+					       freg, greg, gparam);
+                  freg += 2;
+                  greg += 2;
+                  gparam = align_up (gparam + TYPE_LENGTH (target_type),
+                                     tdep->wordsize);
+                }
+            }
 	  else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT
 		   && TYPE_LENGTH (type) <= 8)
 	    {


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