summaryrefslogtreecommitdiff
path: root/sim/arm/kid.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/arm/kid.c')
-rw-r--r--sim/arm/kid.c510
1 files changed, 510 insertions, 0 deletions
diff --git a/sim/arm/kid.c b/sim/arm/kid.c
new file mode 100644
index 00000000000..10e3f35821e
--- /dev/null
+++ b/sim/arm/kid.c
@@ -0,0 +1,510 @@
+/* kid.c -- ARMulator RDP/RDI interface: 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 child process continues here... */
+/* It waits on a pipe from the parent and translates the RDP */
+/* messages into RDI calls to the ARMulator passing RDP replies */
+/* back up a pipe to the parent. */
+/*****************************************************************/
+
+#include <sys/types.h>
+#include <signal.h>
+
+#include "armdefs.h"
+#include "dbg_conf.h"
+#include "dbg_hif.h"
+#include "dbg_rdi.h"
+#include "gdbhost.h"
+#include "communicate.h"
+
+/* The pipes between the two processes */
+extern int mumkid[2];
+extern int kidmum[2];
+
+/* The maximum number of file descriptors */
+extern int nfds;
+
+/* The machine name */
+#define MAXHOSTNAMELENGTH 64
+extern char localhost[MAXHOSTNAMELENGTH + 1];
+
+/* The socket number */
+extern unsigned int socketnumber;
+
+/* RDI interface */
+extern const struct RDIProcVec armul_rdi;
+
+static int MYrdp_level = 0;
+
+static int rdi_state = 0;
+
+/**************************************************************/
+/* Signal handler that terminates excecution in the ARMulator */
+/**************************************************************/
+void kid_handlesignal(int sig) {
+#ifdef DEBUG
+ fprintf(stderr, "Terminate ARMulator excecution\n");
+#endif
+ if (sig != SIGUSR1) {
+ fprintf(stderr, "Unsupported signal.\n");
+ return;
+ }
+ armul_rdi.info(RDISignal_Stop, (unsigned long *) 0, (unsigned long *) 0);
+}
+
+/********************************************************************/
+/* Waits on a pipe from the socket demon for RDP and */
+/* acts as an RDP to RDI interpreter on the front of the ARMulator. */
+/********************************************************************/
+void kid() {
+ char *p, *q;
+ int i, j, k;
+ long outofthebag;
+ unsigned char c, d, message;
+ ARMword x, y, z;
+ struct sigaction action;
+ PointHandle point;
+ Dbg_ConfigBlock config;
+ Dbg_HostosInterface hostif;
+ struct Dbg_MCState *MCState;
+ char command_line[256];
+ struct fd_set readfds;
+
+ /* Setup a signal handler for SIGUSR1 */
+ action.sa_handler = kid_handlesignal;
+ action.sa_mask = 0;
+ action.sa_flags = 0;
+
+ sigaction(SIGUSR1, &action, (struct sigaction *) 0);
+
+ while (1)
+ {
+ /* Wait for ever */
+ FD_ZERO(&readfds);
+ FD_SET(mumkid[0], &readfds);
+
+ i = select(nfds, &readfds,
+ (fd_set *) 0,
+ (fd_set *) 0,
+ (struct timeval *) 0);
+
+ if (i < 0) {
+ perror("select");
+ }
+
+ if (read(mumkid[0], &message, 1) < 1) {
+ perror("read");
+ }
+
+ switch (message) {
+ case RDP_Start :
+ /* Open and/or Initialise */
+ BAG_newbag();
+
+ MYread_char(mumkid[0], &c); /* type */
+ MYread_word(mumkid[0], &x); /* memorysize */
+ if (c & 0x2) MYread_char(mumkid[0], &d); /* speed */
+ config.processor = 0;
+ config.memorysize = x;
+ config.bytesex = (c & 0x4) ? RDISex_Big : RDISex_Little;
+ if (c & 0x8) config.bytesex = RDISex_DontCare;
+
+ hostif.dbgprint = myprint;
+ hostif.dbgpause = mypause;
+ hostif.dbgarg = stdout;
+ hostif.writec = mywritec;
+ hostif.readc = myreadc;
+ hostif.write = mywrite;
+ hostif.gets = mygets;
+ hostif.reset = mypause; /* do nothing */
+ hostif.resetarg = "Do I love resetting or what!\n";
+
+ if (rdi_state)
+ {
+ /* we have restarted, so kill off the existing run. */
+ /* armul_rdi.close(); */
+ }
+ i = armul_rdi.open(c & 0x3, &config, &hostif, MCState);
+ rdi_state = 1;
+
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+
+ x = ~0x4;
+ armul_rdi.info(RDIVector_Catch, &x, 0);
+
+ break;
+
+ case RDP_End :
+ /* Close and Finalise */
+ i = armul_rdi.close();
+ rdi_state = 0;
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_Read :
+ /* Read Memory Address */
+ MYread_word(mumkid[0], &x); /* address */
+ MYread_word(mumkid[0], &y); /* nbytes */
+ p = (char *) malloc(y);
+ i = armul_rdi.read(x, p, (unsigned *) &y);
+ MYwrite_char(kidmum[1], RDP_Return);
+ for (k = 0; k < y; k++)
+ MYwrite_char(kidmum[1], p[k]);
+ free(p);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ if (i)
+ MYwrite_word(kidmum[1], y); /* number of bytes sent without error */
+ break;
+
+ case RDP_Write :
+ /* Write Memory Address */
+ MYread_word(mumkid[0], &x); /* address */
+ MYread_word(mumkid[0], &y); /* nbytes */
+ p = (char *) malloc(y);
+ for (k = 0; k < y; k++)
+ MYread_char(mumkid[0], &p[k]);
+ i = armul_rdi.write(p, x, (unsigned *) &y);
+ free(p);
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ if (i)
+ MYwrite_word(kidmum[1], y); /* number of bytes sent without error */
+ break;
+
+ case RDP_CPUread :
+ /* Read CPU State */
+ MYread_char(mumkid[0], &c); /* mode */
+ MYread_word(mumkid[0], &x); /* mask */
+ p = (char *) malloc(4 * RDINumCPURegs);
+ i = armul_rdi.CPUread(c, x, (ARMword *) p);
+ MYwrite_char(kidmum[1], RDP_Return);
+ for (k = 1, j = 0; k != 0x80000000; k *= 2)
+ if (k & x) MYwrite_word(kidmum[1], ((ARMword *) p)[j++]);
+ free(p);
+ if (i) MYwrite_char(kidmum[1], (unsigned char) j);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_CPUwrite :
+ /* Write CPU State */
+ MYread_char(mumkid[0], &c); /* mode */
+ MYread_word(mumkid[0], &x); /* mask */
+
+ p = (char *) malloc(4 * RDINumCPURegs);
+ for (k = 1, j = 0; k != 0x80000000; k *= 2)
+ if (k & x) MYread_word(mumkid[0], &(((ARMword *) p)[j++]));
+ i = armul_rdi.CPUwrite(c, x, (ARMword *) p);
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ free(p);
+ break;
+
+ case RDP_CPread :
+ /* Read Co-Processor State */
+ MYread_char(mumkid[0], &c); /* CPnum */
+ MYread_word(mumkid[0], &x); /* mask */
+ p = q = (char *) malloc(16 * RDINumCPRegs);
+ i = armul_rdi.CPread(c, x, (ARMword *) p);
+ MYwrite_char(kidmum[1], RDP_Return);
+ for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
+ if (k & x) {
+ if ((c == 1 || c == 2) && k <= 128) {
+ MYwrite_FPword(kidmum[1], q);
+ q += 16;
+ }
+ else {
+ MYwrite_word(kidmum[1], *q);
+ q += 4;
+ }
+ }
+ free(p);
+ if (i) MYwrite_char(kidmum[1], (unsigned char) j);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_CPwrite :
+ /* Write Co-Processor State */
+ MYread_char(mumkid[0], &c); /* CPnum */
+ MYread_word(mumkid[0], &x); /* mask */
+ p = q = (char *) malloc(16 * RDINumCPURegs);
+ for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
+ if (k & x) {
+ if ((c == 1 || c == 2) && k <= 128) {
+ MYread_FPword(kidmum[1], q);
+ q += 16;
+ }
+ else {
+ MYread_word(mumkid[0], (ARMword *) q);
+ q += 4;
+ }
+ }
+ i = armul_rdi.CPwrite(c, x, (ARMword *) p);
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ free(p);
+ break;
+
+ case RDP_SetBreak :
+ /* Set Breakpoint */
+ MYread_word(mumkid[0], &x); /* address */
+ MYread_char(mumkid[0], &c); /* type */
+ if ((c & 0xf) >= 5) MYread_word(mumkid[0], &y); /* bound */
+ i = armul_rdi.setbreak(x, c, y, &point);
+ if (!MYrdp_level) BAG_putpair((long) x, (long) point);
+ MYwrite_char(kidmum[1], RDP_Return);
+ if (MYrdp_level) MYwrite_word(kidmum[1], point);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_ClearBreak :
+ /* Clear Breakpoint */
+ MYread_word(mumkid[0], &point); /* PointHandle */
+ if (!MYrdp_level) {
+ BAG_getsecond((long) point, &outofthebag); /* swap pointhandle for address */
+ BAG_killpair_byfirst(outofthebag);
+ point = outofthebag;
+ }
+ i = armul_rdi.clearbreak(point);
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_SetWatch :
+ /* Set Watchpoint */
+ MYread_word(mumkid[0], &x); /* address */
+ MYread_char(mumkid[0], &c); /* type */
+ MYread_char(mumkid[0], &d); /* datatype */
+ if ((c & 0xf) >= 5) MYread_word(mumkid[0], &y); /* bound */
+ i = armul_rdi.setwatch(x, c, d, y, &point);
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_word(kidmum[1], point);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_ClearWatch :
+ /* Clear Watchpoint */
+ MYread_word(mumkid[0], &point); /* PointHandle */
+ i = armul_rdi.clearwatch(point);
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_Execute :
+ /* Excecute */
+
+ MYread_char(mumkid[0], &c); /* return */
+
+#ifdef DEBUG
+ fprintf(stderr, "Starting execution\n");
+#endif
+ i = armul_rdi.execute(&point);
+#ifdef DEBUG
+ fprintf(stderr, "Completed execution\n");
+#endif
+ MYwrite_char(kidmum[1], RDP_Return);
+ if (c & 0x80) MYwrite_word(kidmum[1], point);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_Step :
+ /* Step */
+ MYread_char(mumkid[0], &c); /* return */
+ MYread_word(mumkid[0], &x); /* ninstr */
+ point = 0x87654321;
+ i = armul_rdi.step(x, &point);
+ MYwrite_char(kidmum[1], RDP_Return);
+ if (c & 0x80) MYwrite_word(kidmum[1], point);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ break;
+
+ case RDP_Info:
+ /* Info */
+ MYread_word (mumkid[0], &x);
+ switch (x)
+ {
+ case RDIInfo_Target:
+ i = armul_rdi.info (RDIInfo_Target, &y, &z);
+ MYwrite_char (kidmum[1], RDP_Return);
+ MYwrite_word (kidmum[1], y); /* Loads of info... */
+ MYwrite_word (kidmum[1], z); /* Model */
+ MYwrite_char (kidmum[1], (unsigned char) i);
+ break;
+
+ case RDISet_RDILevel:
+ MYread_word (mumkid[0], &x); /* arg1, debug level */
+ i = armul_rdi.info (RDISet_RDILevel, &x, 0);
+ if (i == RDIError_NoError)
+ MYrdp_level = x;
+ MYwrite_char (kidmum[1], RDP_Return);
+ MYwrite_char (kidmum[1], (unsigned char) i);
+ break;
+
+ case RDISet_Cmdline:
+ for (p = command_line; MYread_char (mumkid[0], p), *p; p++)
+ ; /* String */
+ i = armul_rdi.info (RDISet_Cmdline,
+ (unsigned long *) command_line, 0);
+ MYwrite_char (kidmum[1], RDP_Return);
+ MYwrite_char (kidmum[1], (unsigned char) i);
+ break;
+
+ case RDIInfo_Step:
+ i = armul_rdi.info (RDIInfo_Step, &x, 0);
+ MYwrite_char (kidmum[1], RDP_Return);
+ MYwrite_word (kidmum[1], x);
+ MYwrite_char (kidmum[1], (unsigned char) i);
+ break;
+
+ case RDIVector_Catch:
+ MYread_word (mumkid[0], &x);
+ i = armul_rdi.info (RDIVector_Catch, &x, 0);
+ MYwrite_char (kidmum[1], RDP_Return);
+ MYwrite_char (kidmum[1], i);
+ break;
+
+ case RDIInfo_Points:
+ i = armul_rdi.info (RDIInfo_Points, &x, 0);
+ MYwrite_char (kidmum[1], RDP_Return);
+ MYwrite_word (kidmum[1], x);
+ MYwrite_char (kidmum[1], (unsigned char) i);
+ break;
+
+ default:
+ fprintf (stderr, "Unsupported info code %d\n", x);
+ break;
+ }
+ break;
+
+ case RDP_OSOpReply:
+ /* OS Operation Reply */
+ MYwrite_char (kidmum[1], RDP_Fatal);
+ break;
+
+ case RDP_Reset:
+ /* Reset */
+ for (i = 0; i < 50; i++)
+ MYwrite_char(kidmum[1], RDP_Reset);
+ p = (char *) malloc(MAXHOSTNAMELENGTH + 5 + 20);
+ sprintf(p, "Running on %s:%d\n", localhost, socketnumber);
+ MYwrite_string(kidmum[1], p);
+ free(p);
+
+ break;
+ default:
+ fprintf (stderr, "Oh dear: Something is seriously wrong :-(\n");
+ /* Hmm.. bad RDP operation */
+ break;
+ }
+ }
+}
+
+
+/* Handles memory read operations until an OS Operation Reply Message is */
+/* encounterd. It then returns the byte info value (0, 1, or 2) and fills */
+/* in 'putinr0' with the data if appropriate. */
+int wait_for_osreply(ARMword *reply)
+{
+ char *p, *q;
+ int i, j, k;
+ unsigned char c, d, message;
+ ARMword x, y, z;
+ struct sigaction action;
+ PointHandle point;
+ Dbg_ConfigBlock config;
+ Dbg_HostosInterface hostif;
+ struct Dbg_MCState *MCState;
+ char command_line[256];
+ struct fd_set readfds;
+
+#ifdef DEBUG
+ fprintf(stderr, "wait_for_osreply ().\n");
+#endif
+
+ /* Setup a signal handler for SIGUSR1 */
+ action.sa_handler = kid_handlesignal;
+ action.sa_mask = 0;
+ action.sa_flags = 0;
+
+ sigaction(SIGUSR1, &action, (struct sigaction *) 0);
+
+ while (1)
+ {
+ /* Wait for ever */
+ FD_ZERO(&readfds);
+ FD_SET(mumkid[0], &readfds);
+
+ i = select(nfds, &readfds,
+ (fd_set *) 0,
+ (fd_set *) 0,
+ (struct timeval *) 0);
+
+ if (i < 0) {
+ perror("select");
+ }
+
+ if (read(mumkid[0], &message, 1) < 1) {
+ perror("read");
+ }
+
+ switch (message) {
+ case RDP_Read :
+ /* Read Memory Address */
+ MYread_word(mumkid[0], &x); /* address */
+ MYread_word(mumkid[0], &y); /* nbytes */
+ p = (char *) malloc(y);
+ i = armul_rdi.read(x, p, (unsigned *) &y);
+ MYwrite_char(kidmum[1], RDP_Return);
+ for (k = 0; k < y; k++)
+ MYwrite_char(kidmum[1], p[k]);
+ free(p);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ if (i)
+ MYwrite_word(kidmum[1], y); /* number of bytes sent without error */
+ break;
+
+ case RDP_Write :
+ /* Write Memory Address */
+ MYread_word(mumkid[0], &x); /* address */
+ MYread_word(mumkid[0], &y); /* nbytes */
+ p = (char *) malloc(y);
+ for (k = 0; k < y; k++)
+ MYread_char(mumkid[0], &p[k]);
+ i = armul_rdi.write(p, x, (unsigned *) &y);
+ free(p);
+ MYwrite_char(kidmum[1], RDP_Return);
+ MYwrite_char(kidmum[1], (unsigned char) i);
+ if (i)
+ MYwrite_word(kidmum[1], y); /* number of bytes sent without error */
+ break;
+
+ case RDP_OSOpReply :
+ /* OS Operation Reply */
+ MYread_char(mumkid[0], &c);
+ if (c == 1) MYread_char(mumkid[0], (char *) reply);
+ if (c == 2) MYread_word(mumkid[0], reply);
+ return c;
+ break;
+
+ default :
+ fprintf(stderr, "HELP! Unaccounted-for message during OS request. \n");
+ MYwrite_char(kidmum[1], RDP_Fatal);
+ }
+ }
+}