Changed a few Makefiles & Fixed 3 bugs.
[fw/sdcc] / debugger / mcs51 / break.c
1 /*-------------------------------------------------------------------------
2   break.c - Source file for break point management
3         Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
4
5    This program is free software; you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by the
7    Free Software Foundation; either version 2, or (at your option) any
8    later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19    In other words, you are welcome to use, share and improve this program.
20    You are forbidden to forbid anyone else to use, share and improve
21    what you give them.   Help stamp out software-hoarding!
22 -------------------------------------------------------------------------*/
23
24 #include "sdcdb.h"
25 #include "symtab.h"
26 #include "break.h"
27
28 static hTab *bptable = NULL;
29 char userBpPresent = 0;
30 /* call stack can be 1024 deep */
31 STACK_DCL(callStack,function *,1024);
32
33 /*-----------------------------------------------------------------*/
34 /* setBreakPoint - creates an entry in the break point table       */
35 /*-----------------------------------------------------------------*/
36 int setBreakPoint (unsigned addr, char addrType, char bpType,
37         int (*callBack)(unsigned,char,char,int,context *) ,
38         char *fileName, int lineno)
39 {
40     breakp *bp, *bpl;
41     static long bpnum = 0;
42     char simbuf[50];
43
44     /* allocate & init a new bp */
45     Safe_calloc(1,bp,sizeof(breakp));
46     bp->addr = addr;
47     bp->addrType = addrType;
48     bp->bpType = bpType;
49     bp->callBack = callBack;
50     bp->bpnum = (bpType == USER ? ++bpnum : 0);
51     bp->filename = fileName;
52     bp->lineno = lineno;
53
54     /* if this is an user break point then
55        check if there already exists one for this address */
56     if (bpType == USER) {
57   for ( bpl = hTabFirstItemWK(bptable,addr) ; bpl;
58         bpl = hTabNextItemWK(bptable)) {
59
60       /* if also a user break point then issue Note : */
61       if (bpl->bpType == USER)
62     fprintf(stderr,"Note: breakpoint %d also set at pc 0x%x\n",
63       bpl->bpnum,bpl->addr);
64   }
65
66   fprintf(stderr,"Breakpoint %d at 0x%x: file %s, line %d.\n",
67     bp->bpnum, addr, fileName, lineno);
68
69   userBpPresent++;
70     }
71
72     /* if a break point does not already exist then
73        send command to simulator to add one */
74     if (!hTabSearch(bptable,addr))
75   /* send the break command to the simulator */
76   simSetBP (addr);
77
78
79     /* now add the break point to list */
80     hTabAddItem(&bptable,addr,bp);
81
82     return bp->bpnum ;
83 }
84
85 /*-----------------------------------------------------------------*/
86 /* deleteSTEPbp - deletes all step break points                    */
87 /*-----------------------------------------------------------------*/
88 void deleteSTEPbp ()
89 {
90     breakp *bp;
91     int k;
92
93     /* for break points delete if they are STEP */
94     for ( bp = hTabFirstItem(bptable,&k); bp ;
95     bp = hTabNextItem(bptable,&k)) {
96
97   /* if this is a step then delete */
98   if (bp->bpType == STEP) {
99       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
100
101       /* if this leaves no other break points then
102          send command to simulator to delete bp from this addr */
103       if (hTabSearch(bptable,bp->addr) == NULL)
104     simClearBP (bp->addr);
105
106       free(bp);
107   }
108     }
109
110 }
111
112 /*-----------------------------------------------------------------*/
113 /* deleteNEXTbp - deletes all step break points                    */
114 /*-----------------------------------------------------------------*/
115 void deleteNEXTbp ()
116 {
117     breakp *bp;
118     int k;
119     char simcmd[50];
120
121     /* for break points delete if they are NEXT */
122     for ( bp = hTabFirstItem(bptable,&k); bp ;
123     bp = hTabNextItem(bptable,&k)) {
124
125   /* if this is a step then delete */
126   if (bp->bpType == NEXT) {
127       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
128
129       /* if this leaves no other break points then
130          send command to simulator to delete bp from this addr */
131       if (hTabSearch(bptable,bp->addr) == NULL) {
132     simClearBP(bp->addr);
133
134       }
135
136       free(bp);
137   }
138     }
139
140 }
141
142 /*-----------------------------------------------------------------*/
143 /* deleteUSERbp - deletes USER break point with number             */
144 /*-----------------------------------------------------------------*/
145 void deleteUSERbp (int bpnum)
146 {
147     breakp *bp;
148     int k;
149     char simcmd[50];
150
151     /* for break points delete if they are STEP */
152     for ( bp = hTabFirstItem(bptable,&k); bp ;
153     bp = hTabNextItem(bptable,&k)) {
154
155   /* if this is a user then delete if break
156      point matches or bpnumber == -1 (meaning delete
157      all user break points */
158   if (bp->bpType == USER && ( bp->bpnum == bpnum || bpnum == -1)) {
159       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
160
161       /* if this leaves no other break points then
162          send command to simulator to delete bp from this addr */
163       if (hTabSearch(bptable,bp->addr) == NULL) {
164     simClearBP (bp->addr);
165
166       }
167       fprintf(stdout,"Deleted breakpoint %d\n",
168         bp->bpnum);
169       userBpPresent --;
170       if (bpnum == -1)
171     continue ;
172       else
173     break;
174   }
175     }
176
177     if (!bp && bpnum != -1)
178   fprintf(stderr,"No breakpoint number %d.\n",bpnum);
179 }
180
181 /*-----------------------------------------------------------------*/
182 /* listUSERbp - list all user break points                         */
183 /*-----------------------------------------------------------------*/
184 void listUSERbp ()
185 {
186     breakp *bp;
187     int k;
188
189     /* if there are none then say so & return */
190     if (!userBpPresent) {
191   fprintf(stdout,"No breakpoints.\n");
192   return ;
193     }
194     fprintf(stdout,"Num Address What\n");
195     for ( bp = hTabFirstItem(bptable,&k) ; bp ;
196     bp = hTabNextItem(bptable,&k)) {
197
198   if (bp->bpType == USER ) {
199       fprintf(stdout,"%-3d 0x%04x  at %s:%d\n",
200         bp->bpnum,bp->addr,
201         bp->filename,bp->lineno);
202
203   }
204     }
205 }
206
207 /*-----------------------------------------------------------------*/
208 /* simStopBPCB - simulator stopped break point                     */
209 /*-----------------------------------------------------------------*/
210 static int simStopBPCB( unsigned int addr)
211 {
212   fprintf(stdout,"Simulator stopped at Address 0x%04x\n",addr);
213   fprintf(stdout,"%s",simResponse());
214   return 1;
215 }
216
217 /*-----------------------------------------------------------------*/
218 /* clearUSERbp - deletes USER break point at address               */
219 /*-----------------------------------------------------------------*/
220 void clearUSERbp ( unsigned int addr )
221 {
222     breakp *bp;
223     char simcmd[50];
224
225     /* for break points delete if they are STEP */
226     for ( bp = hTabFirstItemWK(bptable,addr); bp ;
227     bp = hTabNextItemWK(bptable)) {
228
229   /* if this is a step then delete */
230   if (bp->bpType == USER) {
231       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
232
233       /* if this leaves no other break points then
234          send command to simulator to delete bp from this addr */
235       if (hTabSearch(bptable,bp->addr) == NULL) {
236     simClearBP(bp->addr);
237
238       }
239       fprintf(stdout,"Deleted breakpoint %d\n",
240         bp->bpnum);
241       userBpPresent-- ;
242       break;
243   }
244     }
245
246     if (!bp)
247   fprintf(stderr,"No breakpoint at address 0x%x.\n",addr);
248 }
249
250 /*-----------------------------------------------------------------*/
251 /* dispatchCB - will lookup the bp table and dispatch the cb funcs */
252 /*-----------------------------------------------------------------*/
253 int dispatchCB (unsigned addr, context *ctxt)
254 {
255     breakp *bp;
256     int rv =0;
257
258     /* if no break points set for this address
259        then use a simulator stop break point */
260     if ((bp = hTabFirstItemWK(bptable,addr)) == NULL) {
261       return simStopBPCB(addr);
262     }
263
264     /* dispatch the call back functions */
265     for (; bp; bp = hTabNextItemWK(bptable)) {
266
267       rv += (*bp->callBack)(addr,bp->addrType,
268           bp->bpType,bp->bpnum,ctxt);
269
270     }
271
272     return rv;
273 }
274
275 /*-----------------------------------------------------------------*/
276 /* fentryCB - callback function for function entry                 */
277 /*-----------------------------------------------------------------*/
278 BP_CALLBACK(fentryCB)
279 {
280     /* add the current function into the call stack */
281     STACK_PUSH(callStack,ctxt->func);
282
283     /* will have to add code here to get the value of SP
284        which will be used to display the value of local variables
285        and parameters on the stack */
286
287     return 0;
288 }
289
290 /*-----------------------------------------------------------------*/
291 /* fexitCB - call back for function exit                           */
292 /*-----------------------------------------------------------------*/
293 BP_CALLBACK(fexitCB)
294 {
295     /* pop the top most from the call stack */
296     STACK_POP(callStack);
297     return 0;
298 }
299 /*-----------------------------------------------------------------*/
300 /* userBpCB - call back function for user break points             */
301 /*-----------------------------------------------------------------*/
302 BP_CALLBACK(userBpCB)
303 {
304     if (srcMode == SRC_CMODE) {
305   fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
306     bpnum,
307     ctxt->func->sym->name,
308     ctxt->func->mod->c_name,
309     ctxt->cline);
310   if (ctxt->func->mod && ctxt->cline > 0)
311       fprintf(stdout,"%d\t%s",ctxt->cline,
312         ctxt->func->mod->cLines[ctxt->cline]->src);
313     } else {
314   fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
315     bpnum,
316     ctxt->func->sym->name,
317     ctxt->func->mod->asm_name,
318     ctxt->asmline);
319   if (ctxt->func->mod && ctxt->asmline > 0)
320       fprintf(stdout,"%d\t%s",ctxt->asmline,
321         ctxt->func->mod->asmLines[ctxt->asmline]->src);
322     }
323
324     return 1;
325 }
326
327 /*-----------------------------------------------------------------*/
328 /* stepBpCB - call back function for step break points             */
329 /*-----------------------------------------------------------------*/
330 BP_CALLBACK(stepBpCB)
331 {
332     static function *lfunc = NULL;
333
334     if (srcMode == SRC_CMODE) {
335   if ((lfunc && lfunc != ctxt->func) || !lfunc)
336       fprintf(stdout,"%s () at %s:%d\n",
337         ctxt->func->sym->name,
338         ctxt->func->mod->c_name,
339         ctxt->cline);
340
341   if (ctxt->func->mod && ctxt->cline > 0) {
342       fprintf(stdout,"%d\t%s",ctxt->cline ,
343         ctxt->func->mod->cLines[ctxt->cline]->src);
344   }
345     } else {
346   if ((lfunc && lfunc != ctxt->func) || !lfunc)
347       fprintf(stdout,"%s () at %s:%d\n",
348         ctxt->func->sym->name,
349         ctxt->func->mod->asm_name,
350         ctxt->asmline);
351
352   if (ctxt->func->mod && ctxt->cline > 0) {
353       fprintf(stdout,"%d\t%s",ctxt->asmline ,
354         ctxt->func->mod->asmLines[ctxt->asmline]->src);
355   }
356     }
357     lfunc = ctxt->func;
358
359     deleteSTEPbp();
360     return 1;
361 }
362
363 /*-----------------------------------------------------------------*/
364 /* nextBpCB - call back function for next break points             */
365 /*-----------------------------------------------------------------*/
366 BP_CALLBACK(nextBpCB)
367 {
368     static function *lfunc = NULL;
369
370     if (srcMode == SRC_CMODE) {
371   if ((lfunc && lfunc != ctxt->func) || !lfunc)
372       fprintf(stdout,"%s () at %s:%d\n",
373         ctxt->func->sym->name,
374         ctxt->func->mod->c_name,
375         ctxt->cline);
376
377   if (ctxt->func->mod && ctxt->cline > 0)
378       fprintf(stdout,"%d\t%s",ctxt->cline,
379         ctxt->func->mod->cLines[ctxt->cline]->src);
380     } else {
381   if ((lfunc && lfunc != ctxt->func) || !lfunc)
382       fprintf(stdout,"%s () at %s:%d\n",
383         ctxt->func->sym->name,
384         ctxt->func->mod->asm_name,
385         ctxt->asmline);
386
387   if (ctxt->func->mod && ctxt->asmline > 0)
388       fprintf(stdout,"%d\t%s",ctxt->asmline,
389         ctxt->func->mod->asmLines[ctxt->asmline]->src);
390
391     }
392     lfunc = ctxt->func;
393
394     deleteNEXTbp();
395     return 1;
396 }