import gdb-1999-07-19 snapshot
[external/binutils.git] / sim / common / sim-break.c
1 /* Simulator breakpoint 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 <stdio.h>
22
23 #include "sim-main.h"
24 #include "sim-assert.h"
25 #include "sim-break.h"
26
27 #ifndef SIM_BREAKPOINT
28 #define SIM_BREAKPOINT {0x00}
29 #define SIM_BREAKPOINT_SIZE (1)
30 #endif
31
32 struct
33 sim_breakpoint
34 {
35   struct sim_breakpoint *next;
36   SIM_ADDR addr;                /* Address of this breakpoint */
37   int flags;
38   unsigned char loc_contents[SIM_BREAKPOINT_SIZE]; /* Contents of addr while
39                                                       BP is enabled */
40 };
41
42 #define SIM_BREAK_INSERTED 0x1  /* Breakpoint has been inserted */
43 #define SIM_BREAK_DISABLED 0x2  /* Breakpoint is disabled */
44
45 static unsigned char sim_breakpoint [] = SIM_BREAKPOINT;
46
47 static void insert_breakpoint PARAMS ((SIM_DESC sd,
48                                        struct sim_breakpoint *bp));
49 static void remove_breakpoint PARAMS ((SIM_DESC sd,
50                                        struct sim_breakpoint *bp));
51 static SIM_RC resume_handler PARAMS ((SIM_DESC sd));
52 static SIM_RC suspend_handler PARAMS ((SIM_DESC sd));
53
54
55 /* Do the actual work of inserting a breakpoint into the instruction
56    stream. */
57
58 static void
59 insert_breakpoint (sd, bp)
60      SIM_DESC sd;
61      struct sim_breakpoint *bp;
62 {
63   if (bp->flags & (SIM_BREAK_INSERTED | SIM_BREAK_DISABLED))
64     return;
65
66   sim_core_read_buffer (sd, NULL, exec_map, bp->loc_contents,
67                         bp->addr, SIM_BREAKPOINT_SIZE);
68   sim_core_write_buffer (sd, NULL, exec_map, sim_breakpoint,
69                          bp->addr, SIM_BREAKPOINT_SIZE);
70   bp->flags |= SIM_BREAK_INSERTED;
71 }
72
73 /* Do the actual work of removing a breakpoint. */
74
75 static void
76 remove_breakpoint (sd, bp)
77      SIM_DESC sd;
78      struct sim_breakpoint *bp;
79 {
80   if (!(bp->flags & SIM_BREAK_INSERTED))
81     return;
82
83   sim_core_write_buffer (sd, NULL, exec_map, bp->loc_contents,
84                          bp->addr, SIM_BREAKPOINT_SIZE);
85   bp->flags &= ~SIM_BREAK_INSERTED;
86 }
87
88 /* Come here when a breakpoint insn is hit.  If it's really a breakpoint, we
89    halt things, and never return.  If it's a false hit, we return to let the
90    caller handle things.  */
91
92 void
93 sim_handle_breakpoint (sd, cpu, cia)
94      SIM_DESC sd;
95      sim_cpu *cpu;
96      sim_cia cia;
97 {
98   struct sim_breakpoint *bp;
99
100   for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
101     if (bp->addr == CIA_ADDR (cia))
102       break;
103
104   if (!bp || !(bp->flags & SIM_BREAK_INSERTED))
105     return;
106
107   sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, cia, sim_stopped, SIM_SIGTRAP);
108 }
109
110 /* Handler functions for simulator resume and suspend events. */
111
112 static SIM_RC
113 resume_handler (sd)
114      SIM_DESC sd;
115 {
116   struct sim_breakpoint *bp;
117
118   for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
119     insert_breakpoint (sd, bp);
120
121   return SIM_RC_OK;
122 }
123
124 static SIM_RC
125 suspend_handler (sd)
126      SIM_DESC sd;
127 {
128   struct sim_breakpoint *bp;
129
130   for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
131     remove_breakpoint (sd, bp);
132
133   return SIM_RC_OK;
134 }
135
136 /* Called from simulator module initialization.  */
137
138 SIM_RC
139 sim_break_install (sd)
140      SIM_DESC sd;
141 {
142   sim_module_add_resume_fn (sd, resume_handler);
143   sim_module_add_suspend_fn (sd, suspend_handler);
144
145   return SIM_RC_OK;
146 }
147
148 /* Install a breakpoint.  This is a user-function.  The breakpoint isn't
149    actually installed here.  We just record it.  Resume_handler does the
150    actual work.
151 */
152
153 SIM_RC
154 sim_set_breakpoint (sd, addr)
155      SIM_DESC sd;
156      SIM_ADDR addr;
157 {
158   struct sim_breakpoint *bp;
159
160   for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
161     if (bp->addr == addr)
162       return SIM_RC_DUPLICATE_BREAKPOINT; /* Already there */
163     else
164       break; /* FIXME: why not scan all bp's? */
165
166   bp = ZALLOC (struct sim_breakpoint);
167
168   bp->addr = addr;
169   bp->next = STATE_BREAKPOINTS (sd);
170   bp->flags = 0;
171   STATE_BREAKPOINTS (sd) = bp;
172
173   return SIM_RC_OK;
174 }
175
176 /* Delete a breakpoint.  All knowlege of the breakpoint is removed from the
177    simulator.
178 */
179
180 SIM_RC
181 sim_clear_breakpoint (sd, addr)
182      SIM_DESC sd;
183      SIM_ADDR addr;
184 {
185   struct sim_breakpoint *bp, *bpprev;
186
187   for (bp = STATE_BREAKPOINTS (sd), bpprev = NULL;
188        bp;
189        bpprev = bp, bp = bp->next)
190     if (bp->addr == addr)
191       break;
192
193   if (!bp)
194     return SIM_RC_UNKNOWN_BREAKPOINT;
195
196   remove_breakpoint (sd, bp);
197
198   if (bpprev)
199     bpprev->next = bp->next;
200   else
201     STATE_BREAKPOINTS (sd) = NULL;
202
203   zfree (bp);
204
205   return SIM_RC_OK;
206 }
207
208 SIM_RC
209 sim_clear_all_breakpoints (sd)
210      SIM_DESC sd;
211 {
212   while (STATE_BREAKPOINTS (sd))
213     sim_clear_breakpoint (sd, STATE_BREAKPOINTS (sd)->addr);
214
215   return SIM_RC_OK;
216 }
217
218 SIM_RC
219 sim_enable_breakpoint (sd, addr)
220      SIM_DESC sd;
221      SIM_ADDR addr;
222 {
223   struct sim_breakpoint *bp;
224
225   for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
226     if (bp->addr == addr)
227       break;
228
229   if (!bp)
230     return SIM_RC_UNKNOWN_BREAKPOINT;
231
232   bp->flags &= ~SIM_BREAK_DISABLED;
233
234   return SIM_RC_OK;
235 }
236
237 SIM_RC
238 sim_disable_breakpoint (sd, addr)
239      SIM_DESC sd;
240      SIM_ADDR addr;
241 {
242   struct sim_breakpoint *bp;
243
244   for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
245     if (bp->addr == addr)
246       break;
247
248   if (!bp)
249     return SIM_RC_UNKNOWN_BREAKPOINT;
250
251   bp->flags |= SIM_BREAK_DISABLED;
252
253   return SIM_RC_OK;
254 }
255
256 SIM_RC
257 sim_enable_all_breakpoints (sd)
258      SIM_DESC sd;
259 {
260   struct sim_breakpoint *bp;
261
262   for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
263     bp->flags &= ~SIM_BREAK_DISABLED;
264
265   return SIM_RC_OK;
266 }
267
268 SIM_RC
269 sim_disable_all_breakpoints (sd)
270      SIM_DESC sd;
271 {
272   struct sim_breakpoint *bp;
273
274   for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
275     bp->flags |= SIM_BREAK_DISABLED;
276
277   return SIM_RC_OK;
278 }