diff options
Diffstat (limited to 'sim/arm/kid.c')
-rw-r--r-- | sim/arm/kid.c | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/sim/arm/kid.c b/sim/arm/kid.c new file mode 100644 index 0000000..7a0a521 --- /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., 675 Mass Ave, Cambridge, MA 02139, 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); + } + } +} |