2002-11-02 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Sat, 2 Nov 2002 15:13:34 +0000 (15:13 +0000)
committerAndrew Cagney <cagney@redhat.com>
Sat, 2 Nov 2002 15:13:34 +0000 (15:13 +0000)
* reggroups.h, reggroups.c: New files.
* regcache.c: Include "reggroups.h".
(enum regcache_dump_what): Add `regcache_dump_groups'.
(regcache_dump): Contract size of the "Type" column.  When
specified, dump the register's groups.
(maintenance_print_register_groups): New function.
(_initialize_regcache): Add command `maint print register-groups'.
* Makefile.in (COMMON_OBS): Add reggroups.o
(SFILES): Add reggroups.c.
(reggroups_h): Define.
(regcache.o, gdbarch.o): Update dependencies.
(reggroups.o): Specify dependencies.
* gdbarch.sh (register_reggroup_p): Add pure multi-arch method.
Add opaque declaration for `struct reggroup' in generated .h file.
Include "reggroups.h" in generated .c file.
gdbarch.h, gdbarch.c: Re-generate.

gdb/ChangeLog
gdb/Makefile.in
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/regcache.c
gdb/reggroups.c [new file with mode: 0644]
gdb/reggroups.h [new file with mode: 0644]

index effdb1f6d223e455f3807532e413c7993844f04b..61f6723b5ef5da5c2d95a51f72e75bf6a4f9e705 100644 (file)
@@ -1,3 +1,22 @@
+2002-11-02  Andrew Cagney  <cagney@redhat.com>
+
+       * reggroups.h, reggroups.c: New files.
+       * regcache.c: Include "reggroups.h".
+       (enum regcache_dump_what): Add `regcache_dump_groups'.
+       (regcache_dump): Contract size of the "Type" column.  When
+       specified, dump the register's groups.
+       (maintenance_print_register_groups): New function.
+       (_initialize_regcache): Add command `maint print register-groups'.
+       * Makefile.in (COMMON_OBS): Add reggroups.o
+       (SFILES): Add reggroups.c.
+       (reggroups_h): Define.
+       (regcache.o, gdbarch.o): Update dependencies.
+       (reggroups.o): Specify dependencies.
+       * gdbarch.sh (register_reggroup_p): Add pure multi-arch method.
+       Add opaque declaration for `struct reggroup' in generated .h file.
+       Include "reggroups.h" in generated .c file.
+       gdbarch.h, gdbarch.c: Re-generate.
+
 2002-11-02  Andrew Cagney  <cagney@redhat.com>
 
        * regcache.h (deprecated_read_register_gen): Rename
index a057202f745eb2a12135e575b7a1cdcfa4339a97..ab9a33b1065d50abad53f2096341e78ccd9a676a 100644 (file)
@@ -550,7 +550,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
        nlmread.c \
        objfiles.c osabi.c \
        p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
-       regcache.c remote.c \
+       regcache.c reggroups.c remote.c \
        scm-exp.c scm-lang.c scm-valprint.c serial.c ser-unix.c source.c \
        stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \
        target.c thread.c top.c tracepoint.c typeprint.c \
@@ -698,6 +698,7 @@ ppc_tdep_h = ppc-tdep.h $(osabi_h)
 ppcnbsd_tdep_h = ppcnbsd-tdep.h
 proc_utils_h = proc-utils.h
 regcache_h = regcache.h
+reggroups_h = reggroups.h
 remote_utils_h = remote-utils.h $(target_h)
 remote_h = remote.h
 scm_lang_h = scm-lang.h $(scm_tags_h)
@@ -854,7 +855,8 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
        nlmread.o serial.o mdebugread.o top.o utils.o \
        ui-file.o \
        frame.o doublest.o \
-       gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o
+       gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
+       reggroups.o
 
 OBS = $(COMMON_OBS) $(ANNOTATE_OBS)
 
@@ -1685,7 +1687,7 @@ gdbarch.o: gdbarch.c $(defs_h) $(arch_utils_h) $(gdbcmd_h) $(inferior_h) \
        $(gdb_string_h) $(symtab_h) $(frame_h) $(inferior_h) $(breakpoint_h) \
        $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(gdbthread_h) \
        $(annotate_h) $(symfile_h) $(value_h) $(symcat_h) $(floatformat_h) \
-       $(gdb_assert_h) $(gdb_string_h) $(gdb_events_h)
+       $(gdb_assert_h) $(gdb_string_h) $(gdb_events_h) $(reggroups_h)
 gdbtypes.o: gdbtypes.c $(defs_h) $(gdb_string_h) $(bfd_h) $(symtab_h) \
        $(symfile_h) $(objfiles_h) $(gdbtypes_h) $(expression_h) \
        $(language_h) $(target_h) $(value_h) $(demangle_h) $(complaints_h) \
@@ -2003,8 +2005,10 @@ procfs.o: procfs.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \
 ptx4-nat.o: ptx4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) \
        $(gregset_h)
 regcache.o: regcache.c $(defs_h) $(inferior_h) $(target_h) $(gdbarch_h) \
-       $(gdbcmd_h) $(regcache_h) $(gdb_assert_h) $(gdb_string_h) \
-       $(gdbcmd_h)
+       $(gdbcmd_h) $(regcache_h) $(reggroups_h) $(gdb_assert_h) \
+       $(gdb_string_h) $(gdbcmd_h)
+reggroups.o: reggroups.c $(defs_h) $(reggroups_h) $(gdbtypes_h) \
+       $(gdb_assert_h) $(regcache_h) $(command_h) $(gdbcmd_h)
 remote-array.o: remote-array.c $(defs_h) $(gdbcore_h) $(target_h) \
        $(gdb_string_h) $(command_h) $(serial_h) $(monitor_h) \
        $(remote_utils_h) $(inferior_h) $(version_h) $(regcache_h)
index b34e56506b12bb2cc2f0aab9213136e27b4c3999..0e438f377ed9d6479ae22e63e49b587444d697ae 100644 (file)
@@ -64,6 +64,7 @@
 #include "gdb_assert.h"
 #include "gdb_string.h"
 #include "gdb-events.h"
+#include "reggroups.h"
 
 /* Static function declarations */
 
@@ -274,6 +275,7 @@ struct gdbarch
   gdbarch_address_class_type_flags_ftype *address_class_type_flags;
   gdbarch_address_class_type_flags_to_name_ftype *address_class_type_flags_to_name;
   gdbarch_address_class_name_to_type_flags_ftype *address_class_name_to_type_flags;
+  gdbarch_register_reggroup_p_ftype *register_reggroup_p;
 };
 
 
@@ -437,6 +439,7 @@ struct gdbarch startup_gdbarch =
   0,
   0,
   0,
+  default_register_reggroup_p,
   /* startup_gdbarch() */
 };
 
@@ -568,6 +571,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   current_gdbarch->elf_make_msymbol_special = default_elf_make_msymbol_special;
   current_gdbarch->coff_make_msymbol_special = default_coff_make_msymbol_special;
   current_gdbarch->name_of_malloc = "malloc";
+  current_gdbarch->register_reggroup_p = default_register_reggroup_p;
   /* gdbarch_alloc() */
 
   return current_gdbarch;
@@ -819,6 +823,9 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of address_class_type_flags, has predicate */
   /* Skip verify of address_class_type_flags_to_name, has predicate */
   /* Skip verify of address_class_name_to_type_flags, has predicate */
+  if ((GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL)
+      && (gdbarch->register_reggroup_p == default_register_reggroup_p))
+    fprintf_unfiltered (log, "\n\tregister_reggroup_p");
   buf = ui_file_xstrdup (log, &dummy);
   make_cleanup (xfree, buf);
   if (strlen (buf) > 0)
@@ -851,6 +858,10 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
     fprintf_unfiltered (file,
                         "gdbarch_dump: in_function_epilogue_p = 0x%08lx\n",
                         (long) current_gdbarch->in_function_epilogue_p);
+  if (GDB_MULTI_ARCH)
+    fprintf_unfiltered (file,
+                        "gdbarch_dump: register_reggroup_p = 0x%08lx\n",
+                        (long) current_gdbarch->register_reggroup_p);
   if (GDB_MULTI_ARCH)
     fprintf_unfiltered (file,
                         "gdbarch_dump: pseudo_register_read = 0x%08lx\n",
@@ -5186,6 +5197,25 @@ set_gdbarch_address_class_name_to_type_flags (struct gdbarch *gdbarch,
   gdbarch->address_class_name_to_type_flags = address_class_name_to_type_flags;
 }
 
+int
+gdbarch_register_reggroup_p (struct gdbarch *gdbarch, int regnum, struct reggroup *reggroup)
+{
+  gdb_assert (gdbarch != NULL);
+  if (gdbarch->register_reggroup_p == 0)
+    internal_error (__FILE__, __LINE__,
+                    "gdbarch: gdbarch_register_reggroup_p invalid");
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_register_reggroup_p called\n");
+  return gdbarch->register_reggroup_p (gdbarch, regnum, reggroup);
+}
+
+void
+set_gdbarch_register_reggroup_p (struct gdbarch *gdbarch,
+                                 gdbarch_register_reggroup_p_ftype register_reggroup_p)
+{
+  gdbarch->register_reggroup_p = register_reggroup_p;
+}
+
 
 /* Keep a registry of per-architecture data-pointers required by GDB
    modules. */
index 524071a1d2d12affb9dde9782a21a7267bdca70b..3add874d337f55a6cb591324d1b80a64616d7e2a 100644 (file)
@@ -47,6 +47,7 @@ struct value;
 struct objfile;
 struct minimal_symbol;
 struct regcache;
+struct reggroup;
 
 extern struct gdbarch *current_gdbarch;
 
@@ -2660,6 +2661,12 @@ typedef int (gdbarch_address_class_name_to_type_flags_ftype) (struct gdbarch *gd
 extern int gdbarch_address_class_name_to_type_flags (struct gdbarch *gdbarch, char *name, int *type_flags_ptr);
 extern void set_gdbarch_address_class_name_to_type_flags (struct gdbarch *gdbarch, gdbarch_address_class_name_to_type_flags_ftype *address_class_name_to_type_flags);
 
+/* Is a register in a group */
+
+typedef int (gdbarch_register_reggroup_p_ftype) (struct gdbarch *gdbarch, int regnum, struct reggroup *reggroup);
+extern int gdbarch_register_reggroup_p (struct gdbarch *gdbarch, int regnum, struct reggroup *reggroup);
+extern void set_gdbarch_register_reggroup_p (struct gdbarch *gdbarch, gdbarch_register_reggroup_p_ftype *register_reggroup_p);
+
 extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
 
 
index da0e76010f7f1d79daf5125e3f86d7ff900d5bfa..1dd29f2ccbfe724fefd98e6ec3c2bc990267300b 100755 (executable)
@@ -667,6 +667,8 @@ v::HAVE_NONSTEPPABLE_WATCHPOINT:int:have_nonsteppable_watchpoint::::0:0::0
 F:2:ADDRESS_CLASS_TYPE_FLAGS:int:address_class_type_flags:int byte_size, int dwarf2_addr_class:byte_size, dwarf2_addr_class
 M:2:ADDRESS_CLASS_TYPE_FLAGS_TO_NAME:char *:address_class_type_flags_to_name:int type_flags:type_flags:
 M:2:ADDRESS_CLASS_NAME_TO_TYPE_FLAGS:int:address_class_name_to_type_flags:char *name, int *type_flags_ptr:name, type_flags_ptr
+# Is a register in a group
+m:::int:register_reggroup_p:int regnum, struct reggroup *reggroup:regnum, reggroup:::default_register_reggroup_p
 EOF
 }
 
@@ -778,6 +780,7 @@ struct value;
 struct objfile;
 struct minimal_symbol;
 struct regcache;
+struct reggroup;
 
 extern struct gdbarch *current_gdbarch;
 
@@ -1253,6 +1256,7 @@ cat <<EOF
 #include "gdb_assert.h"
 #include "gdb_string.h"
 #include "gdb-events.h"
+#include "reggroups.h"
 
 /* Static function declarations */
 
index 070651e1956272c60aa361d09e2a453b20d9f3bb..16a520cb5af72be49b662ad42df4ae443f31500e 100644 (file)
@@ -26,6 +26,7 @@
 #include "gdbarch.h"
 #include "gdbcmd.h"
 #include "regcache.h"
+#include "reggroups.h"
 #include "gdb_assert.h"
 #include "gdb_string.h"
 #include "gdbcmd.h"            /* For maintenanceprintlist.  */
@@ -1479,7 +1480,7 @@ dump_endian_bytes (struct ui_file *file, enum bfd_endian endian,
 
 enum regcache_dump_what
 {
-  regcache_dump_none, regcache_dump_raw, regcache_dump_cooked
+  regcache_dump_none, regcache_dump_raw, regcache_dump_cooked, regcache_dump_groups
 };
 
 static void
@@ -1487,6 +1488,8 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
               enum regcache_dump_what what_to_dump)
 {
   struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
+  struct gdbarch *gdbarch = regcache->descr->gdbarch;
+  struct reggroup *const *groups = reggroups (gdbarch);
   int regnum;
   int footnote_nr = 0;
   int footnote_register_size = 0;
@@ -1593,27 +1596,32 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
        }
 
       /* Type.  */
-      if (regnum < 0)
-       fprintf_unfiltered (file, " %-20s", "Type");
-      else
-       {
-         static const char blt[] = "builtin_type";
-         const char *t = TYPE_NAME (register_type (regcache->descr->gdbarch,
-                                                   regnum));
-         if (t == NULL)
-           {
-             char *n;
-             if (!footnote_register_type_name_null)
-               footnote_register_type_name_null = ++footnote_nr;
-             xasprintf (&n, "*%d", footnote_register_type_name_null);
-             make_cleanup (xfree, n);
-             t = n;
-           }
-         /* Chop a leading builtin_type.  */
-         if (strncmp (t, blt, strlen (blt)) == 0)
-           t += strlen (blt);
-         fprintf_unfiltered (file, " %-20s", t);
-       }
+      {
+       const char *t;
+       if (regnum < 0)
+         t = "Type";
+       else
+         {
+           static const char blt[] = "builtin_type";
+           t = TYPE_NAME (register_type (regcache->descr->gdbarch, regnum));
+           if (t == NULL)
+             {
+               char *n;
+               if (!footnote_register_type_name_null)
+                 footnote_register_type_name_null = ++footnote_nr;
+               xasprintf (&n, "*%d", footnote_register_type_name_null);
+               make_cleanup (xfree, n);
+               t = n;
+             }
+           /* Chop a leading builtin_type.  */
+           if (strncmp (t, blt, strlen (blt)) == 0)
+             t += strlen (blt);
+         }
+       fprintf_unfiltered (file, " %-15s", t);
+      }
+
+      /* Leading space always present.  */
+      fprintf_unfiltered (file, " ");
 
       /* Value, raw.  */
       if (what_to_dump == regcache_dump_raw)
@@ -1647,6 +1655,26 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
            }
        }
 
+      /* Group members.  */
+      if (what_to_dump == regcache_dump_groups)
+       {
+         if (regnum < 0)
+           fprintf_unfiltered (file, "Groups");
+         else
+           {
+             int i;
+             const char *sep = "";
+             for (i = 0; groups[i] != NULL; i++)
+               {
+                 if (gdbarch_register_reggroup_p (gdbarch, regnum, groups[i]))
+                   {
+                     fprintf_unfiltered (file, "%s%s", sep, reggroup_name (groups[i]));
+                     sep = ",";
+                   }
+               }
+           }
+       }
+
       fprintf_unfiltered (file, "\n");
     }
 
@@ -1696,6 +1724,12 @@ maintenance_print_cooked_registers (char *args, int from_tty)
   regcache_print (args, regcache_dump_cooked);
 }
 
+static void
+maintenance_print_register_groups (char *args, int from_tty)
+{
+  regcache_print (args, regcache_dump_groups);
+}
+
 void
 _initialize_regcache (void)
 {
@@ -1726,6 +1760,11 @@ Takes an optional file parameter.",
   add_cmd ("cooked-registers", class_maintenance,
           maintenance_print_cooked_registers,
           "Print the internal register configuration including cooked values.\
+Takes an optional file parameter.",
+          &maintenanceprintlist);
+  add_cmd ("register-groups", class_maintenance,
+          maintenance_print_register_groups,
+          "Print the internal register configuration including each register's group.\
 Takes an optional file parameter.",
           &maintenanceprintlist);
 
diff --git a/gdb/reggroups.c b/gdb/reggroups.c
new file mode 100644 (file)
index 0000000..8c3cbb7
--- /dev/null
@@ -0,0 +1,268 @@
+/* Register groupings for GDB, the GNU debugger.
+
+   Copyright 2002 Free Software Foundation, Inc.
+
+   Contributed by Red Hat.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "reggroups.h"
+#include "gdbtypes.h"
+#include "gdb_assert.h"
+#include "regcache.h"
+#include "command.h"
+#include "gdbcmd.h"            /* For maintenanceprintlist.  */
+
+/* Individual register groups.  */
+
+struct reggroup
+{
+  const char *name;
+  enum reggroup_type type;
+};
+
+struct reggroup *
+reggroup_new (const char *name, enum reggroup_type type)
+{
+  struct reggroup *group = XMALLOC (struct reggroup);
+  group->name = name;
+  group->type = type;
+  return group;
+}
+
+/* Register group attributes.  */
+
+const char *
+reggroup_name (struct reggroup *group)
+{
+  return group->name;
+}
+
+enum reggroup_type
+reggroup_type (struct reggroup *group)
+{
+  return group->type;
+}
+
+/* All the groups for a given architecture.  */
+
+struct reggroups
+{
+  int nr_group;
+  struct reggroup **group;
+};
+
+static struct gdbarch_data *reggroups_data;
+
+static void *
+reggroups_init (struct gdbarch *gdbarch)
+{
+  struct reggroups *groups = XMALLOC (struct reggroups);
+  groups->nr_group = 0;
+  groups->group = NULL;
+  return groups;
+}
+
+static void
+reggroups_free (struct gdbarch *gdbarch, void *data)
+{
+  struct reggroups *groups = data;
+  xfree (groups->group);
+  xfree (groups);
+}
+
+/* Add a register group (with attribute values) to the pre-defined
+   list.  This function can be called during architecture
+   initialization and hence needs to handle NULL architecture groups.  */
+
+static void
+add_group (struct reggroups *groups, struct reggroup *group)
+{
+  gdb_assert (group != NULL);
+  groups->nr_group++;
+  groups->group = xrealloc (groups->group, (sizeof (struct reggroup *)
+                                           * (groups->nr_group + 1)));
+  groups->group[groups->nr_group - 1] = group;
+  groups->group[groups->nr_group] = NULL;
+}
+
+void
+reggroup_add (struct gdbarch *gdbarch, struct reggroup *group)
+{
+  struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
+  if (groups == NULL)
+    {
+      /* ULGH, called during architecture initialization.  Patch
+         things up.  */
+      groups = reggroups_init (gdbarch);
+      set_gdbarch_data (gdbarch, reggroups_data, groups);
+    }
+  add_group (groups, group);
+}
+
+/* The register groups for the current architecture.  Mumble something
+   about the lifetime of the buffer....  */
+
+static struct reggroups *default_groups;
+
+struct reggroup * const*
+reggroups (struct gdbarch *gdbarch)
+{
+  struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
+  /* Don't allow this function to be called during architecture
+     creation.  */
+  gdb_assert (groups != NULL);
+  if (groups->group == NULL)
+    return default_groups->group;
+  else
+    return groups->group;
+}
+
+/* Is REGNUM a member of REGGROUP?  */
+int
+default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                            struct reggroup *group)
+{
+  int vector_p;
+  int float_p;
+  int raw_p;
+  if (REGISTER_NAME (regnum) == NULL
+      || *REGISTER_NAME (regnum) == '\0')
+    return 0;
+  if (group == all_reggroup)
+    return 1;
+  vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
+  float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
+  raw_p = regnum < gdbarch_num_regs (gdbarch);
+  if (group == float_reggroup)
+    return float_p;
+  if (group == vector_reggroup)
+    return vector_p;
+  if (group == general_reggroup)
+    return (!vector_p && !float_p);
+  if (group == save_reggroup || group == restore_reggroup)
+    return raw_p;
+  return 0;   
+}
+
+/* Dump out a table of register groups for the current architecture.  */
+
+static void
+reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file)
+{
+  struct reggroup *const *groups = reggroups (gdbarch);
+  int i = -1;
+  do
+    {
+      /* Group name.  */
+      {
+       const char *name;
+       if (i < 0)
+         name = "Group";
+       else
+         name = reggroup_name (groups[i]);
+       fprintf_unfiltered (file, " %-10s", name);
+      }
+      
+      /* Group type.  */
+      {
+       const char *type;
+       if (i < 0)
+         type = "Type";
+       else
+         {
+           switch (reggroup_type (groups[i]))
+             {
+             case USER_REGGROUP:
+               type = "user";
+               break;
+             case INTERNAL_REGGROUP:
+               type = "internal";
+               break;
+             default:
+               internal_error (__FILE__, __LINE__, "bad switch");
+             }
+         }
+       fprintf_unfiltered (file, " %-10s", type);
+      }
+
+      /* Note: If you change this, be sure to also update the
+         documentation.  */
+      
+      fprintf_unfiltered (file, "\n");
+      i++;
+    }
+  while (groups[i] != NULL);
+}
+
+static void
+maintenance_print_reggroups (char *args, int from_tty)
+{
+  if (args == NULL)
+    reggroups_dump (current_gdbarch, gdb_stdout);
+  else
+    {
+      struct ui_file *file = gdb_fopen (args, "w");
+      if (file == NULL)
+       perror_with_name ("maintenance print reggroups");
+      reggroups_dump (current_gdbarch, file);    
+      ui_file_delete (file);
+    }
+}
+
+/* Pre-defined register groups.  */
+static struct reggroup general_group = { "general", USER_REGGROUP };
+static struct reggroup float_group = { "float", USER_REGGROUP };
+static struct reggroup system_group = { "system", USER_REGGROUP };
+static struct reggroup vector_group = { "vector", USER_REGGROUP };
+static struct reggroup all_group = { "all", USER_REGGROUP };
+static struct reggroup save_group = { "save", INTERNAL_REGGROUP };
+static struct reggroup restore_group = { "restore", INTERNAL_REGGROUP };
+
+struct reggroup *const general_reggroup = &general_group;
+struct reggroup *const float_reggroup = &float_group;
+struct reggroup *const system_reggroup = &system_group;
+struct reggroup *const vector_reggroup = &vector_group;
+struct reggroup *const all_reggroup = &all_group;
+struct reggroup *const save_reggroup = &save_group;
+struct reggroup *const restore_reggroup = &restore_group;
+
+void
+_initialize_reggroup (void)
+{
+  reggroups_data = register_gdbarch_data (reggroups_init, reggroups_free);
+
+  /* The pre-defined list of groups.  */
+  default_groups = reggroups_init (NULL);
+  add_group (default_groups, general_reggroup);
+  add_group (default_groups, float_reggroup);
+  add_group (default_groups, system_reggroup);
+  add_group (default_groups, vector_reggroup);
+  add_group (default_groups, all_reggroup);
+  add_group (default_groups, save_reggroup);
+  add_group (default_groups, restore_reggroup);
+
+
+  add_cmd ("reggroups", class_maintenance,
+          maintenance_print_reggroups, "\
+Print the internal register group names.\n\
+Takes an optional file parameter.",
+          &maintenanceprintlist);
+
+}
diff --git a/gdb/reggroups.h b/gdb/reggroups.h
new file mode 100644 (file)
index 0000000..0088a85
--- /dev/null
@@ -0,0 +1,61 @@
+/* Register groupings for GDB, the GNU debugger.
+
+   Copyright 2002 Free Software Foundation, Inc.
+
+   Contributed by Red Hat.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef REGGROUPS_H
+#define REGGROUPS_H
+
+struct gdbarch;
+struct reggroup;
+
+enum reggroup_type { USER_REGGROUP, INTERNAL_REGGROUP };
+
+/* Pre-defined, user visible, register groups.  */
+extern struct reggroup *const general_reggroup;
+extern struct reggroup *const float_reggroup;
+extern struct reggroup *const system_reggroup;
+extern struct reggroup *const vector_reggroup;
+extern struct reggroup *const all_reggroup;
+
+/* Pre-defined, internal, register groups.  */
+extern struct reggroup *const save_reggroup;
+extern struct reggroup *const restore_reggroup;
+
+/* Create a new local register group.  */
+extern struct reggroup *reggroup_new (const char *name,
+                                     enum reggroup_type type);
+
+/* Add a register group (with attribute values) to the pre-defined list.  */
+extern void reggroup_add (struct gdbarch *gdbarch, struct reggroup *group);
+
+/* Register group attributes.  */
+extern const char *reggroup_name (struct reggroup *reggroup);
+extern enum reggroup_type reggroup_type (struct reggroup *reggroup);
+
+/* The register groups for the current architecture.  */
+extern struct reggroup *const *reggroups (struct gdbarch *gdbarch);
+
+/* Is REGNUM a member of REGGROUP?  */
+extern int default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                                       struct reggroup *reggroup);
+
+#endif