ddd fixes
[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 = -1; /* 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 /*-----------------------------------------------------------------*/
49 /* waitForSim - wait till simulator is done its job                */
50 /*-----------------------------------------------------------------*/
51 void waitForSim(int timeout_ms, char *expect)
52 {
53   int i=0;
54   int ch;
55
56 Dprintf(D_simi, ("simi: waitForSim start(%d)\n", timeout_ms));
57     sbp = simibuff;
58
59     while ((ch = fgetc(simin)) > 0 ) {
60       *sbp++ = ch;
61     }
62     *sbp = 0;
63     Dprintf(D_simi, ("waitForSim(%d) got[%s]\n", timeout_ms, simibuff));
64
65 }
66
67 /*-----------------------------------------------------------------*/
68 /* openSimulator - create a pipe to talk to simulator              */
69 /*-----------------------------------------------------------------*/
70 void openSimulator (char **args, int nargs)
71 {
72     struct sockaddr_in sin;     
73     int retry = 0;
74     int i ;
75  Dprintf(D_simi, ("simi: openSimulator\n"));
76
77     /* fork and start the simulator as a subprocess */
78     if ((simPid = fork())) {
79       Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
80     }
81     else {
82       /* we are in the child process : start the simulator */
83       signal(SIGHUP , SIG_IGN );
84       signal(SIGINT , SIG_IGN );
85       signal(SIGABRT, SIG_IGN );
86       signal(SIGCHLD, SIG_IGN );
87
88       if (execvp(args[0],args) < 0) {
89         perror("cannot exec simulator");
90         exit(1);
91       }
92     }
93     
94  try_connect:
95     sock = socket(AF_INET,SOCK_STREAM,0);
96     
97     memset(&sin,0,sizeof(sin));
98     sin.sin_family = AF_INET;
99     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
100     sin.sin_port = htons(9756);
101     
102     sleep(1);
103     /* connect to the simulator */
104     if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0) {
105         /* if failed then wait 1 second & try again
106            do this for 10 secs only */
107         if (retry < 10) {
108             retry ++;
109             sleep (1);
110             goto try_connect;
111         }
112         perror("connect failed :");
113         exit(1);
114     }
115     /* go the socket now turn it into a file handle */
116     if (!(simin = fdopen(sock,"r"))) {
117         fprintf(stderr,"cannot open socket for read\n");
118         exit(1);
119     }
120
121     if (!(simout = fdopen(sock,"w"))) {
122         fprintf(stderr,"cannot open socket for write\n");
123         exit(1);
124     }
125
126     /* now that we have opened, wait for the prompt */
127     waitForSim(200,NULL);
128     simactive = 1;
129 }
130 /*-----------------------------------------------------------------*/
131 /* simResponse - returns buffer to simulator's response            */
132 /*-----------------------------------------------------------------*/
133 char *simResponse()
134 {
135     return simibuff;
136 }
137
138 /*-----------------------------------------------------------------*/
139 /* sendSim - sends a command to the simuator                 */
140 /*-----------------------------------------------------------------*/
141 void sendSim(char *s)
142 {
143     if ( ! simout ) 
144         return;
145
146     Dprintf(D_simi, ("simi: sendSim-->%s", s));  // s has LF at end already
147     fputs(s,simout);
148     fflush(simout);
149 }
150
151 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
152 {
153     char buffer[40], *s,*prefix;
154     int i;
155     switch (mem) 
156     {
157         case 'A':
158             prefix = "x";
159             break;
160         case 'B':       
161             prefix = "i";
162             break;
163         case 'C':
164         case 'D':
165             prefix = "c";
166             break;
167         case 'E':
168         case 'G':
169             prefix = "i";
170             break;
171         case 'F':
172             prefix = "x";
173             break;
174         case 'H':
175             prefix = "bit" ;
176             break;
177         case 'I':
178             prefix = "sfr" ;
179             break;
180         case 'J':
181             prefix = "sbit" ;
182             break;
183         case 'R':
184             return; /* set registers !! */
185             //prefix = "i" ;
186             break;
187         default:
188             return;
189     }
190     sprintf(buffer,"set mem %s 0x%x",prefix,addr);
191     s = buffer + strlen(buffer);
192     for ( i = 0 ; i < size ; i++ )
193     {
194         sprintf(s," 0x%x", val & 0xff);
195         s += strlen(s);
196         val >>= 8;
197     }
198     sprintf(s,"\n");
199     sendSim(buffer);
200     waitForSim(100,NULL);
201     simResponse();   
202 }
203
204 /*-----------------------------------------------------------------*/
205 /* simGetValue - get value @ address for mem space                 */
206 /*-----------------------------------------------------------------*/
207 unsigned long simGetValue (unsigned int addr,char mem, int size)
208 {
209     unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
210     char i;
211     char *prefix;
212     char buffer[20];
213     char *resp;
214
215     switch (mem) {
216     case 'A':
217       prefix = "dx";
218       break;
219     case 'B':       
220       prefix = "di";
221       break;
222     case 'C':
223     case 'D':
224     prefix = "dch";
225         break;
226     case 'E':
227     case 'G':
228         prefix = "di";
229         break;
230     case 'F':
231         prefix = "dx";
232         break;
233     case 'H':
234     case 'J':
235 //      prefix = "db" ;
236         prefix = "dump" ;
237         break;
238     case 'I':
239         prefix = "ds" ;
240         break;
241     case 'R':
242         prefix = "i r" ;
243         break;
244     default:
245         prefix = "dump" ;
246         break;
247     }
248     
249     /* create the simulator command */
250     sprintf(buffer,"%s 0x%x \n",prefix,addr);
251     sendSim(buffer);
252     waitForSim(100,NULL);
253     resp = simResponse();
254
255     /* got the response we need to parse it the response
256        is of the form 
257        [address] [v] [v] [v] ... special case in
258        case of bit variables which case it becomes
259        [address] [assembler bit address] [v] */
260     /* first skip thru white space */
261     while (isspace(*resp)) resp++ ;
262
263     if (strncmp(resp, "0x",2) == 0)
264       resp += 2;
265
266     /* then make the branch for bit variables */
267     /* skip thru the address part */
268     while (isxdigit(*resp)) resp++;
269
270     if (!strcmp(prefix,"i r")) 
271     {
272         /* skip registers */
273         for (i = 0 ; i < addr ; i++ ) 
274         {
275             while (isspace(*resp)) resp++ ;
276             /* skip */
277             while (isxdigit(*resp)) resp++;
278         }
279         }
280     
281     if (!strcmp(prefix,"dump")) {
282
283         /* skip white space */
284         while (isspace(*resp)) resp++ ;
285     
286         /* skip thru the assembler bit address */
287         while (!isspace(*resp)) resp++;
288
289         /* white space */
290         while (isspace(*resp)) resp++ ;
291
292         /* scan in the value */
293         sscanf(resp,"%d",&b[0]);
294     } else {
295         
296         for (i = 0 ; i < size ; i++ ) {
297             /* skip white space */
298             while (isspace(*resp)) resp++ ;
299             
300             sscanf(resp,"%x",&b[i]);
301             
302             /* skip */
303             while (isxdigit(*resp)) resp++;
304         }
305     }
306
307     return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
308         
309 }
310
311 /*-----------------------------------------------------------------*/
312 /* simSetBP - set break point for a given address                  */
313 /*-----------------------------------------------------------------*/
314 void simSetBP (unsigned int addr)
315 {
316     char buff[50];
317
318     sprintf(buff,"break 0x%x\n",addr);
319     sendSim(buff);
320     waitForSim(100,NULL);
321 }
322
323 /*-----------------------------------------------------------------*/
324 /* simClearBP - clear a break point                                */
325 /*-----------------------------------------------------------------*/
326 void simClearBP (unsigned int addr)
327 {
328     char buff[50];
329
330     sprintf(buff,"clear 0x%x\n",addr);
331     sendSim(buff);
332     waitForSim(100,NULL);
333 }
334
335 /*-----------------------------------------------------------------*/
336 /* simLoadFile - load the simulator file                           */
337 /*-----------------------------------------------------------------*/
338 void simLoadFile (char *s)
339 {
340     char buff[128];
341
342     sprintf(buff,"l \"%s\"\n",s);
343     printf(buff);
344     sendSim(buff);
345     waitForSim(500,NULL);
346 }
347
348 /*-----------------------------------------------------------------*/
349 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
350 /*-----------------------------------------------------------------*/
351 unsigned int simGoTillBp ( unsigned int gaddr)
352 {
353     char *sr, *svr;
354     unsigned addr ; 
355     char *sfmt;
356     int wait_ms = 1000;
357
358     if (gaddr == 0) {
359       /* initial start, start & stop from address 0 */
360       char buf[20];
361
362          // this program is setting up a bunch of breakpoints automatically
363          // at key places.  Like at startup & main() and other function
364          // entry points.  So we don't need to setup one here..
365       //sendSim("break 0x0\n");
366       //sleep(1);
367       //waitForSim();
368
369       sendSim("run 0x0\n");
370     } else      if (gaddr == -1) { /* resume */
371       sendSim ("run\n");
372       wait_ms = 100;
373     }
374     else {
375       printf("Error, simGoTillBp > 0!\n");
376       exit(1);
377     }
378
379     waitForSim(wait_ms, NULL);
380     
381     /* get the simulator response */
382     svr  = sr = strdup(simResponse());
383
384     /* figure out the address of the break point the simulators 
385        response in a break point situation is of the form 
386        [... F* <addr> <disassembled instruction> ] 
387        we will ignore till we get F* then parse the address */
388     while (*sr) {
389       if (strncmp(sr,"Stop at",7) == 0) {
390           sr += 7;
391           sfmt = "%x";
392           break;
393       } 
394
395       if (*sr == 'F' && ( *(sr+1) == '*' || *(sr+1) == ' ')) {
396           sr += 2;
397           sfmt = "%x";
398           break;
399       }
400       sr++;
401     }
402
403     if (!*sr) {
404       fprintf(stderr, "Error?, simGoTillBp failed to Stop\n");
405       return 0;
406     }
407
408     while (isspace(*sr)) sr++ ;
409
410     if (sscanf(sr,sfmt,&addr) != 1) {
411       fprintf(stderr, "Error?, simGoTillBp failed to get Addr\n");
412       return 0;
413     }
414         return addr;
415
416 }
417
418 /*-----------------------------------------------------------------*/
419 /* simReset - reset the simulator                                  */
420 /*-----------------------------------------------------------------*/
421 void simReset ()
422 {
423     sendSim("res\n");
424     waitForSim(100,NULL);
425 }
426
427 /*-----------------------------------------------------------------*/
428 /* getValueStr - read a value followed by a string =               */
429 /*-----------------------------------------------------------------*/
430 static unsigned int getValueStr (char *src,char *cstr)
431 {
432     int i = strlen(cstr);
433     int rv;
434     /* look for the string */
435     if (! (src = strstr(src,cstr)))
436         return 0;
437
438     src += i;
439     if (!*src) return 0;
440
441     /* look for the digit */
442     while (*src && !isxdigit(*src)) src++;
443     sscanf(src,"%x",&rv);
444     return rv;
445 }
446
447 /*-----------------------------------------------------------------*/
448 /* simRegs - returns value of registers                            */
449 /*-----------------------------------------------------------------*/
450 char  *simRegs()
451 {   
452     char *resp ;
453     unsigned int rv;
454     char *rb = regBuff;
455     int i;
456
457     sendSim("info registers\n");
458
459     waitForSim(100,NULL);
460          
461     resp  = simResponse();
462
463 #if 0
464     return resp;
465
466 #else
467     /*Take this out(2-09-02) cant see as its that useful to reformat, karl.*/
468   
469     /* the response is of the form 
470        XXXXXX R0 R1 R2 R3 R4 R5 R6 R7 ........
471        XXXXXX XX . ACC=0xxx dd cc B=0xxx dd cc DPTR= 0xxxxx @DPTR= 0xxx dd cc
472        XXXXXX XX . PSW= 0xxx CY=[1|0] AC=[0|1] OV=[0|1] P=[1|0]
473
474 Format as of 8-4-01:
475        0x00 00 00 00 00 00 00 00 00 ........
476        000000 00 .  ACC= 0x00   0 .  B= 0x00   DPTR= 0x0000 @DPTR= 0x00   0 .
477        000000 00 .  PSW= 0x00 CY=0 AC=0 OV=0 P=0
478 F  0x006d 75 87 80 MOV   PCON,#80
479 */
480
481     memset(regBuff,0,sizeof(regBuff));
482     /* skip the first numerics */
483     while (*resp && !isxdigit(*resp)) resp++;
484
485     if (strncmp(resp, "0x", 2)) {
486       fprintf(stderr, "Error: Format1A\n");
487       return regBuff;
488     }
489     resp += 2;
490     while (*resp && isxdigit(*resp)) resp++;
491
492     /* now get the eight registers */
493     for (i = 0 ; i < 7 ; i++) {
494         while (*resp && isspace(*resp)) resp++;
495         if (!*resp)
496             break;
497         rv = strtol(resp,&resp,16);
498         sprintf(rb,"R%d  : 0x%02X %d %c\n",i,rv,rv,(isprint(rv) ? rv : '.'));
499         rb += strlen(rb);
500     }
501
502     if (!*resp) return regBuff;
503
504     /* skip till end of line */
505     while (*resp && *resp != '\n') resp++;
506     while (*resp && !isxdigit(*resp)) resp++;
507     while (*resp && isxdigit(*resp)) resp++;
508     
509     /* accumulator value */
510     rv = getValueStr(resp,"ACC");
511     sprintf(rb,"ACC : 0x%02X %d %c\n",rv,rv,(isprint(rv) ? rv : '.'));
512     rb += strlen(rb);
513     
514     /* value of B */
515     rv = getValueStr(resp,"B=");
516     sprintf(rb,"B   : 0x%02X %d %c\n",rv,rv,(isprint(rv) ? rv : '.'));
517     rb += strlen(rb);
518
519     rv = getValueStr(resp,"DPTR=");
520     sprintf(rb,"DPTR: 0x%04X %d\n",rv,rv);
521     rb += strlen(rb);
522
523     rv = getValueStr(resp,"@DPTR=");
524     sprintf(rb,"@DPTR: 0x%02X %d %c\n", rv,rv,(isprint(rv) ? rv : '.'));
525     rb += strlen(rb);
526     
527     sprintf(rb,"PSW  : 0x%02X | CY : %d | AC : %d | OV : %d | P : %d\n",
528             getValueStr(resp,"PSW="),
529             getValueStr(resp,"CY="),
530             getValueStr(resp,"AC="),
531             getValueStr(resp,"OV="),
532             getValueStr(resp,"P="));
533
534     return regBuff;
535 #endif
536
537 }
538
539 /*-----------------------------------------------------------------*/
540 /* closeSimulator - close connection to simulator                  */
541 /*-----------------------------------------------------------------*/
542 void closeSimulator ()
543 {
544     if ( ! simin || ! simout || sock == -1 )
545     {
546         simactive = 0;
547         return;
548     }
549     sendSim("q\n");
550     kill (simPid,SIGKILL);
551     fclose (simin);
552     fclose (simout);
553     shutdown(sock,2);   
554     close(sock);    
555     sock = -1;
556 }
557
558