* ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Check the selected
authorDaniel Jacobowitz <drow@false.org>
Tue, 30 Oct 2007 19:35:35 +0000 (19:35 +0000)
committerDaniel Jacobowitz <drow@false.org>
Tue, 30 Oct 2007 19:35:35 +0000 (19:35 +0000)
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.

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

* 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.

gdb/ChangeLog
gdb/Makefile.in
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/ppc-sysv-tdep.c
gdb/ppc-tdep.h
gdb/rs6000-tdep.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.arch/altivec-abi.exp

index c356fb7..20aba85 100644 (file)
@@ -1,3 +1,25 @@
+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-29  Carlos Eduardo Seo  <cseo@linux.vnet.ibm.com>
 
        * ppc-linux-tdep.c (ppc32_linux_reg_offsets): Corrected
index 52c6035..79efa0d 100644 (file)
@@ -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) $(frame_h) $(inferior_h) $(symtab_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 d44a453..83d679f 100644 (file)
@@ -1,3 +1,8 @@
+2007-10-30  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb.texinfo (PowerPC): Document "set powerpc vector-abi" and "set
+       powerpc soft-float".
+
 2007-10-24  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * gdb.texinfo (Files): Correct formatting.  Mention Expat
index 7ad47fc..83c7680 100644 (file)
@@ -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 (such as Motorola's ADS).
 
 @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 542acbd..5dc90f1 100644 (file)
@@ -104,8 +104,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          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 gdbarch *gdbarch, struct value *function,
                  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 gdbarch *gdbarch, struct value *function,
            }
          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 gdbarch *gdbarch, struct value *function,
            }
          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 gdbarch *gdbarch, struct value *function,
                  || 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 gdbarch *gdbarch, struct value *function,
 
 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 *gdbarch, struct type *type,
        {
          /* 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 *gdbarch, struct type *type,
     }
   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 *gdbarch, struct type *type,
        }
       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 gdbarch *gdbarch, struct value *function,
      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 gdbarch *gdbarch, struct value *function,
                 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 gdbarch *gdbarch, struct value *function,
 }
 
 
-/* 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 62f0e7e..52b172f 100644 (file)
@@ -157,9 +157,24 @@ extern void ppc_collect_vrregset (const struct regset *regset,
 
 /* 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 f133b78..0843be5 100644 (file)
@@ -49,6 +49,7 @@
 #include "libxcoff.h"
 
 #include "elf-bfd.h"
+#include "elf/ppc.h"
 
 #include "solib-svr4.h"
 #include "ppc-tdep.h"
 #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 info, struct gdbarch_list *arches)
   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 info, struct gdbarch_list *arches)
       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 info, struct gdbarch_list *arches)
          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 info, struct gdbarch_list *arches)
 
   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 *gdbarch, struct ui_file *file)
   /* 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 551c8d6..2f3a5d7 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2007-10-30  Pedro Alves  <pedro_alves@portugalmail.pt>
 
        * lib/gdb.exp, gdb.base/sepdebug.exp: Replace usage of eq and ne
index bdb7853..c811c3d 100644 (file)
@@ -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
 }
 
-if [test_compiler_info gcc*] {
-    set compile_flags "$compile_flags additional_flags=-maltivec additional_flags=-mabi=altivec"
-} elseif [test_compiler_info xlc*] {
-    set compile_flags "$compile_flags additional_flags=-qaltivec"
-} else {
-    warning "unknown compiler"
-    return -1
-}
+proc altivec_abi_tests { extra_flags force_abi } {
+    global testfile binfile srcfile srcdir subdir
+    global gdb_prompt
 
-if  { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $compile_flags] != "" } {
-     untested altivec-abi.exp
-     return -1
-}
+    set compile_flags "debug nowarnings $extra_flags"
 
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
+    if  { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $compile_flags] != "" } {
+       untested altivec-abi.exp
+       return -1
+    }
 
-#
-# Run to `main' where we begin our tests.
-#
+    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 ![runto_main] then {
-    gdb_suppress_tests
-}
+       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 "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)"
+    gdb_test "set powerpc vector-abi $force_abi"
 
-# now all the arguments of vec_fun are initialized
+    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)"
 
-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.."
+    # now all the arguments of vec_fun are initialized
 
-set pattern1 $pattern
-append pattern1 " at.*altivec-abi.c.*vint_res  = vec_add.*vint_f, intv_on_stack_f.;"
+    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.."
 
-# 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) "
+    set pattern1 $pattern
+    append pattern1 " at.*altivec-abi.c.*vint_res  = vec_add.*vint_f, intv_on_stack_f.;"
 
-# 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) "
+    # 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 step into the function, to see if the args are printed correctly.
-gdb_test "step" \
-  $pattern1 \
-  "step into vec_fun"
+    # 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)"
 
-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 step into the function, to see if the args are printed correctly.
+    gdb_test "step" \
+       $pattern1 \
+       "step into vec_fun"
 
-# Let's see if the result is returned correctly.
-gdb_test "finish" \
-  "Run till exit from .0.*$pattern2" \
-  "vector value returned correctly"
+    set pattern2 $pattern
+    append pattern2 " at.*altivec-abi.c.*main.*result = vec_func .vshort,.*goes in v2.*Value returned is.*= .2, 2, 2, 2."
 
-# can we print the args correctly for this function?
-gdb_test "break struct_of_vector_func" "" ""
+    # Let's see if the result is returned correctly.
+    gdb_test "finish" "Run till exit from .0.*$pattern2" \
+       "vector value returned correctly"
 
-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.*"
+    # can we print the args correctly for this function?
+    gdb_test "break struct_of_vector_func" "" ""
 
-gdb_test "continue" \
-  "Breakpoint 3, $pattern.*vector_struct.vshort1 = vec_add .vector_struct.vshort1, vector_struct.vshort2.;" \
-  "continue to 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 "finish" \
-  "Run till exit from .0  $pattern\[ \r\n\]+main.*altivec-abi.c.*array_of_vector_func.*" \
-  "back to main (2)"
+    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 "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"
+    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 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*] {
+    altivec_abi_tests "additional_flags=-qaltivec" "auto"
+} else {
+    warning "unknown compiler"
+    return -1
+}