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