1 /* Register groupings for GDB, the GNU debugger.
2 
3    Copyright (C) 2002-2024 Free Software Foundation, Inc.
4 
5    Contributed by Red Hat.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 #include "arch-utils.h"
23 #include "reggroups.h"
24 #include "gdbtypes.h"
25 #include "regcache.h"
26 #include "command.h"
27 #include "cli/cli-cmds.h"
28 #include "gdbsupport/gdb_obstack.h"
29 
30 /* See reggroups.h.  */
31 
32 const reggroup *
reggroup_new(const char * name,enum reggroup_type type)33 reggroup_new (const char *name, enum reggroup_type type)
34 {
35   return new reggroup (name, type);
36 }
37 
38 /* See reggroups.h.  */
39 
40 const reggroup *
reggroup_gdbarch_new(struct gdbarch * gdbarch,const char * name,enum reggroup_type type)41 reggroup_gdbarch_new (struct gdbarch *gdbarch, const char *name,
42                           enum reggroup_type type)
43 {
44   name = gdbarch_obstack_strdup (gdbarch, name);
45   return obstack_new<struct reggroup> (gdbarch_obstack (gdbarch),
46                                                name, type);
47 }
48 
49 /* A container holding all the register groups for a particular
50    architecture.  */
51 
52 struct reggroups
53 {
reggroupsreggroups54   reggroups ()
55   {
56     /* Add the default groups.  */
57     add (general_reggroup);
58     add (float_reggroup);
59     add (system_reggroup);
60     add (vector_reggroup);
61     add (all_reggroup);
62     add (save_reggroup);
63     add (restore_reggroup);
64   }
65 
66   DISABLE_COPY_AND_ASSIGN (reggroups);
67 
68   /* Add GROUP to the list of register groups.  */
69 
addreggroups70   void add (const reggroup *group)
71   {
72     gdb_assert (group != nullptr);
73 
74     auto find_by_name = [group] (const reggroup *g)
75       {
76           return streq (group->name (), g->name ());
77       };
78     gdb_assert (std::find_if (m_groups.begin (), m_groups.end (), find_by_name)
79                     == m_groups.end ());
80 
81     m_groups.push_back (group);
82   }
83 
84   /* The number of register groups.  */
85 
86   std::vector<struct reggroup *>::size_type
sizereggroups87   size () const
88   {
89     return m_groups.size ();
90   }
91 
92   /* Return a reference to the list of all groups.  */
93 
94   const std::vector<const struct reggroup *> &
groupsreggroups95   groups () const
96   {
97     return m_groups;
98   }
99 
100 private:
101   /* The register groups.  */
102   std::vector<const struct reggroup *> m_groups;
103 };
104 
105 /* Key used to lookup register group data from a gdbarch.  */
106 
107 static const registry<gdbarch>::key<reggroups> reggroups_data;
108 
109 /* Get the reggroups for the architecture, creating if necessary.  */
110 
111 static reggroups *
get_reggroups(struct gdbarch * gdbarch)112 get_reggroups (struct gdbarch *gdbarch)
113 {
114   struct reggroups *groups = reggroups_data.get (gdbarch);
115   if (groups == nullptr)
116     groups = reggroups_data.emplace (gdbarch);
117   return groups;
118 }
119 
120 /* See reggroups.h.  */
121 
122 void
reggroup_add(struct gdbarch * gdbarch,const reggroup * group)123 reggroup_add (struct gdbarch *gdbarch, const reggroup *group)
124 {
125   struct reggroups *groups = get_reggroups (gdbarch);
126 
127   gdb_assert (groups != nullptr);
128   gdb_assert (group != nullptr);
129 
130   groups->add (group);
131 }
132 
133 /* See reggroups.h.  */
134 const std::vector<const reggroup *> &
gdbarch_reggroups(struct gdbarch * gdbarch)135 gdbarch_reggroups (struct gdbarch *gdbarch)
136 {
137   struct reggroups *groups = get_reggroups (gdbarch);
138   gdb_assert (groups != nullptr);
139   gdb_assert (groups->size () > 0);
140   return groups->groups ();
141 }
142 
143 /* See reggroups.h.  */
144 
145 int
default_register_reggroup_p(struct gdbarch * gdbarch,int regnum,const struct reggroup * group)146 default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
147                                    const struct reggroup *group)
148 {
149   int vector_p;
150   int float_p;
151   int raw_p;
152 
153   if (*gdbarch_register_name (gdbarch, regnum) == '\0')
154     return 0;
155   if (group == all_reggroup)
156     return 1;
157   vector_p = register_type (gdbarch, regnum)->is_vector ();
158   float_p = (register_type (gdbarch, regnum)->code () == TYPE_CODE_FLT
159                || (register_type (gdbarch, regnum)->code ()
160                      == TYPE_CODE_DECFLOAT));
161   raw_p = regnum < gdbarch_num_regs (gdbarch);
162   if (group == float_reggroup)
163     return float_p;
164   if (group == vector_reggroup)
165     return vector_p;
166   if (group == general_reggroup)
167     return (!vector_p && !float_p);
168   if (group == save_reggroup || group == restore_reggroup)
169     return raw_p;
170   return 0;
171 }
172 
173 /* See reggroups.h.  */
174 
175 const reggroup *
reggroup_find(struct gdbarch * gdbarch,const char * name)176 reggroup_find (struct gdbarch *gdbarch, const char *name)
177 {
178   for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
179     {
180       if (strcmp (name, group->name ()) == 0)
181           return group;
182     }
183   return NULL;
184 }
185 
186 /* Dump out a table of register groups for the current architecture.  */
187 
188 static void
reggroups_dump(struct gdbarch * gdbarch,struct ui_file * file)189 reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file)
190 {
191   static constexpr const char *fmt = " %-10s %-10s\n";
192 
193   gdb_printf (file, fmt, "Group", "Type");
194 
195   for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
196     {
197       /* Group name.  */
198       const char *name = group->name ();
199 
200       /* Group type.  */
201       const char *type;
202 
203       switch (group->type ())
204           {
205           case USER_REGGROUP:
206             type = "user";
207             break;
208           case INTERNAL_REGGROUP:
209             type = "internal";
210             break;
211           default:
212             internal_error (_("bad switch"));
213           }
214 
215       /* Note: If you change this, be sure to also update the
216            documentation.  */
217 
218       gdb_printf (file, fmt, name, type);
219     }
220 }
221 
222 /* Implement 'maintenance print reggroups' command.  */
223 
224 static void
maintenance_print_reggroups(const char * args,int from_tty)225 maintenance_print_reggroups (const char *args, int from_tty)
226 {
227   struct gdbarch *gdbarch = get_current_arch ();
228 
229   if (args == NULL)
230     reggroups_dump (gdbarch, gdb_stdout);
231   else
232     {
233       stdio_file file;
234 
235       if (!file.open (args, "w"))
236           perror_with_name (_("maintenance print reggroups"));
237       reggroups_dump (gdbarch, &file);
238     }
239 }
240 
241 /* Pre-defined register groups.  */
242 static const reggroup general_group = { "general", USER_REGGROUP };
243 static const reggroup float_group = { "float", USER_REGGROUP };
244 static const reggroup system_group = { "system", USER_REGGROUP };
245 static const reggroup vector_group = { "vector", USER_REGGROUP };
246 static const reggroup all_group = { "all", USER_REGGROUP };
247 static const reggroup save_group = { "save", INTERNAL_REGGROUP };
248 static const reggroup restore_group = { "restore", INTERNAL_REGGROUP };
249 
250 const reggroup *const general_reggroup = &general_group;
251 const reggroup *const float_reggroup = &float_group;
252 const reggroup *const system_reggroup = &system_group;
253 const reggroup *const vector_reggroup = &vector_group;
254 const reggroup *const all_reggroup = &all_group;
255 const reggroup *const save_reggroup = &save_group;
256 const reggroup *const restore_reggroup = &restore_group;
257 
258 void _initialize_reggroup ();
259 void
_initialize_reggroup()260 _initialize_reggroup ()
261 {
262   add_cmd ("reggroups", class_maintenance,
263              maintenance_print_reggroups, _("\
264 Print the internal register group names.\n\
265 Takes an optional file parameter."),
266              &maintenanceprintlist);
267 
268 }
269