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