]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/sim-watch.c
o Add modulo argument to sim_core_attach
[thirdparty/binutils-gdb.git] / sim / common / sim-watch.c
1 /* Mips simulator watchpoint support.
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #include "sim-main.h"
22 #include "sim-options.h"
23
24 #include "sim-assert.h"
25
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #else
29 #ifdef HAVE_STRINGS_H
30 #include <strings.h>
31 #endif
32 #endif
33
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37
38 #include <signal.h>
39
40 static DECLARE_OPTION_HANDLER (watch_option_handler);
41
42 enum {
43 OPTION_WATCH_DELETE = OPTION_START,
44
45 OPTION_WATCH_PC,
46 OPTION_WATCH_CLOCK,
47 OPTION_WATCH_CYCLES,
48
49 OPTION_ACTION_PC,
50 OPTION_ACTION_CLOCK,
51 OPTION_ACTION_CYCLES,
52 };
53
54
55 static void
56 delete_watchpoint (SIM_DESC sd, watchpoint_type type)
57 {
58 sim_watch_point *point = &STATE_WATCHPOINTS (sd)->points[type];
59 if (point->event != NULL)
60 sim_events_deschedule (sd, point->event);
61 point->action = invalid_watchpoint_action;
62 point->event = NULL;
63 }
64
65
66 static sim_event_handler handle_watchpoint;
67
68 static SIM_RC
69 schedule_watchpoint (SIM_DESC sd,
70 watchpoint_type type,
71 unsigned long arg,
72 int is_within,
73 int is_command)
74 {
75 sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
76 sim_watch_point *point = &watch->points[type];
77 if (point->event != NULL)
78 sim_events_deschedule (sd, point->event);
79 point->arg = arg;
80 point->is_within = is_within;
81 if (point->action == invalid_watchpoint_action)
82 point->action = break_watchpoint_action;
83 if (is_command)
84 switch (type)
85 {
86 case pc_watchpoint:
87 point->event = sim_events_watch_sim (sd, watch->pc, watch->sizeof_pc,
88 0/* host-endian */,
89 point->is_within,
90 point->arg, point->arg, /* PC == arg? */
91 handle_watchpoint,
92 point);
93 return SIM_RC_OK;
94 case clock_watchpoint:
95 point->event = sim_events_watch_clock (sd,
96 point->arg, /* ms time */
97 handle_watchpoint,
98 point);
99 return SIM_RC_OK;
100 case cycles_watchpoint:
101 point->event = sim_events_schedule (sd, point->arg, /* time */
102 handle_watchpoint,
103 point);
104 return SIM_RC_OK;
105 default:
106 sim_engine_abort (sd, NULL, NULL_CIA,
107 "handle_watchpoint - internal error - bad switch");
108 return SIM_RC_FAIL;
109 }
110 return SIM_RC_OK;
111 }
112
113
114 static void
115 handle_watchpoint (SIM_DESC sd, void *data)
116 {
117 sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
118 sim_watch_point *point = data;
119 watchpoint_type type = point - watch->points;
120
121 switch (point->action)
122 {
123
124 case break_watchpoint_action:
125 point->event = NULL; /* gone */
126 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIGINT);
127 break;
128
129 case n_interrupt_watchpoint_action:
130 /* First reschedule this event */
131 schedule_watchpoint (sd, type, point->arg, point->is_within, 1/*is-command*/);
132 /* FALL-THROUGH */
133
134 case interrupt_watchpoint_action:
135 watch->interrupt_handler (sd, NULL);
136 break;
137
138 default:
139 sim_engine_abort (sd, NULL, NULL_CIA,
140 "handle_watchpoint - internal error - bad switch");
141
142 }
143 }
144
145
146 static SIM_RC
147 action_watchpoint (SIM_DESC sd, watchpoint_type type, const char *arg)
148 {
149 sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
150 sim_watch_point *point = &watch->points[type];
151 if (strcmp (arg, "break") == 0)
152 {
153 point->action = break_watchpoint_action;
154 }
155 else if (strcmp (arg, "int") == 0)
156 {
157 if (watch->interrupt_handler == NULL)
158 {
159 sim_io_eprintf (sd, "This simulator does not support int watchpoints\n");
160 return SIM_RC_FAIL;
161 }
162 point->action = interrupt_watchpoint_action;
163 }
164 else if (strcmp (arg, "+int") == 0)
165 {
166 if (watch->interrupt_handler == NULL)
167 {
168 sim_io_eprintf (sd, "This simulator does not support int watchpoints\n");
169 return SIM_RC_FAIL;
170 }
171 point->action = n_interrupt_watchpoint_action;
172 }
173 else
174 {
175 sim_io_eprintf (sd, "Interrupts other than `int' currently unsuported\n");
176 return SIM_RC_FAIL;
177 }
178 return SIM_RC_OK;
179 }
180
181
182 static const OPTION watch_options[] =
183 {
184 { {"watch-delete", required_argument, NULL, OPTION_WATCH_DELETE },
185 '\0', "all|pc|cycles|clock", "Delete a watchpoint",
186 watch_option_handler },
187 { {"delete-watch", required_argument, NULL, OPTION_WATCH_DELETE },
188 '\0', "all|pc|cycles|clock", NULL,
189 watch_option_handler },
190
191 { {"watch-pc", required_argument, NULL, OPTION_WATCH_PC },
192 '\0', "[!] VALUE", "Watch the PC (break)",
193 watch_option_handler },
194 { {"watch-clock", required_argument, NULL, OPTION_WATCH_CLOCK },
195 '\0', "TIME-IN-MS", "Watch the clock (break)",
196 watch_option_handler },
197 { {"watch-cycles", required_argument, NULL, OPTION_WATCH_CYCLES },
198 '\0', "CYCLES", "Watch the cycles (break)",
199 watch_option_handler },
200
201 { {"action-pc", required_argument, NULL, OPTION_ACTION_PC },
202 '\0', "break|int|+int", "Action taken by PC watchpoint",
203 watch_option_handler },
204 { {"action-clock", required_argument, NULL, OPTION_ACTION_CLOCK },
205 '\0', "break|int|+int", "Action taken by CLOCK watchpoint",
206 watch_option_handler },
207 { {"action-cycles", required_argument, NULL, OPTION_ACTION_CYCLES },
208 '\0', "break|int|+int", "Action taken by CYCLES watchpoint",
209 watch_option_handler },
210
211 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
212 };
213
214
215 static SIM_RC
216 watch_option_handler (sd, opt, arg, is_command)
217 SIM_DESC sd;
218 int opt;
219 char *arg;
220 int is_command;
221 {
222 switch (opt)
223 {
224
225 case OPTION_WATCH_DELETE:
226 if (strcmp (arg, "all") == 0
227 || strcmp (arg, "pc") == 0)
228 {
229 delete_watchpoint (sd, pc_watchpoint);
230 return SIM_RC_OK;
231 }
232 if (strcmp (arg, "all") == 0
233 || strcmp (arg, "clock") == 0)
234 {
235 delete_watchpoint (sd, clock_watchpoint);
236 return SIM_RC_OK;
237 }
238 if (strcmp (arg, "all") == 0
239 || strcmp (arg, "cycles") == 0)
240 {
241 delete_watchpoint (sd, cycles_watchpoint);
242 return SIM_RC_OK;
243 }
244 sim_io_eprintf (sd, "Unknown watchpoint type `%s'\n", arg);
245 return SIM_RC_FAIL;
246
247 case OPTION_WATCH_PC:
248 if (STATE_WATCHPOINTS (sd)->pc == NULL)
249 {
250 sim_io_eprintf (sd, "PC watchpoints are not supported for this simulator\n");
251 return SIM_RC_FAIL;
252 }
253 if (arg[0] == '!')
254 return schedule_watchpoint (sd, pc_watchpoint, strtoul (arg + 1, NULL, 0),
255 0 /* !is_within */, is_command);
256 else
257 return schedule_watchpoint (sd, pc_watchpoint, strtoul (arg, NULL, 0),
258 1 /* is_within */, is_command);
259
260 case OPTION_WATCH_CLOCK:
261 return schedule_watchpoint (sd, clock_watchpoint, strtoul (arg, NULL, 0), 0, is_command);
262
263 case OPTION_WATCH_CYCLES:
264 return schedule_watchpoint (sd, cycles_watchpoint, strtoul (arg, NULL, 0), 0, is_command);
265
266 case OPTION_ACTION_PC:
267 return action_watchpoint (sd, pc_watchpoint, arg);
268
269 case OPTION_ACTION_CLOCK:
270 return action_watchpoint (sd, clock_watchpoint, arg);
271
272 case OPTION_ACTION_CYCLES:
273 return action_watchpoint (sd, cycles_watchpoint, arg);
274
275
276 default:
277 sim_io_eprintf (sd, "Unknown watch option %d\n", opt);
278 return SIM_RC_FAIL;
279
280 }
281
282 }
283
284 static SIM_RC
285 sim_watchpoint_init (SIM_DESC sd)
286 {
287 /* schedule any watchpoints enabled by command line options */
288 sim_watchpoints *watch = STATE_WATCHPOINTS (sd);
289 watchpoint_type type;
290 for (type = 0; type < nr_watchpoint_types; type++)
291 {
292 if (watch->points[type].action != invalid_watchpoint_action)
293 schedule_watchpoint (sd, type,
294 watch->points[type].arg,
295 watch->points[type].is_within,
296 1 /*is-command*/);
297 }
298 return SIM_RC_OK;
299 }
300
301
302 SIM_RC
303 sim_watchpoint_install (SIM_DESC sd)
304 {
305 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
306 sim_add_option_table (sd, watch_options);
307 sim_module_add_init_fn (sd, sim_watchpoint_init);
308 return SIM_RC_OK;
309 }