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