15796c8dcSSimon Schubert /* Register groupings for GDB, the GNU debugger.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2002-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert Contributed by Red Hat.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This file is part of GDB.
85796c8dcSSimon Schubert
95796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert (at your option) any later version.
135796c8dcSSimon Schubert
145796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175796c8dcSSimon Schubert GNU General Public License for more details.
185796c8dcSSimon Schubert
195796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
215796c8dcSSimon Schubert
225796c8dcSSimon Schubert #include "defs.h"
235796c8dcSSimon Schubert #include "arch-utils.h"
245796c8dcSSimon Schubert #include "reggroups.h"
255796c8dcSSimon Schubert #include "gdbtypes.h"
265796c8dcSSimon Schubert #include "gdb_assert.h"
275796c8dcSSimon Schubert #include "regcache.h"
285796c8dcSSimon Schubert #include "command.h"
295796c8dcSSimon Schubert #include "gdbcmd.h" /* For maintenanceprintlist. */
305796c8dcSSimon Schubert
315796c8dcSSimon Schubert /* Individual register groups. */
325796c8dcSSimon Schubert
335796c8dcSSimon Schubert struct reggroup
345796c8dcSSimon Schubert {
355796c8dcSSimon Schubert const char *name;
365796c8dcSSimon Schubert enum reggroup_type type;
375796c8dcSSimon Schubert };
385796c8dcSSimon Schubert
395796c8dcSSimon Schubert struct reggroup *
reggroup_new(const char * name,enum reggroup_type type)405796c8dcSSimon Schubert reggroup_new (const char *name, enum reggroup_type type)
415796c8dcSSimon Schubert {
425796c8dcSSimon Schubert struct reggroup *group = XMALLOC (struct reggroup);
43cf7f2e2dSJohn Marino
445796c8dcSSimon Schubert group->name = name;
455796c8dcSSimon Schubert group->type = type;
465796c8dcSSimon Schubert return group;
475796c8dcSSimon Schubert }
485796c8dcSSimon Schubert
495796c8dcSSimon Schubert /* Register group attributes. */
505796c8dcSSimon Schubert
515796c8dcSSimon Schubert const char *
reggroup_name(struct reggroup * group)525796c8dcSSimon Schubert reggroup_name (struct reggroup *group)
535796c8dcSSimon Schubert {
545796c8dcSSimon Schubert return group->name;
555796c8dcSSimon Schubert }
565796c8dcSSimon Schubert
575796c8dcSSimon Schubert enum reggroup_type
reggroup_type(struct reggroup * group)585796c8dcSSimon Schubert reggroup_type (struct reggroup *group)
595796c8dcSSimon Schubert {
605796c8dcSSimon Schubert return group->type;
615796c8dcSSimon Schubert }
625796c8dcSSimon Schubert
635796c8dcSSimon Schubert /* A linked list of groups for the given architecture. */
645796c8dcSSimon Schubert
655796c8dcSSimon Schubert struct reggroup_el
665796c8dcSSimon Schubert {
675796c8dcSSimon Schubert struct reggroup *group;
685796c8dcSSimon Schubert struct reggroup_el *next;
695796c8dcSSimon Schubert };
705796c8dcSSimon Schubert
715796c8dcSSimon Schubert struct reggroups
725796c8dcSSimon Schubert {
735796c8dcSSimon Schubert struct reggroup_el *first;
745796c8dcSSimon Schubert struct reggroup_el **last;
755796c8dcSSimon Schubert };
765796c8dcSSimon Schubert
775796c8dcSSimon Schubert static struct gdbarch_data *reggroups_data;
785796c8dcSSimon Schubert
795796c8dcSSimon Schubert static void *
reggroups_init(struct gdbarch * gdbarch)805796c8dcSSimon Schubert reggroups_init (struct gdbarch *gdbarch)
815796c8dcSSimon Schubert {
825796c8dcSSimon Schubert struct reggroups *groups = GDBARCH_OBSTACK_ZALLOC (gdbarch,
835796c8dcSSimon Schubert struct reggroups);
84cf7f2e2dSJohn Marino
855796c8dcSSimon Schubert groups->last = &groups->first;
865796c8dcSSimon Schubert return groups;
875796c8dcSSimon Schubert }
885796c8dcSSimon Schubert
895796c8dcSSimon Schubert /* Add a register group (with attribute values) to the pre-defined
905796c8dcSSimon Schubert list. */
915796c8dcSSimon Schubert
925796c8dcSSimon Schubert static void
add_group(struct reggroups * groups,struct reggroup * group,struct reggroup_el * el)935796c8dcSSimon Schubert add_group (struct reggroups *groups, struct reggroup *group,
945796c8dcSSimon Schubert struct reggroup_el *el)
955796c8dcSSimon Schubert {
965796c8dcSSimon Schubert gdb_assert (group != NULL);
975796c8dcSSimon Schubert el->group = group;
985796c8dcSSimon Schubert el->next = NULL;
995796c8dcSSimon Schubert (*groups->last) = el;
1005796c8dcSSimon Schubert groups->last = &el->next;
1015796c8dcSSimon Schubert }
1025796c8dcSSimon Schubert
1035796c8dcSSimon Schubert void
reggroup_add(struct gdbarch * gdbarch,struct reggroup * group)1045796c8dcSSimon Schubert reggroup_add (struct gdbarch *gdbarch, struct reggroup *group)
1055796c8dcSSimon Schubert {
1065796c8dcSSimon Schubert struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
1075796c8dcSSimon Schubert
1085796c8dcSSimon Schubert if (groups == NULL)
1095796c8dcSSimon Schubert {
1105796c8dcSSimon Schubert /* ULGH, called during architecture initialization. Patch
1115796c8dcSSimon Schubert things up. */
1125796c8dcSSimon Schubert groups = reggroups_init (gdbarch);
1135796c8dcSSimon Schubert deprecated_set_gdbarch_data (gdbarch, reggroups_data, groups);
1145796c8dcSSimon Schubert }
1155796c8dcSSimon Schubert add_group (groups, group,
1165796c8dcSSimon Schubert GDBARCH_OBSTACK_ZALLOC (gdbarch, struct reggroup_el));
1175796c8dcSSimon Schubert }
1185796c8dcSSimon Schubert
1195796c8dcSSimon Schubert /* The default register groups for an architecture. */
1205796c8dcSSimon Schubert
1215796c8dcSSimon Schubert static struct reggroups default_groups = { NULL, &default_groups.first };
1225796c8dcSSimon Schubert
1235796c8dcSSimon Schubert /* A register group iterator. */
1245796c8dcSSimon Schubert
1255796c8dcSSimon Schubert struct reggroup *
reggroup_next(struct gdbarch * gdbarch,struct reggroup * last)1265796c8dcSSimon Schubert reggroup_next (struct gdbarch *gdbarch, struct reggroup *last)
1275796c8dcSSimon Schubert {
1285796c8dcSSimon Schubert struct reggroups *groups;
1295796c8dcSSimon Schubert struct reggroup_el *el;
1305796c8dcSSimon Schubert
1315796c8dcSSimon Schubert /* Don't allow this function to be called during architecture
1325796c8dcSSimon Schubert creation. If there are no groups, use the default groups list. */
1335796c8dcSSimon Schubert groups = gdbarch_data (gdbarch, reggroups_data);
1345796c8dcSSimon Schubert gdb_assert (groups != NULL);
1355796c8dcSSimon Schubert if (groups->first == NULL)
1365796c8dcSSimon Schubert groups = &default_groups;
1375796c8dcSSimon Schubert
1385796c8dcSSimon Schubert /* Return the first/next reggroup. */
1395796c8dcSSimon Schubert if (last == NULL)
1405796c8dcSSimon Schubert return groups->first->group;
1415796c8dcSSimon Schubert for (el = groups->first; el != NULL; el = el->next)
1425796c8dcSSimon Schubert {
1435796c8dcSSimon Schubert if (el->group == last)
1445796c8dcSSimon Schubert {
1455796c8dcSSimon Schubert if (el->next != NULL)
1465796c8dcSSimon Schubert return el->next->group;
1475796c8dcSSimon Schubert else
1485796c8dcSSimon Schubert return NULL;
1495796c8dcSSimon Schubert }
1505796c8dcSSimon Schubert }
1515796c8dcSSimon Schubert return NULL;
1525796c8dcSSimon Schubert }
1535796c8dcSSimon Schubert
1545796c8dcSSimon Schubert /* Is REGNUM a member of REGGROUP? */
1555796c8dcSSimon Schubert int
default_register_reggroup_p(struct gdbarch * gdbarch,int regnum,struct reggroup * group)1565796c8dcSSimon Schubert default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
1575796c8dcSSimon Schubert struct reggroup *group)
1585796c8dcSSimon Schubert {
1595796c8dcSSimon Schubert int vector_p;
1605796c8dcSSimon Schubert int float_p;
1615796c8dcSSimon Schubert int raw_p;
1625796c8dcSSimon Schubert
1635796c8dcSSimon Schubert if (gdbarch_register_name (gdbarch, regnum) == NULL
1645796c8dcSSimon Schubert || *gdbarch_register_name (gdbarch, regnum) == '\0')
1655796c8dcSSimon Schubert return 0;
1665796c8dcSSimon Schubert if (group == all_reggroup)
1675796c8dcSSimon Schubert return 1;
1685796c8dcSSimon Schubert vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
1695796c8dcSSimon Schubert float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
1705796c8dcSSimon Schubert raw_p = regnum < gdbarch_num_regs (gdbarch);
1715796c8dcSSimon Schubert if (group == float_reggroup)
1725796c8dcSSimon Schubert return float_p;
1735796c8dcSSimon Schubert if (group == vector_reggroup)
1745796c8dcSSimon Schubert return vector_p;
1755796c8dcSSimon Schubert if (group == general_reggroup)
1765796c8dcSSimon Schubert return (!vector_p && !float_p);
1775796c8dcSSimon Schubert if (group == save_reggroup || group == restore_reggroup)
1785796c8dcSSimon Schubert return raw_p;
1795796c8dcSSimon Schubert return 0;
1805796c8dcSSimon Schubert }
1815796c8dcSSimon Schubert
1825796c8dcSSimon Schubert /* Dump out a table of register groups for the current architecture. */
1835796c8dcSSimon Schubert
1845796c8dcSSimon Schubert static void
reggroups_dump(struct gdbarch * gdbarch,struct ui_file * file)1855796c8dcSSimon Schubert reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file)
1865796c8dcSSimon Schubert {
1875796c8dcSSimon Schubert struct reggroup *group = NULL;
1885796c8dcSSimon Schubert
1895796c8dcSSimon Schubert do
1905796c8dcSSimon Schubert {
1915796c8dcSSimon Schubert /* Group name. */
1925796c8dcSSimon Schubert {
1935796c8dcSSimon Schubert const char *name;
194cf7f2e2dSJohn Marino
1955796c8dcSSimon Schubert if (group == NULL)
1965796c8dcSSimon Schubert name = "Group";
1975796c8dcSSimon Schubert else
1985796c8dcSSimon Schubert name = reggroup_name (group);
1995796c8dcSSimon Schubert fprintf_unfiltered (file, " %-10s", name);
2005796c8dcSSimon Schubert }
2015796c8dcSSimon Schubert
2025796c8dcSSimon Schubert /* Group type. */
2035796c8dcSSimon Schubert {
2045796c8dcSSimon Schubert const char *type;
205cf7f2e2dSJohn Marino
2065796c8dcSSimon Schubert if (group == NULL)
2075796c8dcSSimon Schubert type = "Type";
2085796c8dcSSimon Schubert else
2095796c8dcSSimon Schubert {
2105796c8dcSSimon Schubert switch (reggroup_type (group))
2115796c8dcSSimon Schubert {
2125796c8dcSSimon Schubert case USER_REGGROUP:
2135796c8dcSSimon Schubert type = "user";
2145796c8dcSSimon Schubert break;
2155796c8dcSSimon Schubert case INTERNAL_REGGROUP:
2165796c8dcSSimon Schubert type = "internal";
2175796c8dcSSimon Schubert break;
2185796c8dcSSimon Schubert default:
2195796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("bad switch"));
2205796c8dcSSimon Schubert }
2215796c8dcSSimon Schubert }
2225796c8dcSSimon Schubert fprintf_unfiltered (file, " %-10s", type);
2235796c8dcSSimon Schubert }
2245796c8dcSSimon Schubert
2255796c8dcSSimon Schubert /* Note: If you change this, be sure to also update the
2265796c8dcSSimon Schubert documentation. */
2275796c8dcSSimon Schubert
2285796c8dcSSimon Schubert fprintf_unfiltered (file, "\n");
2295796c8dcSSimon Schubert
2305796c8dcSSimon Schubert group = reggroup_next (gdbarch, group);
2315796c8dcSSimon Schubert }
2325796c8dcSSimon Schubert while (group != NULL);
2335796c8dcSSimon Schubert }
2345796c8dcSSimon Schubert
2355796c8dcSSimon Schubert static void
maintenance_print_reggroups(char * args,int from_tty)2365796c8dcSSimon Schubert maintenance_print_reggroups (char *args, int from_tty)
2375796c8dcSSimon Schubert {
2385796c8dcSSimon Schubert struct gdbarch *gdbarch = get_current_arch ();
2395796c8dcSSimon Schubert
2405796c8dcSSimon Schubert if (args == NULL)
2415796c8dcSSimon Schubert reggroups_dump (gdbarch, gdb_stdout);
2425796c8dcSSimon Schubert else
2435796c8dcSSimon Schubert {
2445796c8dcSSimon Schubert struct cleanup *cleanups;
2455796c8dcSSimon Schubert struct ui_file *file = gdb_fopen (args, "w");
246cf7f2e2dSJohn Marino
2475796c8dcSSimon Schubert if (file == NULL)
2485796c8dcSSimon Schubert perror_with_name (_("maintenance print reggroups"));
2495796c8dcSSimon Schubert cleanups = make_cleanup_ui_file_delete (file);
2505796c8dcSSimon Schubert reggroups_dump (gdbarch, file);
2515796c8dcSSimon Schubert do_cleanups (cleanups);
2525796c8dcSSimon Schubert }
2535796c8dcSSimon Schubert }
2545796c8dcSSimon Schubert
2555796c8dcSSimon Schubert /* Pre-defined register groups. */
2565796c8dcSSimon Schubert static struct reggroup general_group = { "general", USER_REGGROUP };
2575796c8dcSSimon Schubert static struct reggroup float_group = { "float", USER_REGGROUP };
2585796c8dcSSimon Schubert static struct reggroup system_group = { "system", USER_REGGROUP };
2595796c8dcSSimon Schubert static struct reggroup vector_group = { "vector", USER_REGGROUP };
2605796c8dcSSimon Schubert static struct reggroup all_group = { "all", USER_REGGROUP };
2615796c8dcSSimon Schubert static struct reggroup save_group = { "save", INTERNAL_REGGROUP };
2625796c8dcSSimon Schubert static struct reggroup restore_group = { "restore", INTERNAL_REGGROUP };
2635796c8dcSSimon Schubert
2645796c8dcSSimon Schubert struct reggroup *const general_reggroup = &general_group;
2655796c8dcSSimon Schubert struct reggroup *const float_reggroup = &float_group;
2665796c8dcSSimon Schubert struct reggroup *const system_reggroup = &system_group;
2675796c8dcSSimon Schubert struct reggroup *const vector_reggroup = &vector_group;
2685796c8dcSSimon Schubert struct reggroup *const all_reggroup = &all_group;
2695796c8dcSSimon Schubert struct reggroup *const save_reggroup = &save_group;
2705796c8dcSSimon Schubert struct reggroup *const restore_reggroup = &restore_group;
2715796c8dcSSimon Schubert
2725796c8dcSSimon Schubert extern initialize_file_ftype _initialize_reggroup; /* -Wmissing-prototypes */
2735796c8dcSSimon Schubert
2745796c8dcSSimon Schubert void
_initialize_reggroup(void)2755796c8dcSSimon Schubert _initialize_reggroup (void)
2765796c8dcSSimon Schubert {
2775796c8dcSSimon Schubert reggroups_data = gdbarch_data_register_post_init (reggroups_init);
2785796c8dcSSimon Schubert
2795796c8dcSSimon Schubert /* The pre-defined list of groups. */
2805796c8dcSSimon Schubert add_group (&default_groups, general_reggroup, XMALLOC (struct reggroup_el));
2815796c8dcSSimon Schubert add_group (&default_groups, float_reggroup, XMALLOC (struct reggroup_el));
2825796c8dcSSimon Schubert add_group (&default_groups, system_reggroup, XMALLOC (struct reggroup_el));
2835796c8dcSSimon Schubert add_group (&default_groups, vector_reggroup, XMALLOC (struct reggroup_el));
2845796c8dcSSimon Schubert add_group (&default_groups, all_reggroup, XMALLOC (struct reggroup_el));
2855796c8dcSSimon Schubert add_group (&default_groups, save_reggroup, XMALLOC (struct reggroup_el));
2865796c8dcSSimon Schubert add_group (&default_groups, restore_reggroup, XMALLOC (struct reggroup_el));
2875796c8dcSSimon Schubert
2885796c8dcSSimon Schubert add_cmd ("reggroups", class_maintenance,
2895796c8dcSSimon Schubert maintenance_print_reggroups, _("\
2905796c8dcSSimon Schubert Print the internal register group names.\n\
2915796c8dcSSimon Schubert Takes an optional file parameter."),
2925796c8dcSSimon Schubert &maintenanceprintlist);
2935796c8dcSSimon Schubert
2945796c8dcSSimon Schubert }
295