blob: 159e8e35b62ed45feeca883e4e69a3fde693094f [file] [log] [blame]
/* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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);
}
}
}