Initial revision
[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 #ifdef SDCDB_DEBUG
58     fprintf(stderr,"stderr--> reading from sim\n");
59 #endif
60
61     while ((ch = fgetc(simin))) {
62 #ifdef SDCDB_DEBUG      
63         fputc(ch,stdout);
64 #endif
65         *sbp++ = ch;    
66     }
67 #ifdef SDCDB_DEBUG
68     fprintf(stderr,"stderr--> reading from sim done\n");
69 #endif
70
71     *sbp = '\0';
72 }
73
74 /*-----------------------------------------------------------------*/
75 /* waitForSim - wait till simulator is done its job                */
76 /*-----------------------------------------------------------------*/
77 void waitForSim()
78 {
79     readSim(TRUE);
80 }
81
82 /*-----------------------------------------------------------------*/
83 /* openSimulator - create a pipe to talk to simulator              */
84 /*-----------------------------------------------------------------*/
85 void openSimulator (char **args, int nargs)
86 {
87     struct sockaddr_in sin;     
88     int retry = 0;
89     int i ;
90     char *simargs[32] = { "s51","-P","-r 9756", NULL };
91     
92     /* create the arguments */
93     for ( i = 0 ; i < nargs ;i++) {
94         simargs[i+3] = args[i];       
95     }
96     simargs[i+3]= NULL;
97
98     /* fork and start the simulator as a subprocess */
99     if ((simPid = fork())) {
100 #ifdef SDCDB_DEBUG
101         printf("simulator pid %d\n",(int) simPid);
102 #endif
103     }
104     else {
105         
106         /* we are in the child process : start the simulator */
107         if (execvp("s51",simargs) < 0) {
108             perror("cannot exec simulator");
109             exit(1);
110         }       
111     }
112     
113  try_connect:
114     sock = socket(AF_INET,SOCK_STREAM,0);
115     
116     memset(&sin,0,sizeof(sin));
117     sin.sin_family = AF_INET;
118     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
119     sin.sin_port = htons(9756);
120     
121     sleep(1);
122     /* connect to the simulator */
123     if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0) {
124         /* if failed then wait 1 second & try again
125            do this for 10 secs only */
126         if (retry < 10) {
127             retry ++;
128             sleep (1);
129             goto try_connect;
130         }
131         perror("connect failed :");
132         exit(1);
133     }
134     /* go the socket now turn it into a file handle */
135     if (!(simin = fdopen(sock,"r"))) {
136         fprintf(stderr,"cannot open socket for read\n");
137         exit(1);
138     }
139
140     if (!(simout = fdopen(sock,"w"))) {
141         fprintf(stderr,"cannot open socket for write\n");
142         exit(1);
143     }
144
145     /* now that we have opend wait for the prompt */
146     waitForSim();
147     simactive = 1;
148 }
149 /*-----------------------------------------------------------------*/
150 /* simResponse - returns buffer to simulator's response            */
151 /*-----------------------------------------------------------------*/
152 char *simResponse()
153 {
154     return simibuff;
155 }
156
157 /*-----------------------------------------------------------------*/
158 /* sendSim - sends a command to the simuator                 */
159 /*-----------------------------------------------------------------*/
160 void sendSim(char *s)
161 {
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     if (gaddr != -1) {
299         char buf[20];
300         sprintf(buf,"g 0x%x\n",gaddr);
301         sendSim(buf);
302     } else      
303         sendSim ("g\n");
304     
305     waitForSim();
306     
307     /* get the simulator response */
308     svr  = sr = strdup(simResponse());
309
310     /* figure out the address of the break point the simulators 
311        response in a break point situation is of the form 
312        [... F* <addr> <disassembled instruction> ] 
313        we will ignore till we get F* then parse the address */
314     while (*sr) {
315         
316         if (strncmp(sr,"Stop at",7) == 0) {
317             sr += 7;
318             sfmt = "%x";
319             break;
320         } 
321             
322         if (*sr == 'F' && ( *(sr+1) == '*' || *(sr+1) == ' ')) {
323             sr += 2;
324             sfmt = "%x";
325             break;
326         }
327         sr++;
328     }
329
330     if (!*sr) return 0;
331
332     while (isspace(*sr)) sr++ ;
333
334     if (sscanf(sr,sfmt,&addr) != 1)
335         return 0;
336     else
337         return addr;
338      
339
340 }
341
342 /*-----------------------------------------------------------------*/
343 /* simReset - reset the simulator                                  */
344 /*-----------------------------------------------------------------*/
345 void simReset ()
346 {
347     sendSim("res\n");
348     waitForSim();
349 }
350
351 /*-----------------------------------------------------------------*/
352 /* getValueStr - read a value followed by a string =               */
353 /*-----------------------------------------------------------------*/
354 static unsigned int getValueStr (char *src,char *cstr)
355 {
356     int i = strlen(cstr);
357     int rv;
358     /* look for the string */
359     if (! (src = strstr(src,cstr)))
360         return 0;
361
362     src += i;
363     if (!*src) return 0;
364
365     /* look for the digit */
366     while (*src && !isxdigit(*src)) src++;
367     sscanf(src,"%x",&rv);
368     return rv;
369 }
370
371 /*-----------------------------------------------------------------*/
372 /* simRegs - returns value of registers                            */
373 /*-----------------------------------------------------------------*/
374 char  *simRegs()
375 {   
376     char *resp ;
377     unsigned int rv;
378     char *rb = regBuff;
379     int i;
380
381     sendSim("dr\n");
382     waitForSim();
383     /* make it some more readable */
384     resp  = simResponse();
385
386     /* the response is of the form 
387        XXXXXX R0 R1 R2 R3 R4 R5 R6 R7 ........
388        XXXXXX XX . ACC=0xxx dd cc B=0xxx dd cc DPTR= 0xxxxx @DPTR= 0xxx dd cc
389        XXXXXX XX . PSW= 0xxx CY=[1|0] AC=[0|1] OV=[0|1] P=[1|0] */
390     memset(regBuff,0,sizeof(regBuff));
391     /* skip the first numerics */
392     while (*resp && !isxdigit(*resp)) resp++;
393     while (*resp && isxdigit(*resp)) resp++;
394
395     /* now get the eight registers */
396     for (i = 0 ; i < 7 ; i++) {
397         while (*resp && isspace(*resp)) resp++;
398         if (!*resp)
399             break;
400         rv = strtol(resp,&resp,16);
401         sprintf(rb,"R%d  : 0x%02X %d %c\n",i,rv,rv,(isprint(rv) ? rv : '.'));
402         rb += strlen(rb);
403     }
404
405     if (!*resp) return regBuff;
406
407     /* skip till end of line */
408     while (*resp && *resp != '\n') resp++;
409     while (*resp && !isxdigit(*resp)) resp++;
410     while (*resp && isxdigit(*resp)) resp++;
411     
412     /* accumulator value */
413     rv = getValueStr(resp,"ACC");
414     sprintf(rb,"ACC : 0x%02X %d %c\n",rv,rv,(isprint(rv) ? rv : '.'));
415     rb += strlen(rb);
416     
417     /* value of B */
418     rv = getValueStr(resp,"B=");
419     sprintf(rb,"B   : 0x%02X %d %c\n",rv,rv,(isprint(rv) ? rv : '.'));
420     rb += strlen(rb);
421
422     rv = getValueStr(resp,"DPTR=");
423     sprintf(rb,"DPTR: 0x%04X %d\n",rv,rv);
424     rb += strlen(rb);
425
426     rv = getValueStr(resp,"@DPTR=");
427     sprintf(rb,"@DPTR: 0x%02X %d %c\n", rv,rv,(isprint(rv) ? rv : '.'));
428     rb += strlen(rb);
429     
430     sprintf(rb,"PSW  : 0x%02X | CY : %d | AC : %d | OV : %d | P : %d\n",
431             getValueStr(resp,"PSW="),
432             getValueStr(resp,"CY="),
433             getValueStr(resp,"AC="),
434             getValueStr(resp,"OV="),
435             getValueStr(resp,"P="));
436
437     return regBuff;
438     
439     
440
441 }
442
443 /*-----------------------------------------------------------------*/
444 /* closeSimulator - close connection to simulator                  */
445 /*-----------------------------------------------------------------*/
446 void closeSimulator ()
447 {
448
449     sendSim("q\n");
450     kill (simPid,SIGKILL);
451     fclose (simin);
452     fclose (simout);
453     shutdown(sock,2);   
454     close(sock);    
455     
456 }