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]

Re: [rfc] PowerPC ABI detection and overrides


On Thu, Oct 25, 2007 at 03:59:32PM -0400, Daniel Jacobowitz wrote:
> The patch makes GDB look at ABI markings in ELF files for both hard
> versus soft floating point and AltiVec versus SPE versus generic
> vectors.  There are also new commands to force the right behavior
> and documentation for them.

Here's what I checked in.  This skips some of the tests when using ELF
without ABI markings, but still runs enough to be useful - the tests
fail in a way that's hard to XFAIL, since the generic ABI uses
pass by reference so we end up with bad pointers.

Tested on powerpc-linux using gdbserver, -maltivec, -mabi=altivec.
Checked in.

-- 
Daniel Jacobowitz
CodeSourcery

2007-10-30  Daniel Jacobowitz  <dan@codesourcery.com>

	* ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Check the selected
	soft float and vector ABIs.  Support the generic vector ABI for
	AltiVec types.
	(do_ppc_sysv_return_value): Likewise.  Correct argument types and
	casts.
	(ppc64_sysv_abi_push_dummy_call): Assert that floating point is
	supported.
	* ppc-tdep.h (enum powerpc_vector_abi): New.
	(struct gdbarch_tdep): Add soft_float and vector_abi.
	* rs6000-tdep.c (setpowerpccmdlist, showpowerpccmdlist)
	(powerpc_soft_float_global, powerpc_vector_strings)
	(powerpc_vector_abi_global, powerpc_vector_abi_string): New.
	(rs6000_gdbarch_init): Check for soft-float and vector ABI markings.
	(set_powerpc_command, show_powerpc_command, powerpc_set_soft_float)
	(powerpc_set_vector_abi): New.
	(_initialize_rs6000_tdep): Register "set powerpc" and "show powerpc"
	commands.
	* Makefile.in (elf_ppc_h): New.
	(rs6000-tdep.o): Update.

2007-10-30  Daniel Jacobowitz  <dan@codesourcery.com>

	* gdb.texinfo (PowerPC): Document "set powerpc vector-abi" and "set
	powerpc soft-float".

2007-10-30  Daniel Jacobowitz  <dan@codesourcery.com>

	* gdb.arch/altivec-abi.exp: Run multiple times for GCC on GNU/Linux.
	Test "set powerpc vector-abi".  Skip auto-detection tests for old
	toolchains.

Index: Makefile.in
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/Makefile.in,v
retrieving revision 1.954
diff -u -p -r1.954 Makefile.in
--- Makefile.in	25 Oct 2007 17:52:31 -0000	1.954
+++ Makefile.in	30 Oct 2007 15:06:46 -0000
@@ -604,6 +604,7 @@ elf_bfd_h =	$(BFD_SRC)/elf-bfd.h
 elf_frv_h =	$(INCLUDE_DIR)/elf/frv.h $(elf_reloc_macros_h)
 elf_m32c_h =    $(INCLUDE_DIR)/elf/m32c.h $(elf_reloc_macros_h)
 elf_mep_h =     $(INCLUDE_DIR)/elf/mep.h $(elf_reloc_macros_h)
+elf_ppc_h =     $(INCLUDE_DIR)/elf/ppc.h $(elf_reloc_macros_h)
 libaout_h =	$(BFD_SRC)/libaout.h
 libiberty_h =	$(INCLUDE_DIR)/libiberty.h
 libbfd_h =	$(BFD_SRC)/libbfd.h
@@ -2578,7 +2579,7 @@ rs6000-tdep.o: rs6000-tdep.c $(defs_h) $
 	$(coff_xcoff_h) $(libxcoff_h) $(elf_bfd_h) $(solib_svr4_h) \
 	$(ppc_tdep_h) $(gdb_assert_h) $(dis_asm_h) $(trad_frame_h) \
 	$(frame_unwind_h) $(frame_base_h) $(rs6000_tdep_h) $(dwarf2_frame_h) \
-	$(target_descriptions) $(user_regs_h) \
+	$(target_descriptions) $(user_regs_h) $(elf_ppc_h) \
 	$(powerpc_32_c) $(powerpc_403_c) $(powerpc_403gc_c) $(powerpc_505_c) \
 	$(powerpc_601_c) $(powerpc_602_c) $(powerpc_603_c) $(powerpc_604_c) \
 	$(powerpc_64_c) $(powerpc_7400_c) $(powerpc_750_c) $(powerpc_860_c) \
Index: ppc-sysv-tdep.c
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/ppc-sysv-tdep.c,v
retrieving revision 1.40
diff -u -p -r1.40 ppc-sysv-tdep.c
--- ppc-sysv-tdep.c	6 Sep 2007 20:21:16 -0000	1.40
+++ ppc-sysv-tdep.c	30 Oct 2007 15:38:38 -0000
@@ -104,8 +104,8 @@ ppc_sysv_abi_push_dummy_call (struct gdb
 	  int len = TYPE_LENGTH (type);
 	  const bfd_byte *val = value_contents (arg);
 
-	  if (TYPE_CODE (type) == TYPE_CODE_FLT
-	      && ppc_floating_point_unit_p (current_gdbarch) && len <= 8)
+	  if (TYPE_CODE (type) == TYPE_CODE_FLT && len <= 8
+	      && !tdep->soft_float)
 	    {
 	      /* Floating point value converted to "double" then
 	         passed in an FP register, when the registers run out,
@@ -141,10 +141,11 @@ ppc_sysv_abi_push_dummy_call (struct gdb
 		  argoffset += 8;
 		}
 	    }
-	  else if (len == 8 && (TYPE_CODE (type) == TYPE_CODE_INT	/* long long */
-				|| (!ppc_floating_point_unit_p (current_gdbarch) && TYPE_CODE (type) == TYPE_CODE_FLT)))	/* double */
+	  else if (len == 8
+		   && (TYPE_CODE (type) == TYPE_CODE_INT	/* long long */
+		       || TYPE_CODE (type) == TYPE_CODE_FLT))	/* double */
 	    {
-	      /* "long long" or "double" passed in an odd/even
+	      /* "long long" or soft-float "double" passed in an odd/even
 	         register pair with the low addressed word in the odd
 	         register and the high addressed word in the even
 	         register, or when the registers run out an 8 byte
@@ -184,7 +185,8 @@ ppc_sysv_abi_push_dummy_call (struct gdb
 	    }
 	  else if (len == 16
 		   && TYPE_CODE (type) == TYPE_CODE_ARRAY
-		   && TYPE_VECTOR (type) && tdep->ppc_vr0_regnum >= 0)
+		   && TYPE_VECTOR (type)
+		   && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
 	    {
 	      /* Vector parameter passed in an Altivec register, or
 	         when that runs out, 16 byte aligned stack location.  */
@@ -205,7 +207,8 @@ ppc_sysv_abi_push_dummy_call (struct gdb
 	    }
 	  else if (len == 8
 		   && TYPE_CODE (type) == TYPE_CODE_ARRAY
-		   && TYPE_VECTOR (type) && tdep->ppc_ev0_regnum >= 0)
+		   && TYPE_VECTOR (type)
+		   && tdep->vector_abi == POWERPC_VEC_SPE)
 	    {
 	      /* Vector parameter passed in an e500 register, or when
 	         that runs out, 8 byte aligned stack location.  Note
@@ -239,9 +242,15 @@ ppc_sysv_abi_push_dummy_call (struct gdb
 		  || TYPE_CODE (type) == TYPE_CODE_STRUCT
 		  || TYPE_CODE (type) == TYPE_CODE_UNION)
 		{
-		  /* Structs and large values are put on an 8 byte
-		     aligned stack ... */
-		  structoffset = align_up (structoffset, 8);
+		  /* Structs and large values are put in an
+		     aligned stack slot ... */
+		  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+		      && TYPE_VECTOR (type)
+		      && len >= 16)
+		    structoffset = align_up (structoffset, 16);
+		  else
+		    structoffset = align_up (structoffset, 8);
+
 		  if (write_pass)
 		    write_memory (sp + structoffset, val, len);
 		  /* ... and then a "word" pointing to that address is
@@ -337,14 +346,14 @@ ppc_sysv_abi_push_dummy_call (struct gdb
 
 static enum return_value_convention
 do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
-			  struct regcache *regcache, void *readbuf,
-			  const void *writebuf, int broken_gcc)
+			  struct regcache *regcache, gdb_byte *readbuf,
+			  const gdb_byte *writebuf, int broken_gcc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   gdb_assert (tdep->wordsize == 4);
   if (TYPE_CODE (type) == TYPE_CODE_FLT
       && TYPE_LENGTH (type) <= 8
-      && ppc_floating_point_unit_p (gdbarch))
+      && !tdep->soft_float)
     {
       if (readbuf)
 	{
@@ -374,17 +383,17 @@ do_ppc_sysv_return_value (struct gdbarch
 	{
 	  /* A long long, or a double stored in the 32 bit r3/r4.  */
 	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
-				(bfd_byte *) readbuf + 0);
+				readbuf + 0);
 	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
-				(bfd_byte *) readbuf + 4);
+				readbuf + 4);
 	}
       if (writebuf)
 	{
 	  /* A long long, or a double stored in the 32 bit r3/r4.  */
 	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
-				 (const bfd_byte *) writebuf + 0);
+				 writebuf + 0);
 	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
-				 (const bfd_byte *) writebuf + 4);
+				 writebuf + 4);
 	}
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -417,7 +426,8 @@ do_ppc_sysv_return_value (struct gdbarch
     }
   if (TYPE_LENGTH (type) == 16
       && TYPE_CODE (type) == TYPE_CODE_ARRAY
-      && TYPE_VECTOR (type) && tdep->ppc_vr0_regnum >= 0)
+      && TYPE_VECTOR (type)
+      && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
     {
       if (readbuf)
 	{
@@ -431,9 +441,42 @@ do_ppc_sysv_return_value (struct gdbarch
 	}
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
+  if (TYPE_LENGTH (type) == 16
+      && TYPE_CODE (type) == TYPE_CODE_ARRAY
+      && TYPE_VECTOR (type)
+      && tdep->vector_abi == POWERPC_VEC_GENERIC)
+    {
+      /* GCC -maltivec -mabi=no-altivec returns vectors in r3/r4/r5/r6.
+	 GCC without AltiVec returns them in memory, but it warns about
+	 ABI risks in that case; we don't try to support it.  */
+      if (readbuf)
+	{
+	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+				readbuf + 0);
+	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+				readbuf + 4);
+	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5,
+				readbuf + 8);
+	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6,
+				readbuf + 12);
+	}
+      if (writebuf)
+	{
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+				 writebuf + 0);
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+				 writebuf + 4);
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5,
+				 writebuf + 8);
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6,
+				 writebuf + 12);
+	}
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
   if (TYPE_LENGTH (type) == 8
       && TYPE_CODE (type) == TYPE_CODE_ARRAY
-      && TYPE_VECTOR (type) && tdep->ppc_ev0_regnum >= 0)
+      && TYPE_VECTOR (type)
+      && tdep->vector_abi == POWERPC_VEC_SPE)
     {
       /* The e500 ABI places return values for the 64-bit DSP types
 	 (__ev64_opaque__) in r3.  However, in GDB-speak, ev3
@@ -604,6 +647,11 @@ ppc64_sysv_abi_push_dummy_call (struct g
      the possible values of tdep->wordsize.  */
   gdb_assert (tdep->wordsize == 8);
 
+  /* This function exists to support a calling convention that
+     requires floating-point registers.  It shouldn't be used on
+     processors that lack them.  */
+  gdb_assert (ppc_floating_point_unit_p (gdbarch));
+
   /* By this stage in the proceedings, SP has been decremented by "red
      zone size" + "struct return size".  Fetch the stack-pointer from
      before this and use that as the BACK_CHAIN.  */
@@ -685,8 +733,7 @@ ppc64_sysv_abi_push_dummy_call (struct g
 	         memory.  */
 	      if (write_pass)
 		{
-		  if (ppc_floating_point_unit_p (current_gdbarch)
-		      && freg <= 13)
+		  if (freg <= 13)
 		    {
 		      gdb_byte regval[MAX_REGISTER_SIZE];
 		      struct type *regtype
@@ -869,7 +916,7 @@ ppc64_sysv_abi_push_dummy_call (struct g
 }
 
 
-/* The 64 bit ABI retun value convention.
+/* The 64 bit ABI return value convention.
 
    Return non-zero if the return-value is stored in a register, return
    0 if the return-value is instead stored on the stack (a.k.a.,
Index: ppc-tdep.h
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/ppc-tdep.h,v
retrieving revision 1.59
diff -u -p -r1.59 ppc-tdep.h
--- ppc-tdep.h	29 Oct 2007 20:26:42 -0000	1.59
+++ ppc-tdep.h	30 Oct 2007 15:06:46 -0000
@@ -157,9 +157,24 @@ extern void ppc_collect_vrregset (const 
 
 /* Private data that this module attaches to struct gdbarch. */
 
+/* Vector ABI used by the inferior.  */
+enum powerpc_vector_abi
+{
+  POWERPC_VEC_AUTO,
+  POWERPC_VEC_GENERIC,
+  POWERPC_VEC_ALTIVEC,
+  POWERPC_VEC_SPE,
+  POWERPC_VEC_LAST
+};
+
 struct gdbarch_tdep
   {
-    int wordsize;              /* size in bytes of fixed-point word */
+    int wordsize;		/* Size in bytes of fixed-point word.  */
+    int soft_float;		/* Avoid FP registers for arguments?  */
+
+    /* How to pass vector arguments.  Never set to AUTO or LAST.  */
+    enum powerpc_vector_abi vector_abi;
+
     int ppc_gp0_regnum;		/* GPR register 0 */
     int ppc_toc_regnum;		/* TOC register */
     int ppc_ps_regnum;	        /* Processor (or machine) status (%msr) */
Index: rs6000-tdep.c
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.294
diff -u -p -r1.294 rs6000-tdep.c
--- rs6000-tdep.c	29 Oct 2007 20:26:42 -0000	1.294
+++ rs6000-tdep.c	30 Oct 2007 15:06:46 -0000
@@ -49,6 +49,7 @@
 #include "libxcoff.h"
 
 #include "elf-bfd.h"
+#include "elf/ppc.h"
 
 #include "solib-svr4.h"
 #include "ppc-tdep.h"
@@ -77,6 +78,27 @@
 #include "features/rs6000/powerpc-e500.c"
 #include "features/rs6000/rs6000.c"
 
+/* The list of available "set powerpc ..." and "show powerpc ..."
+   commands.  */
+static struct cmd_list_element *setpowerpccmdlist = NULL;
+static struct cmd_list_element *showpowerpccmdlist = NULL;
+
+static enum auto_boolean powerpc_soft_float_global = AUTO_BOOLEAN_AUTO;
+
+/* The vector ABI to use.  Keep this in sync with powerpc_vector_abi.  */
+static const char *powerpc_vector_strings[] =
+{
+  "auto",
+  "generic",
+  "altivec",
+  "spe",
+  NULL
+};
+
+/* A variable that can be configured by the user.  */
+static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO;
+static const char *powerpc_vector_abi_string = "auto";
+
 /* If the kernel has to deliver a signal, it pushes a sigcontext
    structure on the stack and then calls the signal handler, passing
    the address of the sigcontext in an argument register. Usually
@@ -3145,6 +3167,9 @@ rs6000_gdbarch_init (struct gdbarch_info
   bfd abfd;
   int sysv_abi;
   asection *sect;
+  enum auto_boolean soft_float_flag = powerpc_soft_float_global;
+  int soft_float;
+  enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
   int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0;
   int tdesc_wordsize = -1;
   const struct target_desc *tdesc = info.target_desc;
@@ -3417,6 +3442,76 @@ rs6000_gdbarch_init (struct gdbarch_info
       return NULL;
     }
 
+#ifdef HAVE_ELF
+  if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec)
+    {
+      switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
+					Tag_GNU_Power_ABI_FP))
+	{
+	case 1:
+	  soft_float_flag = AUTO_BOOLEAN_FALSE;
+	  break;
+	case 2:
+	  soft_float_flag = AUTO_BOOLEAN_TRUE;
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  if (vector_abi == POWERPC_VEC_AUTO && from_elf_exec)
+    {
+      switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
+					Tag_GNU_Power_ABI_Vector))
+	{
+	case 1:
+	  vector_abi = POWERPC_VEC_GENERIC;
+	  break;
+	case 2:
+	  vector_abi = POWERPC_VEC_ALTIVEC;
+	  break;
+	case 3:
+	  vector_abi = POWERPC_VEC_SPE;
+	  break;
+	default:
+	  break;
+	}
+    }
+#endif
+
+  if (soft_float_flag == AUTO_BOOLEAN_TRUE)
+    soft_float = 1;
+  else if (soft_float_flag == AUTO_BOOLEAN_FALSE)
+    soft_float = 0;
+  else
+    soft_float = !have_fpu;
+
+  /* If we have a hard float binary or setting but no floating point
+     registers, downgrade to soft float anyway.  We're still somewhat
+     useful in this scenario.  */
+  if (!soft_float && !have_fpu)
+    soft_float = 1;
+
+  /* Similarly for vector registers.  */
+  if (vector_abi == POWERPC_VEC_ALTIVEC && !have_altivec)
+    vector_abi = POWERPC_VEC_GENERIC;
+
+  if (vector_abi == POWERPC_VEC_SPE && !have_spe)
+    vector_abi = POWERPC_VEC_GENERIC;
+
+  if (vector_abi == POWERPC_VEC_AUTO)
+    {
+      if (have_altivec)
+	vector_abi = POWERPC_VEC_ALTIVEC;
+      else if (have_spe)
+	vector_abi = POWERPC_VEC_SPE;
+      else
+	vector_abi = POWERPC_VEC_GENERIC;
+    }
+
+  /* Do not limit the vector ABI based on available hardware, since we
+     do not yet know what hardware we'll decide we have.  Yuck!  FIXME!  */
+
   /* Find a candidate among extant architectures.  */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
        arches != NULL;
@@ -3426,6 +3521,10 @@ rs6000_gdbarch_init (struct gdbarch_info
          meaningful, because 64-bit CPUs can run in 32-bit mode.  So, perform
          separate word size check.  */
       tdep = gdbarch_tdep (arches->gdbarch);
+      if (tdep && tdep->soft_float != soft_float)
+	continue;
+      if (tdep && tdep->vector_abi != vector_abi)
+	continue;
       if (tdep && tdep->wordsize == wordsize)
 	{
 	  if (tdesc_data != NULL)
@@ -3444,6 +3543,8 @@ rs6000_gdbarch_init (struct gdbarch_info
 
   tdep = XCALLOC (1, struct gdbarch_tdep);
   tdep->wordsize = wordsize;
+  tdep->soft_float = soft_float;
+  tdep->vector_abi = vector_abi;
 
   gdbarch = gdbarch_alloc (&info, tdep);
 
@@ -3643,6 +3744,61 @@ rs6000_dump_tdep (struct gdbarch *gdbarc
   /* FIXME: Dump gdbarch_tdep.  */
 }
 
+/* PowerPC-specific commands.  */
+
+static void
+set_powerpc_command (char *args, int from_tty)
+{
+  printf_unfiltered (_("\
+\"set powerpc\" must be followed by an appropriate subcommand.\n"));
+  help_list (setpowerpccmdlist, "set powerpc ", all_commands, gdb_stdout);
+}
+
+static void
+show_powerpc_command (char *args, int from_tty)
+{
+  cmd_show_list (showpowerpccmdlist, from_tty, "");
+}
+
+static void
+powerpc_set_soft_float (char *args, int from_tty,
+			struct cmd_list_element *c)
+{
+  struct gdbarch_info info;
+
+  /* Update the architecture.  */
+  gdbarch_info_init (&info);
+  if (!gdbarch_update_p (info))
+    internal_error (__FILE__, __LINE__, "could not update architecture");
+}
+
+static void
+powerpc_set_vector_abi (char *args, int from_tty,
+			struct cmd_list_element *c)
+{
+  struct gdbarch_info info;
+  enum powerpc_vector_abi vector_abi;
+
+  for (vector_abi = POWERPC_VEC_AUTO;
+       vector_abi != POWERPC_VEC_LAST;
+       vector_abi++)
+    if (strcmp (powerpc_vector_abi_string,
+		powerpc_vector_strings[vector_abi]) == 0)
+      {
+	powerpc_vector_abi_global = vector_abi;
+	break;
+      }
+
+  if (vector_abi == POWERPC_VEC_LAST)
+    internal_error (__FILE__, __LINE__, _("Invalid vector ABI accepted: %s."),
+		    powerpc_vector_abi_string);
+
+  /* Update the architecture.  */
+  gdbarch_info_init (&info);
+  if (!gdbarch_update_p (info))
+    internal_error (__FILE__, __LINE__, "could not update architecture");
+}
+
 /* Initialization code.  */
 
 extern initialize_file_ftype _initialize_rs6000_tdep; /* -Wmissing-prototypes */
@@ -3668,4 +3824,30 @@ _initialize_rs6000_tdep (void)
   initialize_tdesc_powerpc_860 ();
   initialize_tdesc_powerpc_e500 ();
   initialize_tdesc_rs6000 ();
+
+  /* Add root prefix command for all "set powerpc"/"show powerpc"
+     commands.  */
+  add_prefix_cmd ("powerpc", no_class, set_powerpc_command,
+		  _("Various PowerPC-specific commands."),
+		  &setpowerpccmdlist, "set powerpc ", 0, &setlist);
+
+  add_prefix_cmd ("powerpc", no_class, show_powerpc_command,
+		  _("Various PowerPC-specific commands."),
+		  &showpowerpccmdlist, "show powerpc ", 0, &showlist);
+
+  /* Add a command to allow the user to force the ABI.  */
+  add_setshow_auto_boolean_cmd ("soft-float", class_support,
+				&powerpc_soft_float_global,
+				_("Set whether to use a soft-float ABI."),
+				_("Show whether to use a soft-float ABI."),
+				NULL,
+				powerpc_set_soft_float, NULL,
+				&setpowerpccmdlist, &showpowerpccmdlist);
+
+  add_setshow_enum_cmd ("vector-abi", class_support, powerpc_vector_strings,
+			&powerpc_vector_abi_string,
+			_("Set the vector ABI."),
+			_("Show the vector ABI."),
+			NULL, powerpc_set_vector_abi, NULL,
+			&setpowerpccmdlist, &showpowerpccmdlist);
 }
Index: doc/gdb.texinfo
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.440
diff -u -p -r1.440 gdb.texinfo
--- doc/gdb.texinfo	24 Oct 2007 21:05:36 -0000	1.440
+++ doc/gdb.texinfo	30 Oct 2007 15:06:46 -0000
@@ -14937,7 +14937,25 @@ Set suspend trace mode.
 @node PowerPC
 @subsection PowerPC
 
+@value{GDBN} provides the following PowerPC-specific commands:
+
 @table @code
+@kindex set powerpc
+@item set powerpc soft-float
+@itemx show powerpc soft-float
+Force @value{GDBN} to use (or not use) a software floating point calling
+convention.  By default, @value{GDBN} selects the calling convention based
+on the selected architecture and the provided executable file.
+
+@item set powerpc vector-abi
+@itemx show powerpc vector-abi
+Force @value{GDBN} to use the specified calling convention for vector
+arguments and return values.  The valid options are @samp{auto};
+@samp{generic}, to avoid vector registers even if they are present;
+@samp{altivec}, to use AltiVec registers; and @samp{spe} to use SPE
+registers.  By default, @value{GDBN} selects the calling convention
+based on the selected architecture and the provided executable file.
+
 @kindex target dink32
 @item target dink32 @var{dev}
 DINK32 ROM monitor.
@@ -14955,7 +14973,7 @@ SDS monitor, running on a PowerPC board 
 
 @cindex SDS protocol
 The following commands specific to the SDS protocol are supported
-by@value{GDBN}:
+by @value{GDBN}:
 
 @table @code
 @item set sdstimeout @var{nsec}
Index: testsuite/gdb.arch/altivec-abi.exp
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/testsuite/gdb.arch/altivec-abi.exp,v
retrieving revision 1.12
diff -u -p -r1.12 altivec-abi.exp
--- testsuite/gdb.arch/altivec-abi.exp	21 Oct 2007 12:28:00 -0000	1.12
+++ testsuite/gdb.arch/altivec-abi.exp	30 Oct 2007 19:07:28 -0000
@@ -13,9 +13,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-# Please email any bugs, comments, and/or additions to this file to:
-# bug-gdb@prep.ai.mit.edu
-#
 
 # Tests for Powerpc AltiVec ABI
 
@@ -28,9 +25,6 @@ if $tracelevel then {
 # This file uses altivec-abi.c for input.
 #
 
-set prms_id 0
-set bug_id 0
-
 if {![istarget "powerpc*"] || [skip_altivec_tests]} then {
     verbose "Skipping altivec abi tests."
     verbose -log "Skipping altivec abi tests."
@@ -41,88 +35,124 @@ set testfile "altivec-abi"
 set binfile ${objdir}/${subdir}/${testfile}
 set srcfile ${testfile}.c
 
-set compile_flags {debug nowarnings}
 if [get_compiler_info $binfile] {
     warning "get_compiler failed"
     return -1
 }
 
+proc altivec_abi_tests { extra_flags force_abi } {
+    global testfile binfile srcfile srcdir subdir
+    global gdb_prompt
+
+    set compile_flags "debug nowarnings $extra_flags"
+
+    if  { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $compile_flags] != "" } {
+	untested altivec-abi.exp
+	return -1
+    }
+
+    if { "$force_abi" == "auto" } {
+	# If the toolchain does not record attributes, skip auto-ABI tests.
+	set readelf_program [transform readelf]
+	set result [catch "exec $readelf_program -A $binfile" output]
+
+	if {$result == 0 && ![regexp Tag_GNU_Power_ABI_Vector $output]} {
+	    untested "ABI not marked"
+	    return
+	}
+    }
+
+    gdb_exit
+    gdb_start
+    gdb_reinitialize_dir $srcdir/$subdir
+    gdb_load ${binfile}
+
+    # Run to `main' where we begin our tests.
+    if ![runto_main] then {
+	untested altivec-abi.exp
+	return -1
+    }
+
+    gdb_test "set powerpc vector-abi $force_abi"
+
+    gdb_test "b marker" "Breakpoint 2 at.*file.*altivec-abi.c, line \[0-9\]+." "break marker"
+    gdb_test "continue" "Breakpoint 2.*marker.*altivec-abi.c.*" "continue to marker"
+    gdb_test "finish" "Run till exit from .0.*marker.*at.*altivec-abi.c.*main \\(\\) at.*altivec-abi.c.*result = vec_func \\(vshort,.*goes in v2.*" "back to main (1)"
+
+    # now all the arguments of vec_fun are initialized
+
+    set pattern "vec_func .vshort_f=.111, 222, 333, 444, 555, 666, 777, 888., vushort_f=.100, 200, 300, 400, 500, 600, 700, 800., vint_f=.-10, -20, -30, -40., vuint_f=.1111, 2222, 3333, 4444., vchar_f=.abcdefghilmnopqr., vuchar_f=.ABCDEFGHILMNOPQR., vfloat_f=.1.25, 3.75, 5.5, 1.25., x_f=.1, 2, 3, 4, 5, 6, 7, 8., y_f=.12, 22, 32, 42., a_f=.vector of chars.., b_f=.5.5, 4.5, 3.75, 2.25., c_f=.1.25, 3.5, 5.5, 7.75., intv_on_stack_f=.12, 34, 56, 78.."
+
+    set pattern1 $pattern
+    append pattern1 " at.*altivec-abi.c.*vint_res  = vec_add.*vint_f, intv_on_stack_f.;"
+
+    # Now let's call the function.  This function has > 12 args,
+    # the last one will go on the stack.
+    set msg "call inferior function with vectors (1)"
+    gdb_test "p vec_func(vshort,vushort,vint,vuint,vchar,vuchar,vfloat,x,y,a,b,c,intv_on_stack)" \
+	".\[0-9\]+ = .2, 2, 2, 2." "call inferior function with vectors (1)"
+
+    # Let's call the function again with dummy arguments.  This is to clean
+    # up the contents of the vector registers before the next call.
+    gdb_test "p vec_func(vshort_d,vushort_d,vint_d,vuint_d,vchar_d,vuchar_d,vfloat_d,x_d,y_d,a_d,b_d,c_d,intv_on_stack_d)" \
+	".\[0-9\]+ = .0, 0, 0, 0." "call inferior function with vectors (2)"
+
+    # Let's step into the function, to see if the args are printed correctly.
+    gdb_test "step" \
+	$pattern1 \
+	"step into vec_fun"
+
+    set pattern2 $pattern
+    append pattern2 " at.*altivec-abi.c.*main.*result = vec_func .vshort,.*goes in v2.*Value returned is.*= .2, 2, 2, 2."
+
+    # Let's see if the result is returned correctly.
+    gdb_test "finish" "Run till exit from .0.*$pattern2" \
+	"vector value returned correctly"
+
+    # can we print the args correctly for this function?
+    gdb_test "break struct_of_vector_func" "" ""
+
+    set pattern "struct_of_vector_func .vector_struct=.vshort1 = .1, 2, 3, 4, 5, 6, 7, 8., vshort2 = .11, 12, 13, 14, 15, 16, 17, 18., vshort3 = .21, 22, 23, 24, 25, 26, 27, 28., vshort4 = .31, 32, 33, 34, 35, 36, 37, 38... at.*altivec-abi.c.*"
+
+    gdb_test "continue" \
+	"Breakpoint 3, $pattern.*vector_struct.vshort1 = vec_add .vector_struct.vshort1, vector_struct.vshort2.;" \
+	"continue to struct_of_vector_func"
+
+    gdb_test "finish" \
+	"Run till exit from .0  $pattern\[ \r\n\]+main.*altivec-abi.c.*array_of_vector_func.*" \
+	"back to main (2)"
+
+    gdb_test "step" "" "step into array_of_vector_func"
+    gdb_test "p matrix\[0\]" ".*= .1, 2, 3, 4, 5, 6, 7, 8." "print first vector"
+    gdb_test "p matrix\[1\]" ".*= .11, 12, 13, 14, 15, 16, 17, 18." "print second vector"
+    gdb_test "p matrix\[2\]" ".*= .21, 22, 23, 24, 25, 26, 27, 28." "print third vector"
+    gdb_test "p matrix\[3\]" ".*= .31, 32, 33, 34, 35, 36, 37, 38." "print fourth vector"
+}
+
 if [test_compiler_info gcc*] {
-    set compile_flags "$compile_flags additional_flags=-maltivec additional_flags=-mabi=altivec"
+    set saved_prefix $pf_prefix
+
+    set pf_prefix "${saved_prefix} default ABI, auto:"
+    altivec_abi_tests "additional_flags=-maltivec" "auto"
+
+    # On GNU/Linux, we can mix -mabi=no-altivec and -mabi=altivec.
+    # So test some combinations.
+    if { [istarget "powerpc*-linux*"] } {
+	set binfile ${objdir}/${subdir}/${testfile}-ge-ge
+	set pf_prefix "${saved_prefix} generic ABI, forced:"
+	altivec_abi_tests "additional_flags=-maltivec additional_flags=-mabi=no-altivec" "generic"
+
+	set binfile ${objdir}/${subdir}/${testfile}-av-av
+	set pf_prefix "${saved_prefix} AltiVec ABI, forced:"
+	altivec_abi_tests "additional_flags=-maltivec additional_flags=-mabi=altivec" "altivec"
+
+	set binfile ${objdir}/${subdir}/${testfile}-av-auto
+	set pf_prefix "${saved_prefix} AltiVec ABI, auto:"
+	altivec_abi_tests "additional_flags=-maltivec additional_flags=-mabi=altivec" "auto"
+    }
 } elseif [test_compiler_info xlc*] {
-    set compile_flags "$compile_flags additional_flags=-qaltivec"
+    altivec_abi_tests "additional_flags=-qaltivec" "auto"
 } else {
     warning "unknown compiler"
     return -1
 }
-
-if  { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $compile_flags] != "" } {
-     untested altivec-abi.exp
-     return -1
-}
-
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
-
-#
-# Run to `main' where we begin our tests.
-#
-
-if ![runto_main] then {
-    gdb_suppress_tests
-}
-
-gdb_test "b marker" "Breakpoint 2 at.*file.*altivec-abi.c, line \[0-9\]+." "break marker"
-gdb_test "continue" "Breakpoint 2.*marker.*altivec-abi.c.*" "continue to marker"
-gdb_test "finish" "Run till exit from .0.*marker.*at.*altivec-abi.c.*main \\(\\) at.*altivec-abi.c.*result = vec_func \\(vshort,.*goes in v2.*" "back to main (1)"
-
-# now all the arguments of vec_fun are initialized
-
-set pattern "vec_func .vshort_f=.111, 222, 333, 444, 555, 666, 777, 888., vushort_f=.100, 200, 300, 400, 500, 600, 700, 800., vint_f=.-10, -20, -30, -40., vuint_f=.1111, 2222, 3333, 4444., vchar_f=.abcdefghilmnopqr., vuchar_f=.ABCDEFGHILMNOPQR., vfloat_f=.1.25, 3.75, 5.5, 1.25., x_f=.1, 2, 3, 4, 5, 6, 7, 8., y_f=.12, 22, 32, 42., a_f=.vector of chars.., b_f=.5.5, 4.5, 3.75, 2.25., c_f=.1.25, 3.5, 5.5, 7.75., intv_on_stack_f=.12, 34, 56, 78.."
-
-set pattern1 $pattern
-append pattern1 " at.*altivec-abi.c.*vint_res  = vec_add.*vint_f, intv_on_stack_f.;"
-
-# Now let's call the function.  This function has > 12 args,
-# the last one will go on the stack.
-gdb_test "p vec_func(vshort,vushort,vint,vuint,vchar,vuchar,vfloat,x,y,a,b,c,intv_on_stack)" \
-".\[0-9\]+ = .2, 2, 2, 2." "call inferior function with vectors (1) "
-
-# Let's call the function again with dummy arguments.  This is to clean
-# up the contents of the vector registers before the next call.
-gdb_test "p vec_func(vshort_d,vushort_d,vint_d,vuint_d,vchar_d,vuchar_d,vfloat_d,x_d,y_d,a_d,b_d,c_d,intv_on_stack_d)" \
-".\[0-9\]+ = .0, 0, 0, 0." "call inferior function with vectors (2) "
-
-# Let's step into the function, to see if the args are printed correctly.
-gdb_test "step" \
-  $pattern1 \
-  "step into vec_fun"
-
-set pattern2 $pattern
-append pattern2 " at.*altivec-abi.c.*main.*result = vec_func .vshort,.*goes in v2.*Value returned is.*= .2, 2, 2, 2."
-
-# Let's see if the result is returned correctly.
-gdb_test "finish" \
-  "Run till exit from .0.*$pattern2" \
-  "vector value returned correctly"
-
-# can we print the args correctly for this function?
-gdb_test "break struct_of_vector_func" "" ""
-
-set pattern "struct_of_vector_func .vector_struct=.vshort1 = .1, 2, 3, 4, 5, 6, 7, 8., vshort2 = .11, 12, 13, 14, 15, 16, 17, 18., vshort3 = .21, 22, 23, 24, 25, 26, 27, 28., vshort4 = .31, 32, 33, 34, 35, 36, 37, 38... at.*altivec-abi.c.*"
-
-gdb_test "continue" \
-  "Breakpoint 3, $pattern.*vector_struct.vshort1 = vec_add .vector_struct.vshort1, vector_struct.vshort2.;" \
-  "continue to struct_of_vector_func"
-
-gdb_test "finish" \
-  "Run till exit from .0  $pattern\[ \r\n\]+main.*altivec-abi.c.*array_of_vector_func.*" \
-  "back to main (2)"
-
-gdb_test "step" "" "step into array_of_vector_func"
-gdb_test "p matrix\[0\]" ".*= .1, 2, 3, 4, 5, 6, 7, 8." "print first vector"
-gdb_test "p matrix\[1\]" ".*= .11, 12, 13, 14, 15, 16, 17, 18." "print second vector"
-gdb_test "p matrix\[2\]" ".*= .21, 22, 23, 24, 25, 26, 27, 28." "print third vector"
-gdb_test "p matrix\[3\]" ".*= .31, 32, 33, 34, 35, 36, 37, 38." "print fourth vector"
-


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