aboutsummaryrefslogtreecommitdiff
path: root/sim/arm/parent.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/arm/parent.c')
-rw-r--r--sim/arm/parent.c483
1 files changed, 483 insertions, 0 deletions
diff --git a/sim/arm/parent.c b/sim/arm/parent.c
new file mode 100644
index 0000000..21da643
--- /dev/null
+++ b/sim/arm/parent.c
@@ -0,0 +1,483 @@
+/* parent.c -- ARMulator RDP comms code: ARM6 Instruction Emulator.
+ Copyright (C) 1994 Advanced RISC Machines Ltd.
+
+ 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 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*****************************************************************/
+/* The Parent process continues here... */
+/* It waits on the socket and passes on RDP messages down a pipe */
+/* to the ARMulator RDP to RDI interpreter. */
+/*****************************************************************/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include "time.h"
+#include "armdefs.h"
+#include "dbg_rdi.h"
+#include "communicate.h"
+
+/* The socket to the debugger */
+extern int debugsock;
+
+/* The pipes between the two processes */
+extern int mumkid[2];
+extern int kidmum[2];
+
+/* A pipe for handling SWI return values that goes straight from the */
+/* parent to the ARMulator host interface, bypassing the child's RDP */
+/* to RDI interpreter */
+extern int DebuggerARMul[2];
+
+/* The maximum number of file descriptors */
+extern int nfds;
+
+/* The child process id. */
+extern pid_t child;
+
+void
+parent ()
+{
+ int i, j, k;
+ unsigned char message, CPnum, exreturn;
+ ARMword mask, nbytes, messagetype;
+ unsigned char c, d;
+ ARMword x, y;
+ int virgin = 1;
+ struct fd_set readfds;
+
+#ifdef DEBUG
+ fprintf (stderr, "parent ()...\n");
+#endif
+
+ panic_error:
+
+ if (!virgin)
+ {
+#ifdef DEBUG
+ fprintf(stderr, "Arghh! What is going on?\n");
+#endif
+ kill (child, SIGHUP);
+ MYwrite_char(debugsock, RDP_Reset);
+ }
+
+ virgin = 0;
+
+ while (1)
+ {
+
+ /* Wait either for the ARMulator or the debugger */
+
+ FD_ZERO (&readfds);
+ FD_SET (kidmum[0], &readfds); /* Wait for messages from ARMulator */
+ FD_SET (debugsock, &readfds); /* Wait for messages from debugger */
+
+#ifdef DEBUG
+ fprintf (stderr, "Waiting for ARMulator or debugger... ");
+#endif
+
+ while ((i = select (nfds, &readfds, (fd_set *) 0, (fd_set *) 0, 0)) < 0)
+ {
+ perror ("select");
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "(%d/2)", i);
+#endif
+
+ if (FD_ISSET (debugsock, &readfds)) {
+#ifdef DEBUG
+ fprintf (stderr, "->debugger\n");
+#endif
+
+ /* Inside this rather large if statement with simply pass on a complete
+ message to the ARMulator. The reason we need to pass messages on one
+ at a time is that we have to know whether the message is an OSOpReply
+ or an info(stop), so that we can take different action in those
+ cases. */
+
+ if (MYread_char (debugsock, &message))
+ goto panic_error;
+
+ switch (message)
+ {
+ case RDP_Start:
+ /* Open and/or Initialise */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Open\n");
+#endif
+ if (MYread_char(debugsock, &c)) /* type */
+ goto panic_error;
+
+ if (MYread_word(debugsock, &x)) /* memory size */
+ goto panic_error;
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_char (mumkid[1], c);
+ MYwrite_word (mumkid[1], x);
+ if (c & 0x2)
+ {
+ passon (debugsock, mumkid[1], 1); /* speed */
+ }
+ break;
+
+ case RDP_End:
+ /* Close and Finalise */
+#ifdef DEBUG
+ fprintf(stderr, "RDP Close\n");
+#endif
+ MYwrite_char (mumkid[1], message);
+ break;
+
+ case RDP_Read:
+ /* Read Memory Address */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Read Memory\n");
+#endif
+ MYwrite_char (mumkid[1], message);
+ if (passon (debugsock, mumkid[1], 4))
+ goto panic_error; /* address */
+ if (MYread_word(debugsock, &nbytes))
+ goto panic_error; /* nbytes */
+ MYwrite_word (mumkid[1], nbytes);
+ break;
+
+ case RDP_Write :
+ /* Write Memory Address */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Write Memory\n");
+#endif
+ if (MYread_word (debugsock, &x))
+ goto panic_error; /* address */
+
+ if (MYread_word (debugsock, &y))
+ goto panic_error; /* nbytes */
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], x);
+ MYwrite_word (mumkid[1], y);
+ passon (debugsock, mumkid[1], y); /* actual data */
+ break;
+
+ case RDP_CPUread:
+ /* Read CPU State */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Read CPU\n");
+#endif
+ if (MYread_char(debugsock, &c))
+ goto panic_error; /* mode */
+
+ if (MYread_word (debugsock, &mask))
+ goto panic_error; /* mask */
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_char (mumkid[1], c);
+ MYwrite_word (mumkid[1], mask);
+ break;
+
+ case RDP_CPUwrite :
+ /* Write CPU State */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Write CPU\n");
+#endif
+ if (MYread_char (debugsock, &c))
+ goto panic_error; /* mode */
+
+ if (MYread_word (debugsock, &x))
+ goto panic_error; /* mask */
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_char (mumkid[1], c);
+ MYwrite_word (mumkid[1], x);
+ for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
+ if ((k & x)
+ && passon(debugsock, mumkid[1], 4))
+ goto panic_error;
+ break;
+
+ case RDP_CPread:
+ /* Read Co-Processor State */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Read CP state\n");
+#endif
+ if (MYread_char (debugsock, &CPnum))
+ goto panic_error;
+
+ if (MYread_word (debugsock, &mask))
+ goto panic_error;
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_char (mumkid[1], CPnum);
+ MYwrite_word (mumkid[1], mask);
+ break;
+
+ case RDP_CPwrite:
+ /* Write Co-Processor State */
+#ifdef DEBUG
+ fprintf(stderr, "RDP Write CP state\n");
+#endif
+ if (MYread_char (debugsock, &CPnum))
+ goto panic_error;
+
+ if (MYread_word (debugsock, &mask))
+ goto panic_error;
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_char (mumkid[1], c);
+ MYwrite_char (mumkid[1], x);
+ for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
+ if (k & x)
+ {
+ if ((c == 1 || c == 2) && k <= 128)
+ {
+ /* FP register = 12 bytes + 4 bytes format */
+ if (passon(debugsock, mumkid[1], 16))
+ goto panic_error;
+ }
+ else
+ {
+ /* Normal register = 4 bytes */
+ if (passon(debugsock, mumkid[1], 4))
+ goto panic_error;
+ }
+ }
+ break;
+
+ case RDP_SetBreak:
+ /* Set Breakpoint */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Set Breakpoint\n");
+#endif
+ if (MYread_word (debugsock, &x))
+ goto panic_error; /* address */
+
+ if (MYread_char (debugsock, &c))
+ goto panic_error; /* type */
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], x);
+ MYwrite_char (mumkid[1], c);
+ if (((c & 0xf) >= 5)
+ && passon(debugsock, mumkid[1], 4))
+ goto panic_error; /* bound */
+ break;
+
+ case RDP_ClearBreak:
+ /* Clear Breakpoint */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Clear Breakpoint\n");
+#endif
+ MYwrite_char (mumkid[1], message);
+ if (passon (debugsock, mumkid[1], 4))
+ goto panic_error; /* point */
+ break;
+
+ case RDP_SetWatch:
+ /* Set Watchpoint */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Set Watchpoint\n");
+#endif
+ if (MYread_word (debugsock, &x))
+ goto panic_error; /* address */
+
+ if (MYread_char(debugsock, &c))
+ goto panic_error; /* type */
+
+ if (MYread_char (debugsock, &d))
+ goto panic_error; /* datatype */
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], x);
+ MYwrite_char (mumkid[1], c);
+ MYwrite_char (mumkid[1], d);
+ if (((c & 0xf) >= 5)
+ && passon(debugsock, mumkid[1], 4))
+ goto panic_error; /* bound */
+ break;
+
+ case RDP_ClearWatch:
+ /* Clear Watchpoint */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Clear Watchpoint\n");
+#endif
+ MYwrite_char (mumkid[1], message);
+ if (passon (debugsock, mumkid[1], 4))
+ goto panic_error; /* point */
+ break;
+
+ case RDP_Execute:
+ /* Excecute */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Execute\n");
+#endif
+
+ /* LEAVE THIS ONE 'TIL LATER... */
+ /* NEED TO WORK THINGS OUT */
+
+ /* NO ASCYNCHROUS RUNNING */
+
+ if (MYread_char(debugsock, &c))
+ goto panic_error; /* return */
+
+ /* Remember incase bit 7 is set and we have to send back a word */
+ exreturn = c;
+
+ MYwrite_char(mumkid[1], message);
+ MYwrite_char(mumkid[1], c);
+ break;
+
+ case RDP_Step:
+ /* Step */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Step\n");
+#endif
+
+ if (MYread_char(debugsock, &c))
+ goto panic_error; /* return */
+
+ if (MYread_word(debugsock, &x))
+ goto panic_error; /* ninstr */
+
+ MYwrite_char (mumkid[1], message);
+ MYwrite_char (mumkid[1], c);
+ MYwrite_word (mumkid[1], x);
+ break;
+
+ case RDP_Info:
+ /* Info */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Info\n");
+#endif
+ /* INFO TARGET, SET RDI LEVEL */
+ if (MYread_word (debugsock, &messagetype))
+ goto panic_error; /* info */
+
+ switch (messagetype)
+ {
+ case RDIInfo_Target:
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], messagetype);
+ break;
+
+ case RDISet_RDILevel:
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], messagetype);
+ if (passon (debugsock, mumkid[1], 1))
+ goto panic_error; /* argument */
+ break;
+
+ case RDISet_Cmdline:
+ /* Got to pass on a string argument */
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], messagetype);
+ do
+ {
+ if (MYread_char (debugsock, &c))
+ goto panic_error;
+
+ MYwrite_char (mumkid[1], c);
+ } while (c);
+ break;
+
+ case RDISignal_Stop:
+ kill (child, SIGUSR1);
+ MYwrite_char (debugsock, RDP_Return);
+ MYwrite_char (debugsock, RDIError_UserInterrupt);
+ break;
+
+ case RDIVector_Catch:
+ MYread_word (debugsock, &x);
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], messagetype);
+ MYwrite_word (mumkid[1], x);
+ break;
+
+ case RDIInfo_Step:
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], messagetype);
+ break;
+
+ case RDIInfo_Points:
+ MYwrite_char (mumkid[1], message);
+ MYwrite_word (mumkid[1], messagetype);
+ break;
+
+ default:
+ fprintf (stderr, "Unrecognized RDIInfo request %d\n",
+ messagetype);
+ goto panic_error;
+ }
+ break;
+
+ case RDP_OSOpReply:
+ /* OS Operation Reply */
+#ifdef DEBUG
+ fprintf (stderr, "RDP OS Reply\n");
+#endif
+ MYwrite_char (mumkid[1], message);
+ if (MYread_char (debugsock, &message))
+ goto panic_error;
+ MYwrite_char (mumkid[1], message);
+ switch(message)
+ {
+ case 0: /* return value i.e. nothing else.*/
+ break;
+
+ case 1: /* returns a byte... */
+ if (MYread_char(debugsock, &c))
+ goto panic_error;
+
+ MYwrite_char (mumkid[1], c);
+ break;
+
+ case 2: /* returns a word... */
+ if (MYread_word(debugsock, &x))
+ goto panic_error;
+
+ MYwrite_word (mumkid[1], x);
+ break;
+ }
+ break;
+
+ case RDP_Reset:
+ /* Reset */
+#ifdef DEBUG
+ fprintf (stderr, "RDP Reset\n");
+#endif
+ MYwrite_char (mumkid[1], message);
+ break;
+
+ default:
+ /* Hmm.. bad RDP operation */
+ fprintf (stderr, "RDP Bad RDP request (%d)\n", message);
+ MYwrite_char (debugsock, RDP_Return);
+ MYwrite_char (debugsock, RDIError_UnimplementedMessage);
+ break;
+ }
+ }
+
+ if (FD_ISSET (kidmum[0], &readfds))
+ {
+#ifdef DEBUG
+ fprintf (stderr, "->ARMulator\n");
+#endif
+ /* Anything we get from the ARMulator has to go to the debugger... */
+ /* It is that simple! */
+
+ passon (kidmum[0], debugsock, 1);
+ }
+ }
+}
+