This is the mail archive of the gdb-patches@sources.redhat.com 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]

[rfa] Add e500 function call support to PPC


Hello,

This adds support for the e500's function call convention to the PPC (ppc-sysv-tdep.c to be exact).

The e500 passes everything in GPRs (which are extended to 64 bits).

ok?
Andrew
2003-03-08  Andrew Cagney  <cagney at redhat dot com>

	From Elena Zannoni  <ezannoni at redhat dot com>
	* ppc-sysv-tdep.c (ppc_sysv_abi_push_arguments): Handle e500
	vector and floating-point parameters.
	(ppc_sysv_abi_use_struct_convention): Handle e500 struct return
	convention.
	(ppc_sysv_abi_broken_use_struct_convention): Ditto.

Index: ppc-sysv-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-sysv-tdep.c,v
retrieving revision 1.3
diff -u -r1.3 ppc-sysv-tdep.c
--- ppc-sysv-tdep.c	14 Nov 2002 20:37:28 -0000	1.3
+++ ppc-sysv-tdep.c	8 Mar 2003 18:59:54 -0000
@@ -61,11 +61,12 @@
   int structstkspace;
   int argoffset;
   int structoffset;
-  struct value *arg;
   struct type *type;
   int len;
   char old_sp_buf[4];
   CORE_ADDR saved_sp;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (current_gdbarch);
 
   greg = struct_return ? 4 : 3;
   freg = 1;
@@ -79,11 +80,12 @@
      are put in registers. */
   for (argno = 0; argno < nargs; argno++)
     {
-      arg = args[argno];
+      struct value *arg = args[argno];
       type = check_typedef (VALUE_TYPE (arg));
       len = TYPE_LENGTH (type);
 
-      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+      if (TYPE_CODE (type) == TYPE_CODE_FLT
+          && arch_info->mach != bfd_mach_ppc_e500)
 	{
 	  if (freg <= 8)
 	    freg++;
@@ -96,7 +98,10 @@
 	      argstkspace += 8;
 	    }
 	}
-      else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8)	/* long long */
+      else if (len == 8 
+               && (TYPE_CODE (type) == TYPE_CODE_INT /* long long */
+                   || (arch_info->mach == bfd_mach_ppc_e500
+                       && TYPE_CODE (type) == TYPE_CODE_FLT))) /* double */
 	{
 	  if (greg > 9)
 	    {
@@ -144,6 +149,20 @@
 		  argstkspace += 16;
 		}
 	    }
+          else if (len == 8 
+                   && TYPE_CODE (type) == TYPE_CODE_ARRAY
+                   && TYPE_VECTOR (type))
+            {
+              if (greg <= 10)
+                greg++;
+              else
+                {
+                  /* Vector arguments must be aligned to 8 bytes on
+                     the stack. */
+                  argstkspace += round2 (argstkspace, 8);
+                  argstkspace += 8;
+                }
+            }
 	}
     }
 
@@ -170,30 +189,33 @@
   freg = 1;
   greg = 3;
   vreg = 2;
+
   /* Fill in r3 with the return structure, if any */
   if (struct_return)
     {
-      char val_buf[4];
-      store_address (val_buf, 4, struct_addr);
-      memcpy (&deprecated_registers[REGISTER_BYTE (greg)], val_buf, 4);
+      write_register (tdep->ppc_gp0_regnum + greg, struct_addr);
       greg++;
     }
+
   /* Now fill in the registers and stack... */
   for (argno = 0; argno < nargs; argno++)
     {
-      arg = args[argno];
+      struct value *arg = args[argno];
+      char *val = VALUE_CONTENTS (arg);
       type = check_typedef (VALUE_TYPE (arg));
       len = TYPE_LENGTH (type);
 
-      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+      if (TYPE_CODE (type) == TYPE_CODE_FLT
+          && arch_info->mach != bfd_mach_ppc_e500)
 	{
 	  if (freg <= 8)
 	    {
+	      ULONGEST regval;
 	      if (len > 8)
 		printf_unfiltered (
 				   "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
-	      memcpy (&deprecated_registers[REGISTER_BYTE (FP0_REGNUM + freg)],
-		      VALUE_CONTENTS (arg), len);
+              regval = extract_unsigned_integer (val, len);
+              write_register (FP0_REGNUM + freg, regval);
 	      freg++;
 	    }
 	  else
@@ -203,29 +225,32 @@
 	      /* FIXME: Convert floats to doubles */
 	      if (argoffset & 0x4)
 		argoffset += 4;
-	      write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len);
+	      write_memory (sp + argoffset, val, len);
 	      argoffset += 8;
 	    }
 	}
-      else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8)	/* long long */
+      else if (len == 8 
+               && (TYPE_CODE (type) == TYPE_CODE_INT /* long long */
+                   || (arch_info->mach == bfd_mach_ppc_e500
+                        && TYPE_CODE (type) == TYPE_CODE_FLT))) /* double */
 	{
 	  if (greg > 9)
 	    {
 	      greg = 11;
 	      if (argoffset & 0x4)
 		argoffset += 4;
-	      write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len);
+	      write_memory (sp + argoffset, val, len);
 	      argoffset += 8;
 	    }
 	  else
 	    {
+	      ULONGEST regval;
 	      if ((greg & 1) == 0)
 		greg++;
-
-	      memcpy (&deprecated_registers[REGISTER_BYTE (greg)],
-		      VALUE_CONTENTS (arg), 4);
-	      memcpy (&deprecated_registers[REGISTER_BYTE (greg + 1)],
-		      VALUE_CONTENTS (arg) + 4, 4);
+              regval = extract_unsigned_integer (val, 4);
+              write_register (tdep->ppc_gp0_regnum + greg, regval);
+              regval = extract_unsigned_integer (val + 4, 4);
+              write_register (tdep->ppc_gp0_regnum + greg + 1, regval);
 	      greg += 2;
 	    }
 	}
@@ -236,18 +261,19 @@
 	      || TYPE_CODE (type) == TYPE_CODE_STRUCT
 	      || TYPE_CODE (type) == TYPE_CODE_UNION)
 	    {
-	      write_memory (sp + structoffset, VALUE_CONTENTS (arg), len);
+	      write_memory (sp + structoffset, val, len);
 	      store_address (val_buf, 4, sp + structoffset);
 	      structoffset += round2 (len, 8);
 	    }
 	  else
 	    {
 	      memset (val_buf, 0, 4);
-	      memcpy (val_buf, VALUE_CONTENTS (arg), len);
+	      memcpy (val_buf, val, len);
 	    }
 	  if (greg <= 10)
 	    {
-	      memcpy (&deprecated_registers[REGISTER_BYTE (greg)], val_buf, 4);
+              ULONGEST regval = extract_unsigned_integer (val_buf, 4);
+              write_register (tdep->ppc_gp0_regnum + greg, regval);
 	      greg++;
 	    }
 	  else
@@ -262,15 +288,14 @@
 	      && TYPE_CODE (type) == TYPE_CODE_ARRAY
 	      && TYPE_VECTOR (type))
 	    {
-	      struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 	      char *v_val_buf = alloca (16);
 	      memset (v_val_buf, 0, 16);
-	      memcpy (v_val_buf, VALUE_CONTENTS (arg), len);
+	      memcpy (v_val_buf, val, len);
 	      if (vreg <= 13)
 		{
-		  memcpy (&deprecated_registers[REGISTER_BYTE (tdep->ppc_vr0_regnum
-						    + vreg)],
-			  v_val_buf, 16);
+		  regcache_cooked_write (current_regcache,
+					 tdep->ppc_vr0_regnum + vreg,
+					 v_val_buf);
 		  vreg++;
 		}
 	      else
@@ -279,6 +304,26 @@
 		  argoffset += 16;
 		}
 	    }
+          else if (len == 8 
+		   && TYPE_CODE (type) == TYPE_CODE_ARRAY
+		   && TYPE_VECTOR (type))
+            {
+              char *v_val_buf = alloca (8);
+              memset (v_val_buf, 0, 8);
+              memcpy (v_val_buf, val, len);
+              if (greg <= 10)
+                {
+		  regcache_cooked_write (current_regcache,
+					 tdep->ppc_ev0_regnum + greg,
+					 v_val_buf);
+                  greg++;
+                }
+              else
+                {
+                  write_memory (sp + argoffset, v_val_buf, 8);
+                  argoffset += 8;
+                }
+            }
         }
     }
 
@@ -293,7 +338,7 @@
 int     
 ppc_sysv_abi_broken_use_struct_convention (int gcc_p, struct type *value_type)
 {  
-  if (TYPE_LENGTH (value_type) == 16 
+  if ((TYPE_LENGTH (value_type) == 16 || TYPE_LENGTH (value_type) == 8)
       && TYPE_VECTOR (value_type))
     return 0;                            
 
@@ -305,7 +350,7 @@
 int
 ppc_sysv_abi_use_struct_convention (int gcc_p, struct type *value_type)
 {
-  if (TYPE_LENGTH (value_type) == 16
+  if ((TYPE_LENGTH (value_type) == 16 || TYPE_LENGTH (value_type) == 8)
       && TYPE_VECTOR (value_type))
     return 0;
 

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