Get debugger working
[fw/sdcc] / debugger / mcs51 / simi.c
1 /*-------------------------------------------------------------------------
2   simi.c - source file for simulator interaction
3
4               Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19    
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!  
23 -------------------------------------------------------------------------*/
24 #include "sdcdb.h"
25 #include "simi.h"
26
27 #ifdef HAVE_SYS_SOCKET_H
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <unistd.h>
33 #include <signal.h>
34 #else
35 #error "Cannot build debugger without socket support"
36 #endif
37 FILE *simin ; /* stream for simulator input */
38 FILE *simout; /* stream for simulator output */
39
40 int sock ; /* socket descriptor to comm with simulator */
41 pid_t simPid;
42 static char simibuff[MAX_SIM_BUFF];    /* sim buffer       */
43 static char regBuff[MAX_SIM_BUFF];
44 static char *sbp = simibuff;           /* simulator buffer pointer */
45 extern char **environ;
46 char simactive = 0;
47 /*-----------------------------------------------------------------*/
48 /* readSim - reads one character into simulator buffer             */
49 /*-----------------------------------------------------------------*/
50 void readSim(int resetp)
51 {
52     int ch ;
53     /* if reset required then point to beginning of buffer */
54     if (resetp)
55         sbp = simibuff;
56     
57     Dprintf(D_simi, ("readSim: reading from sim["));
58
59     while ((ch = fgetc(simin))) {
60
61 #ifdef SDCDB_DEBUG      
62  if (D_simi) {
63         fputc(ch,stdout);
64  }
65 #endif
66
67         *sbp++ = ch;    
68     }
69
70     Dprintf(D_simi, ("] end readSim\n"));
71
72     *sbp = '\0';
73 }
74
75 /*-----------------------------------------------------------------*/
76 /* waitForSim - wait till simulator is done its job                */
77 /*-----------------------------------------------------------------*/
78 void waitForSim()
79 {
80     readSim(TRUE);
81 }
82
83 /*-----------------------------------------------------------------*/
84 /* openSimulator - create a pipe to talk to simulator              */
85 /*-----------------------------------------------------------------*/
86 void openSimulator (char **args, int nargs)
87 {
88     struct sockaddr_in sin;     
89     int retry = 0;
90     int i ;
91     char *simargs[32] = { "s51","-P","-r 9756", NULL };
92     
93     /* create the arguments */
94     for ( i = 0 ; i < nargs ;i++) {
95         simargs[i+3] = args[i];       
96     }
97     simargs[i+3]= NULL;
98
99     /* fork and start the simulator as a subprocess */
100     if ((simPid = fork())) {
101       Dprintf(D_simi, ("simulator pid %d\n",(int) simPid));
102     }
103     else {
104         
105         /* we are in the child process : start the simulator */
106         if (execvp("s51",simargs) < 0) {
107             perror("cannot exec simulator");
108             exit(1);
109         }       
110     }
111     
112  try_connect:
113     sock = socket(AF_INET,SOCK_STREAM,0);
114     
115     memset(&sin,0,sizeof(sin));
116     sin.sin_family = AF_INET;
117     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
118     sin.sin_port = htons(9756);
119     
120     sleep(1);
121     /* connect to the simulator */
122     if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0) {
123         /* if failed then wait 1 second & try again
124            do this for 10 secs only */
125         if (retry < 10) {
126             retry ++;
127             sleep (1);
128             goto try_connect;
129         }
130         perror("connect failed :");
131         exit(1);
132     }
133     /* go the socket now turn it into a file handle */
134     if (!(simin = fdopen(sock,"r"))) {
135         fprintf(stderr,"cannot open socket for read\n");
136         exit(1);
137     }
138
139     if (!(simout = fdopen(sock,"w"))) {
140         fprintf(stderr,"cannot open socket for write\n");
141         exit(1);
142     }
143
144     /* now that we have opend wait for the prompt */
145     waitForSim();
146     simactive = 1;
147 }
148 /*-----------------------------------------------------------------*/
149 /* simResponse - returns buffer to simulator's response            */
150 /*-----------------------------------------------------------------*/
151 char *simResponse()
152 {
153     return simibuff;
154 }
155
156 /*-----------------------------------------------------------------*/
157 /* sendSim - sends a command to the simuator                 */
158 /*-----------------------------------------------------------------*/
159 void sendSim(char *s)
160 {
161     Dprintf(D_simi, ("sendSim-->%s", s));  // s has LF at end already
162     fputs(s,simout);
163     fflush(simout);
164 }
165
166 /*-----------------------------------------------------------------*/
167 /* simGetValue - get value @ address for mem space                 */
168 /*-----------------------------------------------------------------*/
169 unsigned long simGetValue (unsigned int addr,char mem, int size)
170 {
171     unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
172     char i;
173     char *prefix;
174     char buffer[20];
175     char *resp;
176
177     switch (mem) {
178     case 'A':
179       prefix = "dx";
180       break;
181     case 'B':       
182       prefix = "di";
183       break;
184     case 'C':
185     case 'D':
186         prefix = "dch";
187         break;
188     case 'E':
189     case 'G':
190         prefix = "di";
191         break;
192     case 'F':
193         prefix = "dx";
194         break;
195     case 'H':
196     case 'J':
197         prefix = "db" ;
198         break;
199     case 'I':
200         prefix = "ds" ;
201         break;  
202     }
203     
204     /* create the simulator command */
205     sprintf(buffer,"%s 0x%x \n",prefix,addr);
206     sendSim(buffer);
207     waitForSim();
208     resp = simResponse();
209
210     /* got the response we need to parse it the response
211        is of the form 
212        [address] [v] [v] [v] ... special case in
213        case of bit variables which case it becomes
214        [address] [assembler bit address] [v] */
215     /* first skip thru white space */
216     while (isspace(*resp)) resp++ ;
217
218     /* then make the branch for bit variables */
219     /* skip thru the address part */
220     while (isxdigit(*resp)) resp++;
221     
222     if (!strcmp(prefix,"db")) {
223
224         /* skip white space */
225         while (isspace(*resp)) resp++ ;
226     
227         /* skip thru the assembler bit address */
228         while (!isspace(*resp)) resp++;
229
230         /* white space */
231         while (isspace(*resp)) resp++ ;
232
233         /* scan in the value */
234         sscanf(resp,"%d",&b[0]);
235     } else {
236         
237         for (i = 0 ; i < size ; i++ ) {
238             /* skip white space */
239             while (isspace(*resp)) resp++ ;
240             
241             sscanf(resp,"%x",&b[i]);
242             
243             /* skip */
244             while (isxdigit(*resp)) resp++;
245         }
246     }
247
248     return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
249         
250 }
251
252 /*-----------------------------------------------------------------*/
253 /* simSetBP - set break point for a given address                  */
254 /*-----------------------------------------------------------------*/
255 void simSetBP (unsigned int addr)
256 {
257     char buff[50];
258
259     sprintf(buff,"break 0x%x\n",addr);
260     sendSim(buff);
261     waitForSim();
262 }
263
264 /*-----------------------------------------------------------------*/
265 /* simClearBP - clear a break point                                */
266 /*-----------------------------------------------------------------*/
267 void simClearBP (unsigned int addr)
268 {
269     char buff[50];
270
271     sprintf(buff,"clear 0x%x\n",addr);
272     sendSim(buff);
273     waitForSim();  
274 }
275
276 /*-----------------------------------------------------------------*/
277 /* simLoadFile - load the simulator file                           */
278 /*-----------------------------------------------------------------*/
279 void simLoadFile (char *s)
280 {
281     char buff[128];
282
283     sprintf(buff,"l \"%s\"\n",s);
284     printf(buff);
285     sendSim(buff);
286     waitForSim();    
287 }
288
289 /*-----------------------------------------------------------------*/
290 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
291 /*-----------------------------------------------------------------*/
292 unsigned int simGoTillBp ( unsigned int gaddr)
293 {
294     char *sr, *svr;
295     unsigned addr ; 
296     char *sfmt;
297
298     /* kpb: new code 8-03-01 */
299     if (gaddr == 0) {
300       /* initial start, start & stop from address 0 */
301         char buf[20];
302          // this program is setting up a bunch of breakpoints automatically
303          // at key places.  Like at startup & main() and other function
304          // entry points.  So we don't need to setup one here..
305       //sendSim("break 0x0\n");
306       //sleep(1);
307       //waitForSim();
308
309         sendSim("run 0x0\n");
310       sleep(1);  /* do I need this? */
311     } else      if (gaddr == -1) { /* resume */
312
313       // try adding this(kpb)
314       sendSim("step\n");
315       usleep(100000);
316       waitForSim();
317
318         sendSim ("run\n");
319     }
320     else {
321       printf("Error, simGoTillBp > 0!\n");
322       exit(1);
323     }
324
325 #if 0
326     if (gaddr != -1) {
327         char buf[20];
328         sprintf(buf,"g 0x%x\n",gaddr);
329         sendSim(buf);
330     } else      
331         sendSim ("g\n");
332 #endif
333     
334     waitForSim();
335     
336     /* get the simulator response */
337     svr  = sr = strdup(simResponse());
338
339     /* figure out the address of the break point the simulators 
340        response in a break point situation is of the form 
341        [... F* <addr> <disassembled instruction> ] 
342        we will ignore till we get F* then parse the address */
343     while (*sr) {
344         
345         if (strncmp(sr,"Stop at",7) == 0) {
346             sr += 7;
347             sfmt = "%x";
348             break;
349         } 
350             
351         if (*sr == 'F' && ( *(sr+1) == '*' || *(sr+1) == ' ')) {
352             sr += 2;
353             sfmt = "%x";
354             break;
355         }
356         sr++;
357     }
358
359     if (!*sr) {
360       fprintf(stderr, "Error?, simGoTillBp failed to Stop\n");
361       return 0;
362     }
363
364     while (isspace(*sr)) sr++ ;
365
366     if (sscanf(sr,sfmt,&addr) != 1) {
367       fprintf(stderr, "Error?, simGoTillBp failed to get Addr\n");
368       return 0;
369     }
370         return addr;
371
372 }
373
374 /*-----------------------------------------------------------------*/
375 /* simReset - reset the simulator                                  */
376 /*-----------------------------------------------------------------*/
377 void simReset ()
378 {
379     sendSim("res\n");
380     waitForSim();
381 }
382
383 /*-----------------------------------------------------------------*/
384 /* getValueStr - read a value followed by a string =               */
385 /*-----------------------------------------------------------------*/
386 static unsigned int getValueStr (char *src,char *cstr)
387 {
388     int i = strlen(cstr);
389     int rv;
390     /* look for the string */
391     if (! (src = strstr(src,cstr)))
392         return 0;
393
394     src += i;
395     if (!*src) return 0;
396
397     /* look for the digit */
398     while (*src && !isxdigit(*src)) src++;
399     sscanf(src,"%x",&rv);
400     return rv;
401 }
402
403 /*-----------------------------------------------------------------*/
404 /* simRegs - returns value of registers                            */
405 /*-----------------------------------------------------------------*/
406 char  *simRegs()
407 {   
408     char *resp ;
409     unsigned int rv;
410     char *rb = regBuff;
411     int i;
412
413     sendSim("info registers\n");
414     //kpb(8-5-01) sendSim("dr\n");
415
416     waitForSim();
417     /* make it some more readable */
418     resp  = simResponse();
419
420     /* the response is of the form 
421        XXXXXX R0 R1 R2 R3 R4 R5 R6 R7 ........
422        XXXXXX XX . ACC=0xxx dd cc B=0xxx dd cc DPTR= 0xxxxx @DPTR= 0xxx dd cc
423        XXXXXX XX . PSW= 0xxx CY=[1|0] AC=[0|1] OV=[0|1] P=[1|0]
424
425 Format as of 8-4-01:
426        0x00 00 00 00 00 00 00 00 00 ........
427        000000 00 .  ACC= 0x00   0 .  B= 0x00   DPTR= 0x0000 @DPTR= 0x00   0 .
428        000000 00 .  PSW= 0x00 CY=0 AC=0 OV=0 P=0
429 F  0x006d 75 87 80 MOV   PCON,#80
430 */
431
432     memset(regBuff,0,sizeof(regBuff));
433     /* skip the first numerics */
434     while (*resp && !isxdigit(*resp)) resp++;
435
436     if (strncmp(resp, "0x", 2)) {
437       fprintf(stderr, "Error: Format1A\n");
438       return regBuff;
439     }
440     resp += 2;
441     while (*resp && isxdigit(*resp)) resp++;
442
443     /* now get the eight registers */
444     for (i = 0 ; i < 7 ; i++) {
445         while (*resp && isspace(*resp)) resp++;
446         if (!*resp)
447             break;
448         rv = strtol(resp,&resp,16);
449         sprintf(rb,"R%d  : 0x%02X %d %c\n",i,rv,rv,(isprint(rv) ? rv : '.'));
450         rb += strlen(rb);
451     }
452
453     if (!*resp) return regBuff;
454
455     /* skip till end of line */
456     while (*resp && *resp != '\n') resp++;
457     while (*resp && !isxdigit(*resp)) resp++;
458     while (*resp && isxdigit(*resp)) resp++;
459     
460     /* accumulator value */
461     rv = getValueStr(resp,"ACC");
462     sprintf(rb,"ACC : 0x%02X %d %c\n",rv,rv,(isprint(rv) ? rv : '.'));
463     rb += strlen(rb);
464     
465     /* value of B */
466     rv = getValueStr(resp,"B=");
467     sprintf(rb,"B   : 0x%02X %d %c\n",rv,rv,(isprint(rv) ? rv : '.'));
468     rb += strlen(rb);
469
470     rv = getValueStr(resp,"DPTR=");
471     sprintf(rb,"DPTR: 0x%04X %d\n",rv,rv);
472     rb += strlen(rb);
473
474     rv = getValueStr(resp,"@DPTR=");
475     sprintf(rb,"@DPTR: 0x%02X %d %c\n", rv,rv,(isprint(rv) ? rv : '.'));
476     rb += strlen(rb);
477     
478     sprintf(rb,"PSW  : 0x%02X | CY : %d | AC : %d | OV : %d | P : %d\n",
479             getValueStr(resp,"PSW="),
480             getValueStr(resp,"CY="),
481             getValueStr(resp,"AC="),
482             getValueStr(resp,"OV="),
483             getValueStr(resp,"P="));
484
485     return regBuff;
486     
487     
488
489 }
490
491 /*-----------------------------------------------------------------*/
492 /* closeSimulator - close connection to simulator                  */
493 /*-----------------------------------------------------------------*/
494 void closeSimulator ()
495 {
496
497     sendSim("q\n");
498     kill (simPid,SIGKILL);
499     fclose (simin);
500     fclose (simout);
501     shutdown(sock,2);   
502     close(sock);    
503     
504 }