diff options
author | Andrew Cagney <cagney@redhat.com> | 2002-08-26 19:57:39 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2002-08-26 19:57:39 +0000 |
commit | 7061c019a24b3bf6a947698e12e79ffd858c5e7e (patch) | |
tree | f728801726b4a1288d94dd917b6e57828087c8f4 | |
parent | e6e99dbbfca273e55167783dd37ed771ac7268cb (diff) | |
download | gdb-7061c019a24b3bf6a947698e12e79ffd858c5e7e.tar.gz |
2002-08-26 Andrew Cagney <ac131313@redhat.com>
* i386-tdep.c: Include "reggroups.h".
(i386_register_reggroup_p): New function.
(i386_add_reggroups, i386_init_reggroups): New function.
(i386_gdbarch_init): Call i386_add_reggroups. Set
register_reggroup_p.
(_initialize_i386_tdep): Call i386_init_reggroups.
* infcmd.c: Include <ctype.h>.
(registers_info): Rewrite. Handle reggroups.
(default_print_registers_info): Use gdbarch_register_reggroup_p.
(print_float_info): Use gdbarch_register_reggroup_p.
* regcache.c: Include "reggroups.h".
(regcache_dump): Include the register groups in the ``maint print
registers'' command.
* infcmd.c: Include "regroup.h".
(default_print_registers_info): Use gdbarch_register_reggroup_p.
(print_float_info): Ditto.
* gdbarch.sh: Include "reggroups.h".
(register_reggroup_p): New method.
(struct reggroup): Add opaque declaration.
* gdbarch.h, gdbarch.c: Regenerate.
* Makefile.in (SFILES): Add reggroups.c.
(reggroups_h): Define.
(COMMON_OBS): Add reggroups.o.
(reggroups.o): Specify dependencies.
(gdbarch.o, infcmd.o, i386-tdep.o): Update dependencies.
* reggroups.c: New file.
* reggroups.h: New file.
-rw-r--r-- | gdb/ChangeLog | 36 | ||||
-rw-r--r-- | gdb/Makefile.in | 17 | ||||
-rw-r--r-- | gdb/gdbarch.c | 30 | ||||
-rw-r--r-- | gdb/gdbarch.h | 7 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 4 | ||||
-rw-r--r-- | gdb/i386-tdep.c | 51 | ||||
-rw-r--r-- | gdb/infcmd.c | 108 | ||||
-rw-r--r-- | gdb/regcache.c | 25 | ||||
-rw-r--r-- | gdb/reggroups.c | 187 | ||||
-rw-r--r-- | gdb/reggroups.h | 53 |
10 files changed, 487 insertions, 31 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c2d481ed880..03ff1fd823a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,39 @@ +2002-08-26 Andrew Cagney <ac131313@redhat.com> + + * i386-tdep.c: Include "reggroups.h". + (i386_register_reggroup_p): New function. + (i386_add_reggroups, i386_init_reggroups): New function. + (i386_gdbarch_init): Call i386_add_reggroups. Set + register_reggroup_p. + (_initialize_i386_tdep): Call i386_init_reggroups. + + * infcmd.c: Include <ctype.h>. + (registers_info): Rewrite. Handle reggroups. + (default_print_registers_info): Use gdbarch_register_reggroup_p. + (print_float_info): Use gdbarch_register_reggroup_p. + + * regcache.c: Include "reggroups.h". + (regcache_dump): Include the register groups in the ``maint print + registers'' command. + + * infcmd.c: Include "regroup.h". + (default_print_registers_info): Use gdbarch_register_reggroup_p. + (print_float_info): Ditto. + + * gdbarch.sh: Include "reggroups.h". + (register_reggroup_p): New method. + (struct reggroup): Add opaque declaration. + * gdbarch.h, gdbarch.c: Regenerate. + + * Makefile.in (SFILES): Add reggroups.c. + (reggroups_h): Define. + (COMMON_OBS): Add reggroups.o. + (reggroups.o): Specify dependencies. + (gdbarch.o, infcmd.o, i386-tdep.o): Update dependencies. + + * reggroups.c: New file. + * reggroups.h: New file. + 2002-08-25 Andrew Cagney <ac131313@redhat.com> * arch-utils.h (default_next_cooked_register_to_save): Declare. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 756ffdf4074..f8d2c9843eb 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -533,6 +533,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ event-loop.c event-top.c \ expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \ findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c osabi.c \ + reggroups.c \ inf-loop.c infcmd.c inflow.c infrun.c language.c \ kod.c kod-cisco.c \ ui-out.c cli-out.c \ @@ -689,6 +690,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) @@ -842,7 +844,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 + gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o \ + reggroups.o OBS = $(COMMON_OBS) $(ANNOTATE_OBS) @@ -1674,7 +1677,11 @@ frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \ $(arch_utils_h) $(regcache_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) $(gdb_assert_h) $(gdb_string_h) $(gdbcmd_h) \ + $(reggroups_h) + +reggroups.o: reggroups.c $(defs_h) $(reggroups_h) $(gdbtypes_h) \ + $(gdb_assert_h) $(regcache_h) fork-child.o: fork-child.c $(gdb_wait_h) $(defs_h) $(gdbcore_h) \ $(inferior_h) $(target_h) $(terminal_h) $(gdbthread_h) $(gdb_string_h) @@ -1696,7 +1703,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) arch-utils.o: arch-utils.c $(defs_h) $(bfd_h) $(gdbcmd_h) \ $(arch_utils_h) $(gdb_assert_h) $(inferior_h) \ @@ -1751,7 +1758,7 @@ i386gnu-nat.o: gnu-nat.h i386-tdep.o: i386-tdep.c $(defs_h) $(gdb_string_h) $(frame_h) \ $(inferior_h) $(gdbcore_h) $(target_h) $(floatformat_h) \ $(symtab_h) $(gdbcmd_h) $(command_h) $(arch_utils_h) $(regcache_h) \ - $(doublest_h) $(value_h) + $(doublest_h) $(value_h) $(reggroups_h) i386-nat.o: i386-nat.c $(defs_h) $(breakpoint_h) $(command_h) $(gdbcmd_h) @@ -1807,7 +1814,7 @@ ia64-tdep.o: ia64-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \ infcmd.o: infcmd.c $(defs_h) environ.h $(gdbcmd_h) $(gdbcore_h) \ $(inferior_h) $(target_h) $(language_h) $(symfile_h) $(gdb_string_h) \ - $(ui_out_h) $(completer_h) $(regcache_h) + $(ui_out_h) $(completer_h) $(regcache_h) $(reggroups_h) inflow.o: inflow.c $(bfd_h) $(command_h) $(defs_h) $(inferior_h) \ $(target_h) $(terminal_h) $(gdbthread_h) $(gdb_string_h) diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 2835ee16fba..af58497cc19 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -64,6 +64,7 @@ #include "gdb_assert.h" #include "gdb_string.h" #include "gdb-events.h" +#include "reggroup.h" /* Static function declarations */ @@ -267,6 +268,7 @@ struct gdbarch gdbarch_coff_make_msymbol_special_ftype *coff_make_msymbol_special; gdbarch_next_cooked_register_to_save_ftype *next_cooked_register_to_save; gdbarch_next_cooked_register_to_restore_ftype *next_cooked_register_to_restore; + gdbarch_register_reggroup_p_ftype *register_reggroup_p; }; @@ -423,6 +425,7 @@ struct gdbarch startup_gdbarch = 0, default_next_cooked_register_to_save, default_next_cooked_register_to_restore, + default_register_reggroup_p, /* startup_gdbarch() */ }; @@ -555,6 +558,7 @@ gdbarch_alloc (const struct gdbarch_info *info, current_gdbarch->coff_make_msymbol_special = default_coff_make_msymbol_special; current_gdbarch->next_cooked_register_to_save = default_next_cooked_register_to_save; current_gdbarch->next_cooked_register_to_restore = default_next_cooked_register_to_restore; + current_gdbarch->register_reggroup_p = default_register_reggroup_p; /* gdbarch_alloc() */ return current_gdbarch; @@ -803,6 +807,9 @@ verify_gdbarch (struct gdbarch *gdbarch) if ((GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && (gdbarch->next_cooked_register_to_restore == default_next_cooked_register_to_restore)) fprintf_unfiltered (log, "\n\tnext_cooked_register_to_restore"); + 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) @@ -841,6 +848,10 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) (long) current_gdbarch->next_cooked_register_to_save); 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", (long) current_gdbarch->pseudo_register_read); if (GDB_MULTI_ARCH) @@ -4940,6 +4951,25 @@ set_gdbarch_next_cooked_register_to_restore (struct gdbarch *gdbarch, gdbarch->next_cooked_register_to_restore = next_cooked_register_to_restore; } +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. */ diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 1534d7936f2..25365f99023 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -47,6 +47,7 @@ struct value; struct objfile; struct minimal_symbol; struct regcache; +struct reggroup; extern struct gdbarch *current_gdbarch; @@ -2493,6 +2494,12 @@ typedef int (gdbarch_next_cooked_register_to_restore_ftype) (struct gdbarch *gdb extern int gdbarch_next_cooked_register_to_restore (struct gdbarch *gdbarch, int last_regnum); extern void set_gdbarch_next_cooked_register_to_restore (struct gdbarch *gdbarch, gdbarch_next_cooked_register_to_restore_ftype *next_cooked_register_to_restore); +/* 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); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index ac0aa761616..8648407b058 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -661,6 +661,8 @@ f:2:COFF_MAKE_MSYMBOL_SPECIAL:void:coff_make_msymbol_special:int val, struct min # Iterators for the cooked registers to save or restore. m:::int:next_cooked_register_to_save:int last_regnum:last_regnum:::default_next_cooked_register_to_save m:::int:next_cooked_register_to_restore:int last_regnum:last_regnum:::default_next_cooked_register_to_restore +# Is a register in a group +m:::int:register_reggroup_p:int regnum, struct reggroup *reggroup:regnum, reggroup:::default_register_reggroup_p EOF } @@ -772,6 +774,7 @@ struct value; struct objfile; struct minimal_symbol; struct regcache; +struct reggroup; extern struct gdbarch *current_gdbarch; @@ -1247,6 +1250,7 @@ cat <<EOF #include "gdb_assert.h" #include "gdb_string.h" #include "gdb-events.h" +#include "reggroups.h" /* Static function declarations */ diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 8684fce684d..d7778cbb0d1 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -37,6 +37,7 @@ #include "doublest.h" #include "value.h" #include "gdb_assert.h" +#include "reggroups.h" #include "i386-tdep.h" #include "i387-tdep.h" @@ -1413,6 +1414,49 @@ i386_nw_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) } +/* i386 register groups. In addition to the normal groups, add "mmx" + and "sse". */ + +struct reggroup *i368_sse_reggroup; +struct reggroup *i368_mmx_reggroup; + +static void +i386_init_reggroups (void) +{ + i368_sse_reggroup = reggroup_new ("sse"); + i368_mmx_reggroup = reggroup_new ("mmx"); +} + +static void +i386_add_reggroups (struct gdbarch *gdbarch) +{ + reggroup_add (gdbarch, i368_sse_reggroup); + reggroup_add (gdbarch, i368_mmx_reggroup); + reggroup_add (gdbarch, general_reggroup); + reggroup_add (gdbarch, float_reggroup); + reggroup_add (gdbarch, all_reggroup); + reggroup_add (gdbarch, vector_reggroup); + reggroup_add (gdbarch, system_reggroup); +} + +static int +i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, + struct reggroup *group) +{ + if (group == all_reggroup) + return 1; + if (mmx_regnum_p (regnum) || regnum == MXCSR_REGNUM) + return (group == i368_mmx_reggroup || group == vector_reggroup); + if (FP_REGNUM_P (regnum) || FPC_REGNUM_P (regnum)) + return (group == float_reggroup || group == all_reggroup); + if (SSE_REGNUM_P (regnum)) + return (group == i368_sse_reggroup || group == vector_reggroup); + if (group == general_reggroup) + return 1; + return 0; +} + + static struct gdbarch * i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { @@ -1570,6 +1614,10 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read); set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write); + /* Add the i386 register groups. */ + i386_add_reggroups (gdbarch); + set_gdbarch_register_reggroup_p (gdbarch, i386_register_reggroup_p); + /* Hook in ABI-specific overrides, if they have been registered. */ gdbarch_init_osabi (info, gdbarch, osabi); @@ -1643,4 +1691,7 @@ are \"default\", \"pcc\" and \"reg\", and the default value is \"default\".", i386_go32_init_abi); gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_NETWARE, i386_nw_init_abi); + + /* Define the i386 specific register groups. */ + i386_init_reggroups (); } diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 433332555e8..84e295ba349 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -41,6 +41,8 @@ #include "event-top.h" #include "parser-defs.h" #include "regcache.h" +#include "reggroups.h" +#include <ctype.h> /* Functions exported for general use: */ @@ -1586,9 +1588,9 @@ default_print_registers_info (struct gdbarch *gdbarch, { if (!print_all) { - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT) + if (gdbarch_register_reggroup_p (gdbarch, i, float_reggroup)) continue; - if (TYPE_VECTOR (REGISTER_VIRTUAL_TYPE (i))) + if (gdbarch_register_reggroup_p (gdbarch, i, vector_reggroup)) continue; } } @@ -1692,35 +1694,89 @@ registers_info (char *addr_exp, int fpregs) return; } - do + while (*addr_exp != '\0') { + const char *start; + const char *end; + /* Keep skipping leading white space until something interesting + is found. */ + if (isspace ((*addr_exp))) + { + addr_exp++; + continue; + } + + /* Discard any ``$''. There had better be something after it. */ if (addr_exp[0] == '$') addr_exp++; - end = addr_exp; - while (*end != '\0' && *end != ' ' && *end != '\t') - ++end; - numregs = NUM_REGS + NUM_PSEUDO_REGS; - - regnum = target_map_name_to_register (addr_exp, end - addr_exp); - if (regnum >= 0) - goto found; - - regnum = numregs; - - if (*addr_exp >= '0' && *addr_exp <= '9') - regnum = atoi (addr_exp); /* Take a number */ - if (regnum >= numregs) /* Bad name, or bad number */ - error ("%.*s: invalid register", (int) (end - addr_exp), addr_exp); + if (isspace ((*addr_exp)) || (*addr_exp) == '\0') + error ("Missing register name"); - found: - gdbarch_print_registers_info (current_gdbarch, gdb_stdout, - selected_frame, regnum, fpregs); + /* Find the start/end of this register name/group. */ + start = addr_exp; + while ((*addr_exp) != '\0' && !isspace ((*addr_exp))) + addr_exp++; + end = addr_exp; + + /* Figure out what we've found, display it. */ + + /* A register name? */ + { + int regnum = target_map_name_to_register (addr_exp, end - start); + if (regnum >= 0) + { + gdbarch_print_registers_info (current_gdbarch, gdb_stdout, + selected_frame, regnum, fpregs); + continue; + } + } + + /* A register number? (how portable is this one?). */ + { + char *endptr; + int regnum = strtol (start, &endptr, 0); + if (endptr == end + && regnum >= 0 + && regnum < NUM_REGS + NUM_PSEUDO_REGS) + { + gdbarch_print_registers_info (current_gdbarch, gdb_stdout, + selected_frame, regnum, fpregs); + continue; + } + } + + /* A register group? */ + { + struct reggroup *const *group; + for (group = reggroups (current_gdbarch); + (*group) != NULL; + group++) + { + if (strncmp (start, reggroup_name ((*group)), end - start) == 0) + break; + } + if ((*group) != NULL) + { + /* Don't bother with a length check. If the user enters + just part of a register group's name, go with the first + matching one. */ + int regnum; + for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) + { + if (gdbarch_register_reggroup_p (current_gdbarch, regnum, + (*group))) + gdbarch_print_registers_info (current_gdbarch, + gdb_stdout, selected_frame, + regnum, fpregs); + } + continue; + } + } - addr_exp = end; - while (*addr_exp == ' ' || *addr_exp == '\t') - ++addr_exp; + /* Nothing matched. */ + error ("Invalid register `%.*s'", (int) (end - start), start); } - while (*addr_exp != '\0'); + } void @@ -1933,7 +1989,7 @@ print_float_info (struct gdbarch *gdbarch, struct ui_file *file, for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) { - if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT) + if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup)) { printed_something = 1; gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1); diff --git a/gdb/regcache.c b/gdb/regcache.c index f60dbbe01ac..3c1e5f176a3 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -29,6 +29,7 @@ #include "gdb_assert.h" #include "gdb_string.h" #include "gdbcmd.h" /* For maintenanceprintlist. */ +#include "reggroups.h" /* * DATA STRUCTURE @@ -1641,6 +1642,30 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, } } + /* The registers groups. */ + if (what_to_dump == regcache_dump_none) + { + if (regnum < 0) + fprintf_unfiltered (file, "Groups"); + else + { + struct reggroup *const *group; + const char *prefix = ""; + for (group = reggroups (regcache->descr->gdbarch); + *group != NULL; + group++) + { + if (gdbarch_register_reggroup_p (regcache->descr->gdbarch, + regnum, *group)) + { + fprintf_unfiltered (file, "%s%s", prefix, + reggroup_name (*group)); + prefix = ","; + } + } + } + } + fprintf_unfiltered (file, "\n"); } diff --git a/gdb/reggroups.c b/gdb/reggroups.c new file mode 100644 index 00000000000..09b0c930c82 --- /dev/null +++ b/gdb/reggroups.c @@ -0,0 +1,187 @@ +/* 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" + +/* Individual register groups. */ + +struct reggroup +{ + const char *name; +}; + +struct reggroup * +reggroup_new (const char *name) +{ + struct reggroup *group = XMALLOC (struct reggroup); + group->name = name; + return group; +} + +/* Register group attributes. */ + +const char * +reggroup_name (struct reggroup *group) +{ + return group->name; +} + +/* 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; + 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; + if (group == float_reggroup) + return float_p; + if (group == vector_reggroup) + return vector_p; + if (group == general_reggroup) + return (!vector_p && !float_p); + return 0; +} + + + + +/* Pre-defined register groups. */ +struct reggroup general_group = { "general" }; +struct reggroup float_group = { "float" }; +struct reggroup system_group = { "system" }; +struct reggroup vector_group = { "vector" }; +struct reggroup all_group = { "all" }; + +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; + +void +_initialize_reggroup (void) +{ + reggroups_data = register_gdbarch_data (reggroups_init, reggroups_free); + +#if 0 + /* The pre-defined groups. */ + general_reggroup = reggroup_new ("general"); + float_reggroup = reggroup_new ("float"); + system_reggroup = reggroup_new ("system"); + vector_reggroup = reggroup_new ("vector"); + all_reggroup = reggroup_new ("all"); +#endif + + /* 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); +} diff --git a/gdb/reggroups.h b/gdb/reggroups.h new file mode 100644 index 00000000000..cae851ca51f --- /dev/null +++ b/gdb/reggroups.h @@ -0,0 +1,53 @@ +/* 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; + +/* Pre-defined 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; + +/* Create a new local register group. */ +extern struct reggroup *reggroup_new (const char *name); + +/* 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); + +/* 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 |