Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[fw/sdcc] / debugger / mcs51 / simi.c
1 /*-------------------------------------------------------------------------
2   simi.c - source file for simulator interaction
3         Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
4
5    This program is free software; you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by the
7    Free Software Foundation; either version 2, or (at your option) any
8    later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19    In other words, you are welcome to use, share and improve this program.
20    You are forbidden to forbid anyone else to use, share and improve
21    what you give them.   Help stamp out software-hoarding!
22 -------------------------------------------------------------------------*/
23 #include "sdcdb.h"
24 #include "simi.h"
25 #include "newalloc.h"
26
27 #ifdef _WIN32
28 #include <windows.h>
29 #include <winsock2.h>
30 #include <signal.h>
31 #include <io.h>
32 #include <fcntl.h>
33 #else
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #include <unistd.h>
40 #include <signal.h>
41 #else
42 #error "Cannot build debugger without socket support"
43 #endif
44 #endif
45
46 FILE *simin ; /* stream for simulator input */
47 FILE *simout; /* stream for simulator output */
48
49 #ifdef _WIN32
50 SOCKET sock = INVALID_SOCKET;
51 PROCESS_INFORMATION *simPid = NULL;
52 #else
53 int sock = -1; /* socket descriptor to comm with simulator */
54 pid_t simPid = -1;
55 #endif
56 static char simibuff[MAX_SIM_BUFF];    /* sim buffer       */
57 static char regBuff[MAX_SIM_BUFF];
58 static char *sbp = simibuff;           /* simulator buffer pointer */
59 extern char **environ;
60 char simactive = 0;
61
62 static memcache_t memCache[NMEM_CACHE];
63
64 /*-----------------------------------------------------------------*/
65 /* get data from  memory cache/ load cache from simulator          */
66 /*-----------------------------------------------------------------*/
67 static char *getMemCache(unsigned int addr,int cachenum, int size)
68 {
69     char *resp, *buf;
70     unsigned int laddr;
71     memcache_t *cache = &memCache[cachenum];
72
73     if ( cache->size <=   0 ||
74          cache->addr > addr ||
75          cache->addr + cache->size < addr + size )
76     {
77         if ( cachenum == IMEM_CACHE )
78         {
79             sendSim("di 0x0 0xff\n");
80         }
81         else if ( cachenum == SREG_CACHE )
82         {
83             sendSim("ds 0x80 0xff\n");
84         }
85         else if ( cachenum == CMEM_CACHE )
86         {
87 #define CMEM_CACHE_MASK ((MAX_CACHE_SIZE >> 2) - 1)
88             laddr = addr & ~CMEM_CACHE_MASK;
89             sprintf(cache->buffer,"dump rom 0x%x 0x%x\n",laddr,laddr+CMEM_CACHE_MASK );
90             sendSim(cache->buffer);
91         }
92         else
93         {
94             laddr = addr & 0xffffffc0;
95             sprintf(cache->buffer,"dx 0x%x 0x%x\n",laddr,laddr+0xff );
96             sendSim(cache->buffer);
97         }
98         waitForSim(100,NULL);
99         resp = simResponse();
100         cache->addr = strtol(resp,0,0);
101         buf = cache->buffer;
102         cache->size = 0;
103         while ( *resp && *(resp+1) && *(resp+2))
104         {
105             /* cache is a stringbuffer with ascii data like
106                " 00 00 00 00 00 00 00 00"
107             */
108             resp += 2;
109             laddr = 0;
110             /* skip thru the address part */
111             while (isxdigit(*resp)) resp++;
112             while ( *resp && *resp != '\n')
113             {
114                 if ( laddr < 24 )
115                 {
116                     laddr++ ;
117                     *buf++ = *resp ;
118                 }
119                 resp++;
120             }
121             resp++ ;
122             cache->size += 8;
123         }
124         *buf = '\0';
125         if ( cache->addr > addr ||
126              cache->addr + cache->size < addr + size )
127             return NULL;
128     }
129     return cache->buffer + (addr - cache->addr)*3;
130 }
131
132 /*-----------------------------------------------------------------*/
133 /* invalidate memory cache                                         */
134 /*-----------------------------------------------------------------*/
135 static void invalidateCache( int cachenum )
136 {
137     memCache[cachenum].size = 0;
138 }
139
140 /*-----------------------------------------------------------------*/
141 /* waitForSim - wait till simulator is done its job                */
142 /*-----------------------------------------------------------------*/
143 void waitForSim(int timeout_ms, char *expect)
144 {
145   int i=0;
146   int ch;
147
148 Dprintf(D_simi, ("simi: waitForSim start(%d)\n", timeout_ms));
149     sbp = simibuff;
150
151     while ((ch = fgetc(simin)) > 0 ) {
152         *sbp++ = ch;
153     }
154     *sbp = 0;
155     Dprintf(D_simi, ("waitForSim(%d) got[%s]\n", timeout_ms, simibuff));
156
157 }
158
159 /*-----------------------------------------------------------------*/
160 /* openSimulator - create a pipe to talk to simulator              */
161 /*-----------------------------------------------------------------*/
162 #ifdef _WIN32
163 static void init_winsock(void)
164 {
165     static int is_initialized = 0;
166
167     if (!is_initialized)
168     {
169         WSADATA wsaData;
170         int iResult;
171
172         // Initialize Winsock
173         if (0 != WSAStartup(MAKEWORD(2,2), &wsaData))
174         {
175             fprintf(stderr, "WSAStartup failed: %d\n", iResult);
176             exit(1);
177         }
178     }
179 }
180
181 static char *argsToCmdLine(char **args, int nargs)
182 {
183 #define CHUNCK  256
184     int i;
185     int cmdPos = 0;
186     char *cmd = Safe_malloc(CHUNCK);
187     int cmdLen = CHUNCK;
188
189     for (i = 0; i < nargs; i++)
190     {
191         int quote = 0;
192         int argLen = strlen(args[i]);
193
194         if (NULL != strchr(args[i], ' '))
195         {
196             quote = 1;
197             argLen += 2;
198         }
199
200         if (0 < i)
201             ++argLen;
202
203         if (cmdPos + argLen >= cmdLen)
204         {
205             do
206             {
207                 cmdLen += cmdLen;
208             }
209             while (cmdPos + argLen >= cmdLen);
210             cmd = Safe_realloc(cmd, cmdLen);
211         }
212
213         if (0 < i)
214         {
215             cmd[cmdPos++] = ' ';
216             --argLen;
217         }
218
219         if (quote)
220         {
221             cmd[cmdPos++] = '"';
222             --argLen;
223         }
224
225         memcpy(&cmd[cmdPos], args[i], argLen);
226         cmdPos += argLen;
227
228         if (quote)
229             cmd[cmdPos++] = '"';
230     }
231
232     cmd[cmdPos] = '\0';
233
234     return cmd;
235 }
236
237 static PROCESS_INFORMATION *execSimulator(char **args, int nargs)
238 {
239     STARTUPINFO si;
240     static PROCESS_INFORMATION pi;
241     char *cmdLine = argsToCmdLine(args, nargs);
242
243     memset(&si, 0, sizeof(si));
244     si.cb = sizeof(si);
245     memset(&pi, 0, sizeof(pi));
246
247     // Start the child process.
248     if (!CreateProcess(NULL,   // No module name (use command line)
249         cmdLine, // Command line
250         NULL,           // Process handle not inheritable
251         NULL,           // Thread handle not inheritable
252         FALSE,          // Set handle inheritance to FALSE
253         0,              // No creation flags
254         NULL,           // Use parent's environment block
255         NULL,           // Use parent's starting directory
256         &si,            // Pointer to STARTUPINFO structure
257         &pi)            // Pointer to PROCESS_INFORMATION structure
258     )
259     {
260         Safe_free(cmdLine);
261         printf( "CreateProcess failed (%d).\n", GetLastError() );
262         return NULL;
263     }
264
265     Safe_free(cmdLine);
266     return &pi;
267 }
268
269 void openSimulator (char **args, int nargs)
270 {
271     struct sockaddr_in sin;
272     int retry = 0;
273     int i;
274     int fh;
275
276     init_winsock();
277
278     Dprintf(D_simi, ("simi: openSimulator\n"));
279 #ifdef SDCDB_DEBUG
280     if (D_simi & sdcdbDebug)
281     {
282         printf("simi: openSimulator: ");
283         for (i=0; i < nargs; i++ )
284         {
285             printf("arg%d: %s ",i,args[i]);
286         }
287         printf("\n");
288     }
289 #endif
290     invalidateCache(XMEM_CACHE);
291     invalidateCache(IMEM_CACHE);
292     invalidateCache(SREG_CACHE);
293     invalidateCache(CMEM_CACHE);
294
295     if (INVALID_SOCKET == (sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0))) {
296         fprintf(stderr, "cannot create socket: %d\n", WSAGetLastError());
297         exit(1);
298     }
299
300     memset(&sin,0,sizeof(sin));
301     sin.sin_family = AF_INET;
302     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
303     sin.sin_port = htons(9756);
304
305  try_connect:
306     /* connect to the simulator */
307     if (SOCKET_ERROR == connect(sock, (struct sockaddr *)&sin, sizeof(sin)))
308     {
309         /* if failed then wait 1 second & try again
310            do this for 10 secs only */
311         if (retry < 10)
312         {
313             if ( !retry )
314                 simPid = execSimulator(args, nargs);
315             retry ++;
316             Sleep(1000);
317             goto try_connect;
318         }
319         perror("connect failed :");
320         exit(1);
321     }
322
323     fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
324     if (-1 == fh)
325     {
326         perror("cannot _open_osfhandle");
327         exit(1);
328     }
329
330     /* go the socket now turn it into a file handle */
331     if (!(simin = fdopen(fh, "r")))
332     {
333         perror("cannot open socket for read");
334         exit(1);
335     }
336
337     fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
338     if (-1 == fh)
339     {
340         perror("cannot _open_osfhandle");
341         exit(1);
342     }
343
344     if (!(simout = fdopen(fh, "w")))
345     {
346         perror("cannot open socket for write");
347         exit(1);
348     }
349     /* now that we have opened, wait for the prompt */
350     waitForSim(200, NULL);
351     simactive = 1;
352 }
353 #else
354 static int execSimulator(char **args, int nargs)
355 {
356     if ((simPid = fork()))
357     {
358         Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
359     }
360     else
361     {
362         /* we are in the child process : start the simulator */
363         signal(SIGINT , SIG_IGN );
364         signal(SIGABRT, SIG_IGN );
365         signal(SIGHUP , SIG_IGN );
366         signal(SIGCHLD, SIG_IGN );
367
368         if (execvp(args[0],args) < 0)
369         {
370             perror("cannot exec simulator");
371             exit(1);
372         }
373     }
374     return simPid;
375 }
376
377 void openSimulator (char **args, int nargs)
378 {
379     struct sockaddr_in sin;
380     int retry = 0;
381     int i;
382     Dprintf(D_simi, ("simi: openSimulator\n"));
383 #ifdef SDCDB_DEBUG
384     if (D_simi & sdcdbDebug)
385     {
386         printf("simi: openSimulator: ");
387         for (i=0; i < nargs; i++ )
388         {
389             printf("arg%d: %s ",i,args[i]);
390         }
391         printf("\n");
392     }
393 #endif
394     invalidateCache(XMEM_CACHE);
395     invalidateCache(IMEM_CACHE);
396     invalidateCache(SREG_CACHE);
397     invalidateCache(CMEM_CACHE);
398
399     if ((sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
400     {
401         perror("cannot create socket");
402         exit(1);
403     }
404
405     memset(&sin,0,sizeof(sin));
406     sin.sin_family = AF_INET;
407     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
408     sin.sin_port = htons(9756);
409
410  try_connect:
411     /* connect to the simulator */
412     if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
413     {
414         /* if failed then wait 1 second & try again
415            do this for 10 secs only */
416         if (retry < 10)
417         {
418             if ( !retry )
419             {
420                 simPid = execSimulator(args, nargs);
421             }
422             retry ++;
423             sleep (1);
424             goto try_connect;
425         }
426         perror("connect failed :");
427         exit(1);
428     }
429     /* go the socket now turn it into a file handle */
430     if (!(simin = fdopen(sock,"r")))
431     {
432         fprintf(stderr,"cannot open socket for read\n");
433         exit(1);
434     }
435
436     if (!(simout = fdopen(sock,"w")))
437     {
438         fprintf(stderr,"cannot open socket for write\n");
439         exit(1);
440     }
441     /* now that we have opened, wait for the prompt */
442     waitForSim(200,NULL);
443     simactive = 1;
444 }
445 #endif
446
447 /*-----------------------------------------------------------------*/
448 /* simResponse - returns buffer to simulator's response            */
449 /*-----------------------------------------------------------------*/
450 char *simResponse(void)
451 {
452     return simibuff;
453 }
454
455 /*-----------------------------------------------------------------*/
456 /* sendSim - sends a command to the simuator                 */
457 /*-----------------------------------------------------------------*/
458 void sendSim(char *s)
459 {
460     if ( ! simout )
461         return;
462
463     Dprintf(D_simi, ("simi: sendSim-->%s", s));  // s has LF at end already
464     fputs(s,simout);
465     fflush(simout);
466 }
467
468
469 static int getMemString(char *buffer, char wrflag,
470                         unsigned int *addr, char mem, int size )
471 {
472     int cachenr = NMEM_CACHE;
473     char *prefix;
474     char *cmd ;
475
476     if ( wrflag )
477         cmd = "set mem";
478     else
479         cmd = "dump";
480     buffer[0] = '\0' ;
481
482     switch (mem)
483     {
484         case 'A': /* External stack */
485         case 'F': /* External ram */
486         case 'P': /* Pdata space */
487             prefix = "xram";
488             cachenr = XMEM_CACHE;
489             break;
490         case 'C': /* Code */
491         case 'D': /* Code / static segment */
492             prefix = "rom";
493             cachenr = CMEM_CACHE;
494             break;
495         case 'B': /* Internal stack */
496         case 'E': /* Internal ram (lower 128) bytes */
497         case 'G': /* Internal ram */
498             prefix = "iram";
499             cachenr = IMEM_CACHE;
500             break;
501         case 'H': /* Bit addressable */
502         case 'J': /* SBIT space */
503             cachenr = BIT_CACHE;
504             if ( wrflag )
505             {
506                 cmd = "set bit";
507             }
508             sprintf(buffer,"%s 0x%x\n",cmd,*addr);
509             return cachenr;
510             break;
511         case 'I': /* SFR space */
512             prefix = "sfr" ;
513             cachenr = SREG_CACHE;
514             break;
515         case 'R': /* Register space */
516             prefix = "iram";
517             /* get register bank */
518             cachenr = simGetValue (0xd0,'I',1);
519             *addr  += cachenr & 0x18 ;
520             cachenr = IMEM_CACHE;
521             break;
522         default:
523         case 'Z': /* undefined space code */
524             return cachenr;
525     }
526     if ( wrflag )
527         sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
528     else
529         sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
530     return cachenr;
531 }
532
533 void simSetPC( unsigned int addr )
534 {
535     char buffer[40];
536     sprintf(buffer,"pc %d\n", addr);
537     sendSim(buffer);
538     waitForSim(100,NULL);
539     simResponse();
540 }
541
542 unsigned int simGetPC(void)
543 {
544     char *sr;
545     sendSim("pc\n");
546     waitForSim(100,NULL);
547     simResponse();
548     sr = simResponse();
549     return strtol(sr+3,0,0);
550 }
551     
552 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
553 {
554     char cachenr, i;
555     char buffer[40];
556     char *s;
557
558     if ( size <= 0 )
559         return 0;
560
561     cachenr = getMemString(buffer,1,&addr,mem,size);
562     if ( cachenr < NMEM_CACHE )
563     {
564         invalidateCache(cachenr);
565     }
566     s = buffer + strlen(buffer) -1;
567     for ( i = 0 ; i < size ; i++ )
568     {
569         sprintf(s," 0x%lx", val & 0xff);
570         s += strlen(s);
571         val >>= 8;
572     }
573     sprintf(s,"\n");
574     sendSim(buffer);
575     waitForSim(100,NULL);
576     simResponse();
577     return 0;
578 }
579
580
581 /*-----------------------------------------------------------------*/
582 /* simGetValue - get value @ address for mem space                 */
583 /*-----------------------------------------------------------------*/
584 unsigned long simGetValue (unsigned int addr,char mem, int size)
585 {
586     unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
587     char cachenr, i;
588     char buffer[40];
589     char *resp;
590
591     if ( size <= 0 )
592         return 0;
593
594     cachenr = getMemString(buffer,0,&addr,mem,size);
595
596     resp = NULL;
597     if ( cachenr < NMEM_CACHE )
598     {
599         resp = getMemCache(addr,cachenr,size);
600     }
601     if ( !resp )
602     {
603         /* create the simulator command */
604         sendSim(buffer);
605         waitForSim(100,NULL);
606         resp = simResponse();
607
608         /* got the response we need to parse it the response
609            is of the form
610            [address] [v] [v] [v] ... special case in
611            case of bit variables which case it becomes
612            [address] [assembler bit address] [v] */
613         /* first skip thru white space */
614         resp = trim_left(resp);
615
616         if (strncmp(resp, "0x",2) == 0)
617             resp += 2;
618
619         /* skip thru the address part */
620         while (isxdigit(*resp)) resp++;
621
622     }
623     /* make the branch for bit variables */
624     if ( cachenr == BIT_CACHE)
625     {
626         /* skip until newline */
627         while (*resp && *resp != '\n' ) resp++ ;
628         if ( *--resp != '0' )
629             b[0] = 1;
630     }
631     else
632     {
633         for (i = 0 ; i < size ; i++ )
634         {
635             /* skip white space */
636             resp = trim_left(resp);
637
638             b[i] = strtol(resp,&resp,16);
639         }
640     }
641
642     return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
643
644 }
645
646 /*-----------------------------------------------------------------*/
647 /* simSetBP - set break point for a given address                  */
648 /*-----------------------------------------------------------------*/
649 void simSetBP (unsigned int addr)
650 {
651     char buff[50];
652
653     sprintf(buff,"break 0x%x\n",addr);
654     sendSim(buff);
655     waitForSim(100,NULL);
656 }
657
658 /*-----------------------------------------------------------------*/
659 /* simClearBP - clear a break point                                */
660 /*-----------------------------------------------------------------*/
661 void simClearBP (unsigned int addr)
662 {
663     char buff[50];
664
665     sprintf(buff,"clear 0x%x\n",addr);
666     sendSim(buff);
667     waitForSim(100,NULL);
668 }
669
670 /*-----------------------------------------------------------------*/
671 /* simLoadFile - load the simulator file                           */
672 /*-----------------------------------------------------------------*/
673 void simLoadFile (char *s)
674 {
675     char buff[128];
676
677     sprintf(buff,"file \"%s\"\n",s);
678     printf("%s",buff);
679     sendSim(buff);
680     waitForSim(500,NULL);
681 }
682
683 /*-----------------------------------------------------------------*/
684 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
685 /*-----------------------------------------------------------------*/
686 unsigned int simGoTillBp ( unsigned int gaddr)
687 {
688     char *sr;
689     unsigned addr ;
690     char *sfmt;
691     int wait_ms = 1000;
692
693     invalidateCache(XMEM_CACHE);
694     invalidateCache(IMEM_CACHE);
695     invalidateCache(SREG_CACHE);
696     if (gaddr == 0) {
697         /* initial start, start & stop from address 0 */
698         //char buf[20];
699
700            // this program is setting up a bunch of breakpoints automatically
701            // at key places.  Like at startup & main() and other function
702            // entry points.  So we don't need to setup one here..
703         //sendSim("break 0x0\n");
704         //sleep(1);
705         //waitForSim();
706
707         sendSim("reset\n");
708         waitForSim(wait_ms, NULL);
709         sendSim("run 0x0\n");
710     } else      if (gaddr == -1) { /* resume */
711         sendSim ("run\n");
712         wait_ms = 100;
713     }
714     else        if (gaddr == 1 ) { /* nexti or next */
715         sendSim ("next\n");
716         wait_ms = 100;
717     }
718     else        if (gaddr == 2 ) { /* stepi or step */
719         sendSim ("step\n");
720         wait_ms = 100;
721     }
722     else  {
723         printf("Error, simGoTillBp > 0!\n");
724         exit(1);
725     }
726
727     waitForSim(wait_ms, NULL);
728
729     /* get the simulator response */
730     sr = simResponse();
731     /* check for errors */
732     while ( *sr )
733     {
734         while ( *sr && *sr != 'E' ) sr++ ;
735         if ( !*sr )
736             break;
737         if ( ! strncmp(sr,"Error:",6))
738         {
739             fputs(sr,stdout);
740             break;
741         }
742         sr++ ;
743     }
744
745     nointerrupt = 1;
746     /* get answer of stop command */
747     if ( userinterrupt )
748         waitForSim(wait_ms, NULL);
749
750     /* better solution: ask pc */
751     sendSim ("pc\n");
752     waitForSim(100, NULL);
753     sr = simResponse();
754     nointerrupt = 0;
755
756     gaddr = strtol(sr+3,0,0);
757     return gaddr;
758 }
759
760 /*-----------------------------------------------------------------*/
761 /* simReset - reset the simulator                                  */
762 /*-----------------------------------------------------------------*/
763 void simReset (void)
764 {
765     invalidateCache(XMEM_CACHE);
766     invalidateCache(IMEM_CACHE);
767     invalidateCache(SREG_CACHE);
768     invalidateCache(CMEM_CACHE);
769     sendSim("res\n");
770     waitForSim(100,NULL);
771 }
772
773
774 /*-----------------------------------------------------------------*/
775 /* closeSimulator - close connection to simulator                  */
776 /*-----------------------------------------------------------------*/
777 void closeSimulator (void)
778 {
779 #ifdef _WIN32
780     if ( ! simin || ! simout || INVALID_SOCKET == sock )
781 #else
782     if ( ! simin || ! simout || sock == -1 )
783 #endif
784     {
785         simactive = 0;
786         return;
787     }
788     simactive = 0;
789     sendSim("quit\n");
790     fclose (simin);
791     fclose (simout);
792     shutdown(sock,2);
793 #ifdef _WIN32
794     closesocket(sock);
795     sock = -1;
796     if (NULL != simPid)
797         TerminateProcess(simPid->hProcess, 0);
798     // Close process and thread handles.
799     CloseHandle(simPid->hProcess);
800     CloseHandle(simPid->hThread);
801 #else
802     close(sock);
803     sock = -1;
804     if ( simPid > 0 )
805         kill (simPid,SIGKILL);
806 #endif
807 }