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