*** empty log message ***
[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
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))) {
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     Dprintf(D_simi, ("sendSim-->%s", s));  // s has LF at end already
184     fputs(s,simout);
185     fflush(simout);
186 }
187
188 /*-----------------------------------------------------------------*/
189 /* simGetValue - get value @ address for mem space                 */
190 /*-----------------------------------------------------------------*/
191 unsigned long simGetValue (unsigned int addr,char mem, int size)
192 {
193     unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
194     char i;
195     char *prefix;
196     char buffer[20];
197     char *resp;
198
199     switch (mem) {
200     case 'A':
201       prefix = "dx";
202       break;
203     case 'B':       
204       prefix = "di";
205       break;
206     case 'C':
207     case 'D':
208         prefix = "dch";
209         break;
210     case 'E':
211     case 'G':
212         prefix = "di";
213         break;
214     case 'F':
215         prefix = "dx";
216         break;
217     case 'H':
218     case 'J':
219 //      prefix = "db" ;
220         prefix = "dump" ;
221         break;
222     case 'I':
223         prefix = "ds" ;
224         break;  
225     }
226     
227     /* create the simulator command */
228     sprintf(buffer,"%s 0x%x \n",prefix,addr);
229     sendSim(buffer);
230     waitForSim(100,NULL);
231     resp = simResponse();
232
233     /* got the response we need to parse it the response
234        is of the form 
235        [address] [v] [v] [v] ... special case in
236        case of bit variables which case it becomes
237        [address] [assembler bit address] [v] */
238     /* first skip thru white space */
239     while (isspace(*resp)) resp++ ;
240
241     if (strncmp(resp, "0x",2) == 0)
242       resp += 2;
243
244     /* then make the branch for bit variables */
245     /* skip thru the address part */
246     while (isxdigit(*resp)) resp++;
247     
248     if (!strcmp(prefix,"dump")) {
249
250         /* skip white space */
251         while (isspace(*resp)) resp++ ;
252     
253         /* skip thru the assembler bit address */
254         while (!isspace(*resp)) resp++;
255
256         /* white space */
257         while (isspace(*resp)) resp++ ;
258
259         /* scan in the value */
260         sscanf(resp,"%d",&b[0]);
261     } else {
262         
263         for (i = 0 ; i < size ; i++ ) {
264             /* skip white space */
265             while (isspace(*resp)) resp++ ;
266             
267             sscanf(resp,"%x",&b[i]);
268             
269             /* skip */
270             while (isxdigit(*resp)) resp++;
271         }
272     }
273
274     return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
275         
276 }
277
278 /*-----------------------------------------------------------------*/
279 /* simSetBP - set break point for a given address                  */
280 /*-----------------------------------------------------------------*/
281 void simSetBP (unsigned int addr)
282 {
283     char buff[50];
284
285     sprintf(buff,"break 0x%x\n",addr);
286     sendSim(buff);
287     waitForSim(100,NULL);
288 }
289
290 /*-----------------------------------------------------------------*/
291 /* simClearBP - clear a break point                                */
292 /*-----------------------------------------------------------------*/
293 void simClearBP (unsigned int addr)
294 {
295     char buff[50];
296
297     sprintf(buff,"clear 0x%x\n",addr);
298     sendSim(buff);
299     waitForSim(100,NULL);
300 }
301
302 /*-----------------------------------------------------------------*/
303 /* simLoadFile - load the simulator file                           */
304 /*-----------------------------------------------------------------*/
305 void simLoadFile (char *s)
306 {
307     char buff[128];
308
309     sprintf(buff,"l \"%s\"\n",s);
310     printf(buff);
311     sendSim(buff);
312     waitForSim(500,NULL);
313 }
314
315 /*-----------------------------------------------------------------*/
316 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
317 /*-----------------------------------------------------------------*/
318 unsigned int simGoTillBp ( unsigned int gaddr)
319 {
320     char *sr, *svr;
321     unsigned addr ; 
322     char *sfmt;
323     int wait_ms = 1000;
324
325     if (gaddr == 0) {
326       /* initial start, start & stop from address 0 */
327       char buf[20];
328
329          // this program is setting up a bunch of breakpoints automatically
330          // at key places.  Like at startup & main() and other function
331          // entry points.  So we don't need to setup one here..
332       //sendSim("break 0x0\n");
333       //sleep(1);
334       //waitForSim();
335
336       sendSim("run 0x0\n");
337     } else      if (gaddr == -1) { /* resume */
338       sendSim ("run\n");
339       wait_ms = 100;
340     }
341     else {
342       printf("Error, simGoTillBp > 0!\n");
343       exit(1);
344     }
345
346     waitForSim(wait_ms, NULL);
347     
348     /* get the simulator response */
349     svr  = sr = strdup(simResponse());
350
351     /* figure out the address of the break point the simulators 
352        response in a break point situation is of the form 
353        [... F* <addr> <disassembled instruction> ] 
354        we will ignore till we get F* then parse the address */
355     while (*sr) {
356       if (strncmp(sr,"Stop at",7) == 0) {
357           sr += 7;
358           sfmt = "%x";
359           break;
360       } 
361
362       if (*sr == 'F' && ( *(sr+1) == '*' || *(sr+1) == ' ')) {
363           sr += 2;
364           sfmt = "%x";
365           break;
366       }
367       sr++;
368     }
369
370     if (!*sr) {
371       fprintf(stderr, "Error?, simGoTillBp failed to Stop\n");
372       return 0;
373     }
374
375     while (isspace(*sr)) sr++ ;
376
377     if (sscanf(sr,sfmt,&addr) != 1) {
378       fprintf(stderr, "Error?, simGoTillBp failed to get Addr\n");
379       return 0;
380     }
381         return addr;
382
383 }
384
385 /*-----------------------------------------------------------------*/
386 /* simReset - reset the simulator                                  */
387 /*-----------------------------------------------------------------*/
388 void simReset ()
389 {
390     sendSim("res\n");
391     waitForSim(100,NULL);
392 }
393
394 /*-----------------------------------------------------------------*/
395 /* getValueStr - read a value followed by a string =               */
396 /*-----------------------------------------------------------------*/
397 static unsigned int getValueStr (char *src,char *cstr)
398 {
399     int i = strlen(cstr);
400     int rv;
401     /* look for the string */
402     if (! (src = strstr(src,cstr)))
403         return 0;
404
405     src += i;
406     if (!*src) return 0;
407
408     /* look for the digit */
409     while (*src && !isxdigit(*src)) src++;
410     sscanf(src,"%x",&rv);
411     return rv;
412 }
413
414 /*-----------------------------------------------------------------*/
415 /* simRegs - returns value of registers                            */
416 /*-----------------------------------------------------------------*/
417 char  *simRegs()
418 {   
419     char *resp ;
420     unsigned int rv;
421     char *rb = regBuff;
422     int i;
423
424     sendSim("info registers\n");
425
426     waitForSim(100,NULL);
427          
428     resp  = simResponse();
429
430     return resp;
431
432 #if 0
433   Take this out(2-09-02) cant see as its that useful to reformat, karl.
434   
435     /* the response is of the form 
436        XXXXXX R0 R1 R2 R3 R4 R5 R6 R7 ........
437        XXXXXX XX . ACC=0xxx dd cc B=0xxx dd cc DPTR= 0xxxxx @DPTR= 0xxx dd cc
438        XXXXXX XX . PSW= 0xxx CY=[1|0] AC=[0|1] OV=[0|1] P=[1|0]
439
440 Format as of 8-4-01:
441        0x00 00 00 00 00 00 00 00 00 ........
442        000000 00 .  ACC= 0x00   0 .  B= 0x00   DPTR= 0x0000 @DPTR= 0x00   0 .
443        000000 00 .  PSW= 0x00 CY=0 AC=0 OV=0 P=0
444 F  0x006d 75 87 80 MOV   PCON,#80
445 */
446
447     memset(regBuff,0,sizeof(regBuff));
448     /* skip the first numerics */
449     while (*resp && !isxdigit(*resp)) resp++;
450
451     if (strncmp(resp, "0x", 2)) {
452       fprintf(stderr, "Error: Format1A\n");
453       return regBuff;
454     }
455     resp += 2;
456     while (*resp && isxdigit(*resp)) resp++;
457
458     /* now get the eight registers */
459     for (i = 0 ; i < 7 ; i++) {
460         while (*resp && isspace(*resp)) resp++;
461         if (!*resp)
462             break;
463         rv = strtol(resp,&resp,16);
464         sprintf(rb,"R%d  : 0x%02X %d %c\n",i,rv,rv,(isprint(rv) ? rv : '.'));
465         rb += strlen(rb);
466     }
467
468     if (!*resp) return regBuff;
469
470     /* skip till end of line */
471     while (*resp && *resp != '\n') resp++;
472     while (*resp && !isxdigit(*resp)) resp++;
473     while (*resp && isxdigit(*resp)) resp++;
474     
475     /* accumulator value */
476     rv = getValueStr(resp,"ACC");
477     sprintf(rb,"ACC : 0x%02X %d %c\n",rv,rv,(isprint(rv) ? rv : '.'));
478     rb += strlen(rb);
479     
480     /* value of B */
481     rv = getValueStr(resp,"B=");
482     sprintf(rb,"B   : 0x%02X %d %c\n",rv,rv,(isprint(rv) ? rv : '.'));
483     rb += strlen(rb);
484
485     rv = getValueStr(resp,"DPTR=");
486     sprintf(rb,"DPTR: 0x%04X %d\n",rv,rv);
487     rb += strlen(rb);
488
489     rv = getValueStr(resp,"@DPTR=");
490     sprintf(rb,"@DPTR: 0x%02X %d %c\n", rv,rv,(isprint(rv) ? rv : '.'));
491     rb += strlen(rb);
492     
493     sprintf(rb,"PSW  : 0x%02X | CY : %d | AC : %d | OV : %d | P : %d\n",
494             getValueStr(resp,"PSW="),
495             getValueStr(resp,"CY="),
496             getValueStr(resp,"AC="),
497             getValueStr(resp,"OV="),
498             getValueStr(resp,"P="));
499
500     return regBuff;
501 #endif
502
503 }
504
505 /*-----------------------------------------------------------------*/
506 /* closeSimulator - close connection to simulator                  */
507 /*-----------------------------------------------------------------*/
508 void closeSimulator ()
509 {
510
511     sendSim("q\n");
512     kill (simPid,SIGKILL);
513     fclose (simin);
514     fclose (simout);
515     shutdown(sock,2);   
516     close(sock);    
517     
518 }