diff options
Diffstat (limited to 'sim/arm/parent.c')
-rw-r--r-- | sim/arm/parent.c | 483 |
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); + } + } +} + |