struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / debugger / mcs51 / simi.c
blob3e1ae895e6b0c3e65b4f7f96ef89cbc346b38679
1 /*-------------------------------------------------------------------------
2 simi.c - source file for simulator interaction
3 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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.
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.
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.
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 #undef DATADIR
25 #include "simi.h"
26 #include "newalloc.h"
28 #ifdef _WIN32
29 # include <windows.h>
30 # include <winsock2.h>
31 # include <io.h>
32 #else
33 # ifdef __sun
34 # define BSD_COMP
35 # include <sys/file.h>
36 # endif
37 # ifdef HAVE_SYS_SOCKET_H
38 # include <sys/types.h>
39 # include <sys/socket.h>
40 # include <netinet/in.h>
41 # include <arpa/inet.h>
42 # include <unistd.h>
43 # include <sys/ioctl.h>
44 # else
45 # error "Cannot build debugger without socket support"
46 # endif
47 #endif
48 #include <fcntl.h>
49 #include <signal.h>
50 #include <time.h>
52 FILE *simin ; /* stream for simulator input */
53 FILE *simout; /* stream for simulator output */
55 #ifdef _WIN32
56 SOCKET sock = INVALID_SOCKET;
57 PROCESS_INFORMATION *simPid = NULL;
58 #else
59 int sock = -1; /* socket descriptor to comm with simulator */
60 pid_t simPid = -1;
61 #endif
62 static char simibuff[MAX_SIM_BUFF]; /* sim buffer */
63 static char *sbp = simibuff; /* simulator buffer pointer */
64 char simactive = 0;
66 static memcache_t memCache[NMEM_CACHE];
68 /*-----------------------------------------------------------------*/
69 /* get data from memory cache/ load cache from simulator */
70 /*-----------------------------------------------------------------*/
71 static char *getMemCache(unsigned int addr,int cachenum, unsigned int size)
73 char *resp, *buf;
74 unsigned int laddr;
75 memcache_t *cache = &memCache[cachenum];
77 if ( cache->size <= 0 ||
78 cache->addr > addr ||
79 cache->addr + cache->size < addr + size )
81 if ( cachenum == IMEM_CACHE )
83 sendSim("di 0x0 0xff\n");
85 else if ( cachenum == SREG_CACHE )
87 sendSim("ds 0x80 0xff\n");
89 else
91 laddr = addr & 0xffffffc0;
92 sprintf(cache->buffer,"dx 0x%x 0x%x\n",laddr,laddr+0xff );
93 sendSim(cache->buffer);
95 waitForSim(100,NULL);
96 resp = simResponse();
97 cache->addr = strtol(resp,0,0);
98 buf = cache->buffer;
99 cache->size = 0;
100 while ( *resp && *(resp+1) && *(resp+2))
102 /* cache is a stringbuffer with ascii data like
103 " 00 00 00 00 00 00 00 00"
105 resp += 2;
106 laddr = 0;
107 /* skip thru the address part */
108 while (isxdigit(*resp))
109 resp++;
110 while ( *resp && *resp != '\n')
112 if ( laddr < 24 )
114 laddr++ ;
115 *buf++ = *resp ;
117 resp++;
119 resp++ ;
120 cache->size += 8;
122 *buf = '\0';
123 if ( cache->addr > addr ||
124 cache->addr + cache->size < addr + size )
126 return NULL;
129 return cache->buffer + (addr - cache->addr)*3;
132 /*-----------------------------------------------------------------*/
133 /* invalidate memory cache */
134 /*-----------------------------------------------------------------*/
135 static void invalidateCache( int cachenum )
137 memCache[cachenum].size = 0;
140 /*-----------------------------------------------------------------*/
141 /* waitForSim - wait till simulator is done doing its job */
142 /*-----------------------------------------------------------------*/
143 void waitForSim(int timeout_ms, char *expect)
145 int ch;
146 clock_t timeout;
148 Dprintf(D_simi, ("simi: waitForSim start(%d)\n", timeout_ms));
149 sbp = simibuff;
151 timeout = clock() + ((timeout_ms * CLOCKS_PER_SEC) / 1000);
152 while (((ch = fgetc(simin)) > 0 ) && (clock() <= timeout))
154 *sbp++ = ch;
156 *sbp = 0;
157 Dprintf(D_simi, ("waitForSim(%d) got[%s]\n", timeout_ms, simibuff));
160 /*-----------------------------------------------------------------*/
161 /* openSimulator - create a pipe to talk to simulator */
162 /*-----------------------------------------------------------------*/
163 #ifdef _WIN32
164 static void init_winsock(void)
166 static int is_initialized = 0;
168 if (!is_initialized)
170 WSADATA wsaData;
171 int iResult;
173 // Initialize Winsock
174 iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
175 if (0 != iResult)
177 fprintf(stderr, "WSAStartup failed: %d\n", iResult);
178 exit(1);
183 static PROCESS_INFORMATION *execSimulator(char **args, int nargs)
185 STARTUPINFO si;
186 static PROCESS_INFORMATION pi;
187 char *cmdLine = argsToCmdLine(args, nargs);
189 memset(&si, 0, sizeof(si));
190 si.cb = sizeof(si);
191 memset(&pi, 0, sizeof(pi));
193 // Start the child process.
194 if (!CreateProcess(NULL, // No module name (use command line)
195 cmdLine, // Command line
196 NULL, // Process handle not inheritable
197 NULL, // Thread handle not inheritable
198 FALSE, // Set handle inheritance to FALSE
199 0, // No creation flags
200 NULL, // Use parent's environment block
201 NULL, // Use parent's starting directory
202 &si, // Pointer to STARTUPINFO structure
203 &pi) // Pointer to PROCESS_INFORMATION structure
206 Safe_free(cmdLine);
207 printf( "CreateProcess failed (%lu).\n", GetLastError() );
208 return NULL;
211 return &pi;
214 void openSimulator (char **args, int nargs)
216 struct sockaddr_in sin;
217 int retry = 0;
218 int i;
219 int iResult;
220 int fh;
221 u_long iMode;
223 init_winsock();
225 Dprintf(D_simi, ("simi: openSimulator\n"));
226 #ifdef SDCDB_DEBUG
227 if (D_simi & sdcdbDebug)
229 printf("simi: openSimulator: ");
230 for (i=0; i < nargs; i++ )
232 printf("arg%d: %s ", i, args[i]);
234 printf("\n");
236 #endif
237 invalidateCache(XMEM_CACHE);
238 invalidateCache(IMEM_CACHE);
239 invalidateCache(SREG_CACHE);
241 if (INVALID_SOCKET == (sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)))
243 fprintf(stderr, "cannot create socket: %d\n", WSAGetLastError());
244 exit(1);
247 memset(&sin, 0, sizeof(sin));
248 sin.sin_family = AF_INET;
249 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
250 sin.sin_port = htons(9756);
252 try_connect:
253 /* connect to the simulator */
254 if (SOCKET_ERROR == connect(sock, (struct sockaddr *)&sin, sizeof(sin)))
256 /* if failed then wait 1 second & try again
257 do this for 10 secs only */
258 if (retry < 10)
260 if ( !retry )
261 simPid = execSimulator(args, nargs);
262 retry ++;
263 Sleep(1000);
264 goto try_connect;
266 perror("connect failed :");
267 exit(1);
270 iMode = 1; /* set non-blocking mode */
271 iResult = ioctlsocket(sock, FIONBIO, &iMode);
272 if (iResult != NO_ERROR)
274 perror("ioctlsocket failed");
275 exit(1);
278 fh = _open_osfhandle(sock, _O_TEXT);
279 if (-1 == fh)
281 perror("cannot _open_osfhandle");
282 exit(1);
285 /* got the socket now turn it into a file handle */
286 if (!(simin = fdopen(fh, "r")))
288 perror("cannot open socket for read");
289 exit(1);
292 fh = _open_osfhandle(sock, _O_TEXT);
293 if (-1 == fh)
295 perror("cannot _open_osfhandle");
296 exit(1);
299 if (!(simout = fdopen(fh, "w")))
301 perror("cannot open socket for write");
302 exit(1);
304 /* now that we have opened, wait for the prompt */
305 waitForSim(200, NULL);
306 simactive = 1;
308 #else
309 static int execSimulator(char **args, int nargs)
311 if ((simPid = fork()))
313 Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
315 else
317 /* we are in the child process : start the simulator */
318 signal(SIGINT , SIG_IGN );
319 signal(SIGABRT, SIG_IGN );
320 signal(SIGHUP , SIG_IGN );
321 signal(SIGCHLD, SIG_IGN );
323 if (execvp(args[0],args) < 0)
325 perror("cannot exec simulator");
326 exit(1);
329 return simPid;
332 void openSimulator (char **args, int nargs)
334 struct sockaddr_in sin;
335 int retry = 0;
336 int i;
337 int iResult;
338 #if defined(__sun) || defined(__CYGWIN__)
339 u_long iMode;
340 #endif
342 Dprintf(D_simi, ("simi: openSimulator\n"));
343 #ifdef SDCDB_DEBUG
344 if (D_simi & sdcdbDebug)
346 printf("simi: openSimulator: ");
347 for (i=0; i < nargs; i++ )
349 printf("arg%d: %s ",i,args[i]);
351 printf("\n");
353 #endif
354 invalidateCache(XMEM_CACHE);
355 invalidateCache(IMEM_CACHE);
356 invalidateCache(SREG_CACHE);
358 if ((sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
360 perror("cannot create socket");
361 exit(1);
364 memset(&sin,0,sizeof(sin));
365 sin.sin_family = AF_INET;
366 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
367 sin.sin_port = htons(9756);
369 try_connect:
370 /* connect to the simulator */
371 if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
373 /* if failed then wait 1 second & try again
374 do this for 10 secs only */
375 if (retry < 10)
377 if ( !retry )
379 simPid = execSimulator(args, nargs);
381 retry ++;
382 sleep (1);
383 goto try_connect;
385 perror("connect failed :");
386 exit(1);
389 #if defined(__sun) || defined(__CYGWIN__)
390 iMode = 1; /* set non-blocking mode */
391 iResult = ioctl(sock, FIONBIO, &iMode);
392 #else
393 iResult = fcntl(sock, F_SETFL, O_NONBLOCK | O_ASYNC);
394 #endif
395 if (iResult != 0)
397 perror("ioctl failed");
398 exit(1);
401 /* got the socket now turn it into a file handle */
402 if (!(simin = fdopen(sock, "r")))
404 fprintf(stderr,"cannot open socket for read\n");
405 exit(1);
408 if (!(simout = fdopen(sock, "w")))
410 fprintf(stderr,"cannot open socket for write\n");
411 exit(1);
413 /* now that we have opened, wait for the prompt */
414 waitForSim(200,NULL);
415 simactive = 1;
417 #endif
419 /*-----------------------------------------------------------------*/
420 /* simResponse - returns buffer to simulator's response */
421 /*-----------------------------------------------------------------*/
422 char *simResponse(void)
424 return simibuff;
427 /*-----------------------------------------------------------------*/
428 /* sendSim - sends a command to the simuator */
429 /*-----------------------------------------------------------------*/
430 void sendSim(char *s)
432 if ( ! simout )
433 return;
435 Dprintf(D_simi, ("simi: sendSim-->%s", s)); // s has LF at end already
436 fputs(s,simout);
437 fflush(simout);
441 static int getMemString(char *buffer, char wrflag,
442 unsigned int *addr, char mem, unsigned int size )
444 int cachenr = NMEM_CACHE;
445 char *prefix;
446 char *cmd ;
448 if ( wrflag )
449 cmd = "set mem";
450 else
451 cmd = "dump";
452 buffer[0] = '\0' ;
454 switch (mem)
456 case 'A': /* External stack */
457 case 'F': /* External ram */
458 prefix = "xram";
459 cachenr = XMEM_CACHE;
460 break;
461 case 'C': /* Code */
462 case 'D': /* Code / static segment */
463 prefix = "rom";
464 break;
465 case 'B': /* Internal stack */
466 case 'E': /* Internal ram (lower 128) bytes */
467 case 'G': /* Internal ram */
468 prefix = "iram";
469 cachenr = IMEM_CACHE;
470 break;
471 case 'H': /* Bit addressable */
472 case 'J': /* SBIT space */
473 cachenr = BIT_CACHE;
474 if ( wrflag )
476 cmd = "set bit";
478 sprintf(buffer,"%s 0x%x\n",cmd,*addr);
479 return cachenr;
480 case 'I': /* SFR space */
481 prefix = "sfr" ;
482 cachenr = SREG_CACHE;
483 break;
484 case 'R': /* Register space */
485 prefix = "iram";
486 /* get register bank */
487 cachenr = simGetValue (0xd0,'I',1);
488 *addr += cachenr & 0x18 ;
489 cachenr = IMEM_CACHE;
490 break;
491 default:
492 case 'Z': /* undefined space code */
493 return cachenr;
495 if ( wrflag )
496 sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
497 else
498 sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
499 return cachenr;
502 void simSetPC( unsigned int addr )
504 char buffer[40];
505 sprintf(buffer,"pc %d\n", addr);
506 sendSim(buffer);
507 waitForSim(100,NULL);
508 simResponse();
511 int simSetValue (unsigned int addr,char mem, unsigned int size, unsigned long val)
513 unsigned int i;
514 char cachenr;
515 char buffer[40];
516 char *s;
518 if ( size <= 0 )
519 return 0;
521 cachenr = getMemString(buffer, 1, &addr, mem, size);
522 if ( cachenr < NMEM_CACHE )
524 invalidateCache(cachenr);
526 s = buffer + strlen(buffer) -1;
527 for ( i = 0 ; i < size ; i++ )
529 sprintf(s," 0x%lx", val & 0xff);
530 s += strlen(s);
531 val >>= 8;
533 sprintf(s,"\n");
534 sendSim(buffer);
535 waitForSim(100,NULL);
536 simResponse();
537 return 0;
540 /*-----------------------------------------------------------------*/
541 /* simGetValue - get value @ address for mem space */
542 /*-----------------------------------------------------------------*/
543 unsigned long simGetValue (unsigned int addr,char mem, unsigned int size)
545 unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
546 char cachenr;
547 char buffer[40];
548 char *resp;
550 if ( size <= 0 )
551 return 0;
553 cachenr = getMemString(buffer, 0, &addr, mem, size);
555 resp = NULL;
556 if ( cachenr < NMEM_CACHE )
558 resp = getMemCache(addr,cachenr,size);
560 if ( !resp )
562 /* create the simulator command */
563 sendSim(buffer);
564 waitForSim(100,NULL);
565 resp = simResponse();
567 /* got the response we need to parse it the response
568 is of the form
569 [address] [v] [v] [v] ... special case in
570 case of bit variables which case it becomes
571 [address] [assembler bit address] [v] */
572 /* first skip thru white space */
573 resp = trim_left(resp);
575 if (strncmp(resp, "0x",2) == 0)
576 resp += 2;
578 /* skip thru the address part */
579 while (isxdigit(*resp))
580 resp++;
582 /* make the branch for bit variables */
583 if ( cachenr == BIT_CACHE)
585 /* skip until newline */
586 while (*resp && *resp != '\n' )
587 resp++ ;
588 if ( *--resp != '0' )
589 b[0] = 1;
591 else
593 unsigned int i;
595 for (i = 0 ; i < size ; i++ )
597 /* skip white space */
598 resp = trim_left(resp);
600 b[i] = strtol(resp,&resp,16);
604 return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
607 /*-----------------------------------------------------------------*/
608 /* simSetBP - set break point for a given address */
609 /*-----------------------------------------------------------------*/
610 void simSetBP (unsigned int addr)
612 char buff[50];
614 sprintf(buff, "break 0x%x\n", addr);
615 sendSim(buff);
616 waitForSim(100, NULL);
619 /*-----------------------------------------------------------------*/
620 /* simClearBP - clear a break point */
621 /*-----------------------------------------------------------------*/
622 void simClearBP (unsigned int addr)
624 char buff[50];
626 sprintf(buff, "clear 0x%x\n", addr);
627 sendSim(buff);
628 waitForSim(100, NULL);
631 /*-----------------------------------------------------------------*/
632 /* simLoadFile - load the simulator file */
633 /*-----------------------------------------------------------------*/
634 void simLoadFile (char *s)
636 char buff[128];
638 sprintf(buff, "file \"%s\"\n", s);
639 printf("%s",buff);
640 sendSim(buff);
641 waitForSim(500, NULL);
644 /*-----------------------------------------------------------------*/
645 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
646 /*-----------------------------------------------------------------*/
647 unsigned int simGoTillBp ( unsigned int gaddr)
649 char *sr;
650 int wait_ms = 1000;
652 invalidateCache(XMEM_CACHE);
653 invalidateCache(IMEM_CACHE);
654 invalidateCache(SREG_CACHE);
655 if (gaddr == 0)
657 /* initial start, start & stop from address 0 */
658 //char buf[20];
660 // this program is setting up a bunch of breakpoints automatically
661 // at key places. Like at startup & main() and other function
662 // entry points. So we don't need to setup one here..
663 //sendSim("break 0x0\n");
664 //sleep(1);
665 //waitForSim();
667 sendSim("reset\n");
668 waitForSim(wait_ms, NULL);
669 sendSim("run 0x0\n");
671 else if (gaddr == -1)
672 { /* resume */
673 sendSim ("run\n");
674 wait_ms = 100;
676 else if (gaddr == 1 )
677 { /* nexti or next */
678 sendSim ("next\n");
679 wait_ms = 100;
681 else if (gaddr == 2 )
682 { /* stepi or step */
683 sendSim ("step\n");
684 wait_ms = 100;
686 else
688 printf("Error, simGoTillBp > 0!\n");
689 exit(1);
692 waitForSim(wait_ms, NULL);
694 /* get the simulator response */
695 sr = simResponse();
696 /* check for errors */
697 while ( *sr )
699 while ( *sr && *sr != 'E' )
700 sr++ ;
701 if ( !*sr )
702 break;
703 if ( ! strncmp(sr, "Error:", 6))
705 fputs(sr, stdout);
706 break;
708 sr++ ;
711 nointerrupt = 1;
712 /* get answer of stop command */
713 if ( userinterrupt )
714 waitForSim(wait_ms, NULL);
716 /* better solution: ask pc */
717 sendSim ("pc\n");
718 waitForSim(100, NULL);
719 sr = simResponse();
720 nointerrupt = 0;
722 gaddr = strtol(sr+3, 0, 0);
723 return gaddr;
726 /*-----------------------------------------------------------------*/
727 /* simReset - reset the simulator */
728 /*-----------------------------------------------------------------*/
729 void simReset (void)
731 invalidateCache(XMEM_CACHE);
732 invalidateCache(IMEM_CACHE);
733 invalidateCache(SREG_CACHE);
734 sendSim("res\n");
735 waitForSim(100, NULL);
738 /*-----------------------------------------------------------------*/
739 /* closeSimulator - close connection to simulator */
740 /*-----------------------------------------------------------------*/
741 void closeSimulator (void)
743 #ifdef _WIN32
744 if ( ! simin || ! simout || INVALID_SOCKET == sock )
745 #else
746 if ( ! simin || ! simout || sock == -1 )
747 #endif
749 simactive = 0;
750 return;
752 simactive = 0;
753 sendSim("quit\n");
754 shutdown(sock, 2);
755 #ifdef _WIN32
756 closesocket(sock);
757 sock = -1;
758 if (NULL != simPid)
760 TerminateProcess(simPid->hProcess, 0);
761 // Close process and thread handles.
762 CloseHandle(simPid->hProcess);
763 CloseHandle(simPid->hThread);
765 #else
766 close(sock);
767 sock = -1;
768 if ( simPid > 0 )
769 kill (simPid,SIGKILL);
770 #endif
771 /* simin/simout are now dead as they are both associated with the closed socket */
772 simin = NULL;
773 simout = NULL;