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