Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[fw/sdcc] / debugger / mcs51 / simi.c
index 61133fa5481f6e136f26034c7376d9efc664784b..4a771a339fcc4782fa304011bb4b6aa4afb2733b 100644 (file)
@@ -1,29 +1,36 @@
 /*-------------------------------------------------------------------------
   simi.c - source file for simulator interaction
-
-             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
+        Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-   
+
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!  
+   what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 #include "sdcdb.h"
 #include "simi.h"
+#include "newalloc.h"
 
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock2.h>
+#include <signal.h>
+#include <io.h>
+#include <fcntl.h>
+#else
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/types.h>
 #include <sys/socket.h>
 #else
 #error "Cannot build debugger without socket support"
 #endif
+#endif
+
 FILE *simin ; /* stream for simulator input */
 FILE *simout; /* stream for simulator output */
 
+#ifdef _WIN32
+SOCKET sock = INVALID_SOCKET;
+PROCESS_INFORMATION *simPid = NULL;
+#else
 int sock = -1; /* socket descriptor to comm with simulator */
 pid_t simPid = -1;
+#endif
 static char simibuff[MAX_SIM_BUFF];    /* sim buffer       */
 static char regBuff[MAX_SIM_BUFF];
 static char *sbp = simibuff;           /* simulator buffer pointer */
@@ -68,7 +82,14 @@ static char *getMemCache(unsigned int addr,int cachenum, int size)
         {
             sendSim("ds 0x80 0xff\n");
         }
-        else
+        else if ( cachenum == CMEM_CACHE )
+       {
+#define CMEM_CACHE_MASK ((MAX_CACHE_SIZE >> 2) - 1)
+            laddr = addr & ~CMEM_CACHE_MASK;
+            sprintf(cache->buffer,"dump rom 0x%x 0x%x\n",laddr,laddr+CMEM_CACHE_MASK );
+            sendSim(cache->buffer);
+       }
+       else
         {
             laddr = addr & 0xffffffc0;
             sprintf(cache->buffer,"dx 0x%x 0x%x\n",laddr,laddr+0xff );
@@ -113,7 +134,7 @@ static char *getMemCache(unsigned int addr,int cachenum, int size)
 /*-----------------------------------------------------------------*/
 static void invalidateCache( int cachenum )
 {
-    memCache[cachenum].size = 0;  
+    memCache[cachenum].size = 0;
 }
 
 /*-----------------------------------------------------------------*/
@@ -128,7 +149,7 @@ Dprintf(D_simi, ("simi: waitForSim start(%d)\n", timeout_ms));
     sbp = simibuff;
 
     while ((ch = fgetc(simin)) > 0 ) {
-      *sbp++ = ch;
+        *sbp++ = ch;
     }
     *sbp = 0;
     Dprintf(D_simi, ("waitForSim(%d) got[%s]\n", timeout_ms, simibuff));
@@ -138,75 +159,295 @@ Dprintf(D_simi, ("simi: waitForSim start(%d)\n", timeout_ms));
 /*-----------------------------------------------------------------*/
 /* openSimulator - create a pipe to talk to simulator              */
 /*-----------------------------------------------------------------*/
+#ifdef _WIN32
+static void init_winsock(void)
+{
+    static int is_initialized = 0;
+
+    if (!is_initialized)
+    {
+        WSADATA wsaData;
+        int iResult;
+
+        // Initialize Winsock
+        if (0 != WSAStartup(MAKEWORD(2,2), &wsaData))
+        {
+            fprintf(stderr, "WSAStartup failed: %d\n", iResult);
+            exit(1);
+        }
+    }
+}
+
+static char *argsToCmdLine(char **args, int nargs)
+{
+#define CHUNCK  256
+    int i;
+    int cmdPos = 0;
+    char *cmd = Safe_malloc(CHUNCK);
+    int cmdLen = CHUNCK;
+
+    for (i = 0; i < nargs; i++)
+    {
+        int quote = 0;
+        int argLen = strlen(args[i]);
+
+        if (NULL != strchr(args[i], ' '))
+        {
+            quote = 1;
+            argLen += 2;
+        }
+
+        if (0 < i)
+            ++argLen;
+
+        if (cmdPos + argLen >= cmdLen)
+        {
+            do
+            {
+                cmdLen += cmdLen;
+            }
+            while (cmdPos + argLen >= cmdLen);
+            cmd = Safe_realloc(cmd, cmdLen);
+        }
+
+        if (0 < i)
+        {
+            cmd[cmdPos++] = ' ';
+            --argLen;
+        }
+
+        if (quote)
+        {
+            cmd[cmdPos++] = '"';
+            --argLen;
+        }
+
+        memcpy(&cmd[cmdPos], args[i], argLen);
+        cmdPos += argLen;
+
+        if (quote)
+            cmd[cmdPos++] = '"';
+    }
+
+    cmd[cmdPos] = '\0';
+
+    return cmd;
+}
+
+static PROCESS_INFORMATION *execSimulator(char **args, int nargs)
+{
+    STARTUPINFO si;
+    static PROCESS_INFORMATION pi;
+    char *cmdLine = argsToCmdLine(args, nargs);
+
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+    memset(&pi, 0, sizeof(pi));
+
+    // Start the child process.
+    if (!CreateProcess(NULL,   // No module name (use command line)
+        cmdLine, // Command line
+        NULL,           // Process handle not inheritable
+        NULL,           // Thread handle not inheritable
+        FALSE,          // Set handle inheritance to FALSE
+        0,              // No creation flags
+        NULL,           // Use parent's environment block
+        NULL,           // Use parent's starting directory
+        &si,            // Pointer to STARTUPINFO structure
+        &pi)            // Pointer to PROCESS_INFORMATION structure
+    )
+    {
+        Safe_free(cmdLine);
+        printf( "CreateProcess failed (%d).\n", GetLastError() );
+        return NULL;
+    }
+
+    Safe_free(cmdLine);
+    return &pi;
+}
+
 void openSimulator (char **args, int nargs)
 {
-    struct sockaddr_in sin;     
+    struct sockaddr_in sin;
     int retry = 0;
-    int i ;
-    Dprintf(D_simi, ("simi: openSimulator\n"));
+    int i;
+    int fh;
+
+    init_winsock();
 
+    Dprintf(D_simi, ("simi: openSimulator\n"));
+#ifdef SDCDB_DEBUG
+    if (D_simi & sdcdbDebug)
+    {
+        printf("simi: openSimulator: ");
+        for (i=0; i < nargs; i++ )
+        {
+            printf("arg%d: %s ",i,args[i]);
+        }
+        printf("\n");
+    }
+#endif
     invalidateCache(XMEM_CACHE);
     invalidateCache(IMEM_CACHE);
     invalidateCache(SREG_CACHE);
-    
+    invalidateCache(CMEM_CACHE);
+
+    if (INVALID_SOCKET == (sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0))) {
+        fprintf(stderr, "cannot create socket: %d\n", WSAGetLastError());
+        exit(1);
+    }
+
+    memset(&sin,0,sizeof(sin));
+    sin.sin_family = AF_INET;
+    sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sin.sin_port = htons(9756);
+
  try_connect:
-    sock = socket(AF_INET,SOCK_STREAM,0);
-    
+    /* connect to the simulator */
+    if (SOCKET_ERROR == connect(sock, (struct sockaddr *)&sin, sizeof(sin)))
+    {
+        /* if failed then wait 1 second & try again
+           do this for 10 secs only */
+        if (retry < 10)
+        {
+            if ( !retry )
+                simPid = execSimulator(args, nargs);
+            retry ++;
+            Sleep(1000);
+            goto try_connect;
+        }
+        perror("connect failed :");
+        exit(1);
+    }
+
+    fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
+    if (-1 == fh)
+    {
+        perror("cannot _open_osfhandle");
+        exit(1);
+    }
+
+    /* go the socket now turn it into a file handle */
+    if (!(simin = fdopen(fh, "r")))
+    {
+        perror("cannot open socket for read");
+        exit(1);
+    }
+
+    fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
+    if (-1 == fh)
+    {
+        perror("cannot _open_osfhandle");
+        exit(1);
+    }
+
+    if (!(simout = fdopen(fh, "w")))
+    {
+        perror("cannot open socket for write");
+        exit(1);
+    }
+    /* now that we have opened, wait for the prompt */
+    waitForSim(200, NULL);
+    simactive = 1;
+}
+#else
+static int execSimulator(char **args, int nargs)
+{
+    if ((simPid = fork()))
+    {
+        Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
+    }
+    else
+    {
+        /* we are in the child process : start the simulator */
+        signal(SIGINT , SIG_IGN );
+        signal(SIGABRT, SIG_IGN );
+        signal(SIGHUP , SIG_IGN );
+        signal(SIGCHLD, SIG_IGN );
+
+        if (execvp(args[0],args) < 0)
+        {
+            perror("cannot exec simulator");
+            exit(1);
+        }
+    }
+    return simPid;
+}
+
+void openSimulator (char **args, int nargs)
+{
+    struct sockaddr_in sin;
+    int retry = 0;
+    int i;
+    Dprintf(D_simi, ("simi: openSimulator\n"));
+#ifdef SDCDB_DEBUG
+    if (D_simi & sdcdbDebug)
+    {
+        printf("simi: openSimulator: ");
+        for (i=0; i < nargs; i++ )
+        {
+            printf("arg%d: %s ",i,args[i]);
+        }
+        printf("\n");
+    }
+#endif
+    invalidateCache(XMEM_CACHE);
+    invalidateCache(IMEM_CACHE);
+    invalidateCache(SREG_CACHE);
+    invalidateCache(CMEM_CACHE);
+
+    if ((sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
+    {
+        perror("cannot create socket");
+        exit(1);
+    }
+
     memset(&sin,0,sizeof(sin));
     sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
     sin.sin_port = htons(9756);
-    
+
+ try_connect:
     /* connect to the simulator */
-    if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0) {
-       /* if failed then wait 1 second & try again
-          do this for 10 secs only */
-       if (retry < 10) {
-        if ( !retry )
+    if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
+    {
+        /* if failed then wait 1 second & try again
+           do this for 10 secs only */
+        if (retry < 10)
         {
-            /* fork and start the simulator as a subprocess */
-            if ((simPid = fork())) {
-                Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
-            }
-            else {
-                /* we are in the child process : start the simulator */
-                signal(SIGHUP , SIG_IGN );
-                signal(SIGINT , SIG_IGN );
-                signal(SIGABRT, SIG_IGN );
-                signal(SIGCHLD, SIG_IGN );
-
-                if (execvp(args[0],args) < 0) {
-                    perror("cannot exec simulator");
-                    exit(1);
-                }
+            if ( !retry )
+            {
+                simPid = execSimulator(args, nargs);
             }
+            retry ++;
+            sleep (1);
+            goto try_connect;
         }
-           retry ++;
-        sleep (1);
-           goto try_connect;
-       }
-       perror("connect failed :");
-       exit(1);
+        perror("connect failed :");
+        exit(1);
     }
     /* go the socket now turn it into a file handle */
-    if (!(simin = fdopen(sock,"r"))) {
-       fprintf(stderr,"cannot open socket for read\n");
-       exit(1);
+    if (!(simin = fdopen(sock,"r")))
+    {
+        fprintf(stderr,"cannot open socket for read\n");
+        exit(1);
     }
 
-    if (!(simout = fdopen(sock,"w"))) {
-       fprintf(stderr,"cannot open socket for write\n");
-       exit(1);
+    if (!(simout = fdopen(sock,"w")))
+    {
+        fprintf(stderr,"cannot open socket for write\n");
+        exit(1);
     }
-
     /* now that we have opened, wait for the prompt */
     waitForSim(200,NULL);
     simactive = 1;
 }
+#endif
+
 /*-----------------------------------------------------------------*/
 /* simResponse - returns buffer to simulator's response            */
 /*-----------------------------------------------------------------*/
-char *simResponse()
+char *simResponse(void)
 {
     return simibuff;
 }
@@ -216,7 +457,7 @@ char *simResponse()
 /*-----------------------------------------------------------------*/
 void sendSim(char *s)
 {
-    if ( ! simout ) 
+    if ( ! simout )
         return;
 
     Dprintf(D_simi, ("simi: sendSim-->%s", s));  // s has LF at end already
@@ -225,7 +466,7 @@ void sendSim(char *s)
 }
 
 
-static int getMemString(char *buffer, char wrflag, 
+static int getMemString(char *buffer, char wrflag,
                         unsigned int *addr, char mem, int size )
 {
     int cachenr = NMEM_CACHE;
@@ -238,18 +479,20 @@ static int getMemString(char *buffer, char wrflag,
         cmd = "dump";
     buffer[0] = '\0' ;
 
-    switch (mem) 
+    switch (mem)
     {
         case 'A': /* External stack */
         case 'F': /* External ram */
+       case 'P': /* Pdata space */
             prefix = "xram";
             cachenr = XMEM_CACHE;
             break;
         case 'C': /* Code */
         case 'D': /* Code / static segment */
             prefix = "rom";
+           cachenr = CMEM_CACHE;
             break;
-        case 'B': /* Internal stack */  
+        case 'B': /* Internal stack */
         case 'E': /* Internal ram (lower 128) bytes */
         case 'G': /* Internal ram */
             prefix = "iram";
@@ -269,14 +512,14 @@ static int getMemString(char *buffer, char wrflag,
             prefix = "sfr" ;
             cachenr = SREG_CACHE;
             break;
-        case 'R': /* Register space */ 
+        case 'R': /* Register space */
             prefix = "iram";
             /* get register bank */
-            cachenr = simGetValue (0xd0,'I',1); 
+            cachenr = simGetValue (0xd0,'I',1);
             *addr  += cachenr & 0x18 ;
             cachenr = IMEM_CACHE;
             break;
-        default: 
+        default:
         case 'Z': /* undefined space code */
             return cachenr;
     }
@@ -287,6 +530,25 @@ static int getMemString(char *buffer, char wrflag,
     return cachenr;
 }
 
+void simSetPC( unsigned int addr )
+{
+    char buffer[40];
+    sprintf(buffer,"pc %d\n", addr);
+    sendSim(buffer);
+    waitForSim(100,NULL);
+    simResponse();
+}
+
+unsigned int simGetPC(void)
+{
+    char *sr;
+    sendSim("pc\n");
+    waitForSim(100,NULL);
+    simResponse();
+    sr = simResponse();
+    return strtol(sr+3,0,0);
+}
+    
 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
 {
     char cachenr, i;
@@ -304,14 +566,15 @@ int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
     s = buffer + strlen(buffer) -1;
     for ( i = 0 ; i < size ; i++ )
     {
-        sprintf(s," 0x%x", val & 0xff);
+        sprintf(s," 0x%lx", val & 0xff);
         s += strlen(s);
         val >>= 8;
     }
     sprintf(s,"\n");
     sendSim(buffer);
     waitForSim(100,NULL);
-    simResponse();   
+    simResponse();
+    return 0;
 }
 
 
@@ -343,12 +606,12 @@ unsigned long simGetValue (unsigned int addr,char mem, int size)
         resp = simResponse();
 
         /* got the response we need to parse it the response
-           is of the form 
+           is of the form
            [address] [v] [v] [v] ... special case in
            case of bit variables which case it becomes
            [address] [assembler bit address] [v] */
         /* first skip thru white space */
-        while (isspace(*resp)) resp++ ;
+        resp = trim_left(resp);
 
         if (strncmp(resp, "0x",2) == 0)
             resp += 2;
@@ -356,28 +619,28 @@ unsigned long simGetValue (unsigned int addr,char mem, int size)
         /* skip thru the address part */
         while (isxdigit(*resp)) resp++;
 
-    }   
+    }
     /* make the branch for bit variables */
-    if ( cachenr == BIT_CACHE) 
+    if ( cachenr == BIT_CACHE)
     {
         /* skip until newline */
         while (*resp && *resp != '\n' ) resp++ ;
         if ( *--resp != '0' )
             b[0] = 1;
     }
-    else 
-    {  
-        for (i = 0 ; i < size ; i++ ) 
+    else
+    {
+        for (i = 0 ; i < size ; i++ )
         {
             /* skip white space */
-            while (isspace(*resp)) resp++ ;
-           
+            resp = trim_left(resp);
+
             b[i] = strtol(resp,&resp,16);
         }
     }
 
     return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
-       
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -411,8 +674,8 @@ void simLoadFile (char *s)
 {
     char buff[128];
 
-    sprintf(buff,"l \"%s\"\n",s);
-    printf(buff);
+    sprintf(buff,"file \"%s\"\n",s);
+    printf("%s",buff);
     sendSim(buff);
     waitForSim(500,NULL);
 }
@@ -423,7 +686,7 @@ void simLoadFile (char *s)
 unsigned int simGoTillBp ( unsigned int gaddr)
 {
     char *sr;
-    unsigned addr ; 
+    unsigned addr ;
     char *sfmt;
     int wait_ms = 1000;
 
@@ -431,36 +694,38 @@ unsigned int simGoTillBp ( unsigned int gaddr)
     invalidateCache(IMEM_CACHE);
     invalidateCache(SREG_CACHE);
     if (gaddr == 0) {
-      /* initial start, start & stop from address 0 */
-      //char buf[20];
-
-         // this program is setting up a bunch of breakpoints automatically
-         // at key places.  Like at startup & main() and other function
-         // entry points.  So we don't need to setup one here..
-      //sendSim("break 0x0\n");
-      //sleep(1);
-      //waitForSim();
-
-      sendSim("run 0x0\n");
-    } else     if (gaddr == -1) { /* resume */
-      sendSim ("run\n");
-      wait_ms = 100;
+        /* initial start, start & stop from address 0 */
+        //char buf[20];
+
+           // this program is setting up a bunch of breakpoints automatically
+           // at key places.  Like at startup & main() and other function
+           // entry points.  So we don't need to setup one here..
+        //sendSim("break 0x0\n");
+        //sleep(1);
+        //waitForSim();
+
+        sendSim("reset\n");
+        waitForSim(wait_ms, NULL);
+        sendSim("run 0x0\n");
+    } else      if (gaddr == -1) { /* resume */
+        sendSim ("run\n");
+        wait_ms = 100;
     }
-    else       if (gaddr == 1 ) { /* nexti or next */
-      sendSim ("next\n");
-      wait_ms = 100;
+    else        if (gaddr == 1 ) { /* nexti or next */
+        sendSim ("next\n");
+        wait_ms = 100;
     }
-    else       if (gaddr == 2 ) { /* stepi or step */
-      sendSim ("step\n");
-      wait_ms = 100;
+    else        if (gaddr == 2 ) { /* stepi or step */
+        sendSim ("step\n");
+        wait_ms = 100;
     }
-    else  { 
-      printf("Error, simGoTillBp > 0!\n");
-      exit(1);
+    else  {
+        printf("Error, simGoTillBp > 0!\n");
+        exit(1);
     }
 
     waitForSim(wait_ms, NULL);
-    
+
     /* get the simulator response */
     sr = simResponse();
     /* check for errors */
@@ -477,10 +742,16 @@ unsigned int simGoTillBp ( unsigned int gaddr)
         sr++ ;
     }
 
+    nointerrupt = 1;
+    /* get answer of stop command */
+    if ( userinterrupt )
+        waitForSim(wait_ms, NULL);
+
     /* better solution: ask pc */
     sendSim ("pc\n");
     waitForSim(100, NULL);
     sr = simResponse();
+    nointerrupt = 0;
 
     gaddr = strtol(sr+3,0,0);
     return gaddr;
@@ -489,11 +760,12 @@ unsigned int simGoTillBp ( unsigned int gaddr)
 /*-----------------------------------------------------------------*/
 /* simReset - reset the simulator                                  */
 /*-----------------------------------------------------------------*/
-void simReset ()
+void simReset (void)
 {
     invalidateCache(XMEM_CACHE);
     invalidateCache(IMEM_CACHE);
     invalidateCache(SREG_CACHE);
+    invalidateCache(CMEM_CACHE);
     sendSim("res\n");
     waitForSim(100,NULL);
 }
@@ -502,21 +774,34 @@ void simReset ()
 /*-----------------------------------------------------------------*/
 /* closeSimulator - close connection to simulator                  */
 /*-----------------------------------------------------------------*/
-void closeSimulator ()
+void closeSimulator (void)
 {
+#ifdef _WIN32
+    if ( ! simin || ! simout || INVALID_SOCKET == sock )
+#else
     if ( ! simin || ! simout || sock == -1 )
+#endif
     {
         simactive = 0;
         return;
     }
+    simactive = 0;
     sendSim("quit\n");
     fclose (simin);
     fclose (simout);
-    shutdown(sock,2);   
-    close(sock);    
+    shutdown(sock,2);
+#ifdef _WIN32
+    closesocket(sock);
+    sock = -1;
+    if (NULL != simPid)
+        TerminateProcess(simPid->hProcess, 0);
+    // Close process and thread handles.
+    CloseHandle(simPid->hProcess);
+    CloseHandle(simPid->hThread);
+#else
+    close(sock);
     sock = -1;
     if ( simPid > 0 )
         kill (simPid,SIGKILL);
+#endif
 }
-
-