]>
Commit | Line | Data |
---|---|---|
eb8bc282 AC |
1 | /* User visible, per-frame registers, for GDB, the GNU debugger. |
2 | ||
3 | Copyright 2002 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 2 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, write to the Free Software | |
21 | Foundation, Inc., 59 Temple Place - Suite 330, | |
22 | Boston, MA 02111-1307, USA. */ | |
23 | ||
24 | #include "defs.h" | |
25 | #include "user-regs.h" | |
26 | #include "gdbtypes.h" | |
27 | #include "gdb_string.h" | |
28 | #include "gdb_assert.h" | |
29 | #include "frame.h" | |
30 | ||
31 | /* A table of user registers. | |
32 | ||
33 | User registers have regnum's that live above of the range [0 | |
34 | .. NUM_REGS + NUM_PSEUDO_REGS) (which is controlled by the target). | |
35 | The target should never see a user register's regnum value. | |
36 | ||
37 | Always append, never delete. By doing this, the relative regnum | |
38 | (offset from NUM_REGS + NUM_PSEUDO_REGS) assigned to each user | |
39 | register never changes. */ | |
40 | ||
41 | struct user_reg | |
42 | { | |
43 | const char *name; | |
44 | struct value *(*read) (struct frame_info * frame); | |
45 | }; | |
46 | ||
47 | struct user_regs | |
48 | { | |
49 | struct user_reg *user; | |
50 | int nr; | |
51 | }; | |
52 | ||
53 | static void | |
54 | append_user_reg (struct user_regs *regs, | |
55 | const char *name, user_reg_read_ftype *read) | |
56 | { | |
57 | regs->nr++; | |
58 | regs->user = xrealloc (regs->user, | |
59 | regs->nr * sizeof (struct user_reg)); | |
60 | regs->user[regs->nr - 1].name = name; | |
61 | regs->user[regs->nr - 1].read = read; | |
62 | } | |
63 | ||
64 | /* An array of the builtin user registers. */ | |
65 | ||
66 | static struct user_regs builtin_user_regs; | |
67 | ||
68 | void | |
69 | user_reg_add_builtin (const char *name, user_reg_read_ftype *read) | |
70 | { | |
71 | append_user_reg (&builtin_user_regs, name, read); | |
72 | } | |
73 | ||
74 | /* Per-architecture user registers. Start with the builtin user | |
75 | registers and then, again, append. */ | |
76 | ||
77 | static struct gdbarch_data *user_regs_data; | |
78 | ||
79 | static void * | |
80 | user_regs_init (struct gdbarch *gdbarch) | |
81 | { | |
82 | int i; | |
83 | struct user_regs *regs = XMALLOC (struct user_regs); | |
84 | memset (regs, 0, sizeof (struct user_regs)); | |
85 | for (i = 0; i < builtin_user_regs.nr; i++) | |
86 | append_user_reg (regs, builtin_user_regs.user[i].name, | |
87 | builtin_user_regs.user[i].read); | |
88 | return regs; | |
89 | } | |
90 | ||
91 | static void | |
92 | user_regs_free (struct gdbarch *gdbarch, void *data) | |
93 | { | |
94 | struct user_regs *regs = data; | |
95 | xfree (regs->user); | |
96 | xfree (regs); | |
97 | } | |
98 | ||
99 | void | |
100 | user_reg_add (struct gdbarch *gdbarch, const char *name, | |
101 | user_reg_read_ftype *read) | |
102 | { | |
103 | struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data); | |
104 | if (regs == NULL) | |
105 | { | |
106 | /* ULGH, called during architecture initialization. Patch | |
107 | things up. */ | |
108 | regs = user_regs_init (gdbarch); | |
109 | set_gdbarch_data (gdbarch, user_regs_data, regs); | |
110 | } | |
111 | append_user_reg (regs, name, read); | |
112 | } | |
113 | ||
114 | int | |
115 | user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name, | |
116 | int len) | |
117 | { | |
118 | /* Make life easy, set the len to something reasonable. */ | |
119 | if (len < 0) | |
120 | len = strlen (name); | |
121 | ||
122 | /* Search register name space first - always let an architecture | |
123 | specific register override the user registers. */ | |
124 | { | |
125 | int i; | |
126 | int maxregs = (gdbarch_num_regs (gdbarch) | |
127 | + gdbarch_num_pseudo_regs (gdbarch)); | |
128 | for (i = 0; i < maxregs; i++) | |
129 | { | |
130 | const char *regname = gdbarch_register_name (gdbarch, i); | |
131 | if (regname != NULL && len == strlen (regname) | |
132 | && strncmp (regname, name, len) == 0) | |
133 | { | |
134 | return i; | |
135 | } | |
136 | } | |
137 | } | |
138 | ||
139 | /* Search the user name space. */ | |
140 | { | |
141 | struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data); | |
142 | int reg; | |
143 | for (reg = 0; reg < regs->nr; reg++) | |
144 | { | |
145 | if ((len < 0 && strcmp (regs->user[reg].name, name)) | |
146 | || (len == strlen (regs->user[reg].name) | |
147 | && strncmp (regs->user[reg].name, name, len) == 0)) | |
148 | return NUM_REGS + NUM_PSEUDO_REGS + reg; | |
149 | } | |
150 | } | |
151 | ||
152 | return -1; | |
153 | } | |
154 | ||
155 | const char * | |
156 | user_reg_map_regnum_to_name (struct gdbarch *gdbarch, int regnum) | |
157 | { | |
158 | int maxregs = (gdbarch_num_regs (gdbarch) | |
159 | + gdbarch_num_pseudo_regs (gdbarch)); | |
160 | struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data); | |
161 | if (regnum < 0) | |
162 | return NULL; | |
163 | if (regnum < maxregs) | |
164 | return gdbarch_register_name (gdbarch, regnum); | |
165 | if (regnum < (maxregs + regs->nr)) | |
166 | return regs->user[regnum - maxregs].name; | |
167 | return NULL; | |
168 | } | |
169 | ||
170 | struct value * | |
171 | value_of_user_reg (int regnum, struct frame_info *frame) | |
172 | { | |
173 | struct gdbarch *gdbarch = get_frame_arch (frame); | |
174 | struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data); | |
175 | int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS); | |
176 | gdb_assert (reg >= 0 && reg < regs->nr); | |
177 | return regs->user[reg].read (frame); | |
178 | } | |
179 | ||
180 | extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */ | |
181 | ||
182 | void | |
183 | _initialize_user_regs (void) | |
184 | { | |
185 | user_regs_data = register_gdbarch_data (user_regs_init, user_regs_free); | |
186 | } |