1/*  parent.c -- ARMulator RDP comms code:  ARM6 Instruction Emulator.
2    Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
17
18/*****************************************************************/
19/* The Parent process continues here...                          */
20/* It waits on the socket and passes on RDP messages down a pipe */
21/* to the ARMulator RDP to RDI interpreter.                      */
22/*****************************************************************/
23
24#include <stdio.h>
25#include <sys/types.h>
26#include <signal.h>
27#include "time.h"
28#include "armdefs.h"
29#include "dbg_rdi.h"
30#include "communicate.h"
31
32/* The socket to the debugger */
33extern int debugsock;
34
35/* The pipes between the two processes */
36extern int mumkid[2];
37extern int kidmum[2];
38
39/* A pipe for handling SWI return values that goes straight from the */
40/* parent to the ARMulator host interface, bypassing the child's RDP */
41/* to RDI interpreter */
42extern int DebuggerARMul[2];
43
44/* The maximum number of file descriptors */
45extern int nfds;
46
47/* The child process id. */
48extern pid_t child;
49
50void
51parent ()
52{
53  int i, j, k;
54  unsigned char message, CPnum, exreturn;
55  ARMword mask, nbytes, messagetype;
56  unsigned char c, d;
57  ARMword x, y;
58  int virgin = 1;
59  struct fd_set readfds;
60
61#ifdef DEBUG
62  fprintf (stderr, "parent ()...\n");
63#endif
64
65panic_error:
66
67  if (!virgin)
68    {
69#ifdef DEBUG
70      fprintf (stderr, "Arghh! What is going on?\n");
71#endif
72      kill (child, SIGHUP);
73      MYwrite_char (debugsock, RDP_Reset);
74    }
75
76  virgin = 0;
77
78  while (1)
79    {
80
81      /* Wait either for the ARMulator or the debugger */
82
83      FD_ZERO (&readfds);
84      FD_SET (kidmum[0], &readfds);	/* Wait for messages from ARMulator */
85      FD_SET (debugsock, &readfds);	/* Wait for messages from debugger */
86
87#ifdef DEBUG
88      fprintf (stderr, "Waiting for ARMulator or debugger... ");
89#endif
90
91      while ((i = select (nfds, &readfds, (fd_set *) 0, (fd_set *) 0, 0)) < 0)
92	{
93	  perror ("select");
94	}
95
96#ifdef DEBUG
97      fprintf (stderr, "(%d/2)", i);
98#endif
99
100      if (FD_ISSET (debugsock, &readfds))
101	{
102#ifdef DEBUG
103	  fprintf (stderr, "->debugger\n");
104#endif
105
106	  /* Inside this rather large if statement with simply pass on a complete
107	     message to the ARMulator.  The reason we need to pass messages on one
108	     at a time is that we have to know whether the message is an OSOpReply
109	     or an info(stop), so that we can take different action in those
110	     cases. */
111
112	  if (MYread_char (debugsock, &message))
113	    goto panic_error;
114
115	  switch (message)
116	    {
117	    case RDP_Start:
118	      /* Open and/or Initialise */
119#ifdef DEBUG
120	      fprintf (stderr, "RDP Open\n");
121#endif
122	      if (MYread_char (debugsock, &c))	/* type */
123		goto panic_error;
124
125	      if (MYread_word (debugsock, &x))	/* memory size */
126		goto panic_error;
127
128	      MYwrite_char (mumkid[1], message);
129	      MYwrite_char (mumkid[1], c);
130	      MYwrite_word (mumkid[1], x);
131	      if (c & 0x2)
132		{
133		  passon (debugsock, mumkid[1], 1);	/* speed */
134		}
135	      break;
136
137	    case RDP_End:
138	      /* Close and Finalise */
139#ifdef DEBUG
140	      fprintf (stderr, "RDP Close\n");
141#endif
142	      MYwrite_char (mumkid[1], message);
143	      break;
144
145	    case RDP_Read:
146	      /* Read Memory Address */
147#ifdef DEBUG
148	      fprintf (stderr, "RDP Read Memory\n");
149#endif
150	      MYwrite_char (mumkid[1], message);
151	      if (passon (debugsock, mumkid[1], 4))
152		goto panic_error;	/* address */
153	      if (MYread_word (debugsock, &nbytes))
154		goto panic_error;	/* nbytes */
155	      MYwrite_word (mumkid[1], nbytes);
156	      break;
157
158	    case RDP_Write:
159	      /* Write Memory Address */
160#ifdef DEBUG
161	      fprintf (stderr, "RDP Write Memory\n");
162#endif
163	      if (MYread_word (debugsock, &x))
164		goto panic_error;	/* address */
165
166	      if (MYread_word (debugsock, &y))
167		goto panic_error;	/* nbytes */
168
169	      MYwrite_char (mumkid[1], message);
170	      MYwrite_word (mumkid[1], x);
171	      MYwrite_word (mumkid[1], y);
172	      passon (debugsock, mumkid[1], y);	/* actual data */
173	      break;
174
175	    case RDP_CPUread:
176	      /* Read CPU State */
177#ifdef DEBUG
178	      fprintf (stderr, "RDP Read CPU\n");
179#endif
180	      if (MYread_char (debugsock, &c))
181		goto panic_error;	/* mode */
182
183	      if (MYread_word (debugsock, &mask))
184		goto panic_error;	/* mask */
185
186	      MYwrite_char (mumkid[1], message);
187	      MYwrite_char (mumkid[1], c);
188	      MYwrite_word (mumkid[1], mask);
189	      break;
190
191	    case RDP_CPUwrite:
192	      /* Write CPU State */
193#ifdef DEBUG
194	      fprintf (stderr, "RDP Write CPU\n");
195#endif
196	      if (MYread_char (debugsock, &c))
197		goto panic_error;	/* mode */
198
199	      if (MYread_word (debugsock, &x))
200		goto panic_error;	/* mask */
201
202	      MYwrite_char (mumkid[1], message);
203	      MYwrite_char (mumkid[1], c);
204	      MYwrite_word (mumkid[1], x);
205	      for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
206		if ((k & x) && passon (debugsock, mumkid[1], 4))
207		  goto panic_error;
208	      break;
209
210	    case RDP_CPread:
211	      /* Read Co-Processor State */
212#ifdef DEBUG
213	      fprintf (stderr, "RDP Read CP state\n");
214#endif
215	      if (MYread_char (debugsock, &CPnum))
216		goto panic_error;
217
218	      if (MYread_word (debugsock, &mask))
219		goto panic_error;
220
221	      MYwrite_char (mumkid[1], message);
222	      MYwrite_char (mumkid[1], CPnum);
223	      MYwrite_word (mumkid[1], mask);
224	      break;
225
226	    case RDP_CPwrite:
227	      /* Write Co-Processor State */
228#ifdef DEBUG
229	      fprintf (stderr, "RDP Write CP state\n");
230#endif
231	      if (MYread_char (debugsock, &CPnum))
232		goto panic_error;
233
234	      if (MYread_word (debugsock, &mask))
235		goto panic_error;
236
237	      MYwrite_char (mumkid[1], message);
238	      MYwrite_char (mumkid[1], c);
239	      MYwrite_char (mumkid[1], x);
240	      for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
241		if (k & x)
242		  {
243		    if ((c == 1 || c == 2) && k <= 128)
244		      {
245			/* FP register = 12 bytes + 4 bytes format */
246			if (passon (debugsock, mumkid[1], 16))
247			  goto panic_error;
248		      }
249		    else
250		      {
251			/* Normal register = 4 bytes */
252			if (passon (debugsock, mumkid[1], 4))
253			  goto panic_error;
254		      }
255		  }
256	      break;
257
258	    case RDP_SetBreak:
259	      /* Set Breakpoint */
260#ifdef DEBUG
261	      fprintf (stderr, "RDP Set Breakpoint\n");
262#endif
263	      if (MYread_word (debugsock, &x))
264		goto panic_error;	/* address */
265
266	      if (MYread_char (debugsock, &c))
267		goto panic_error;	/* type */
268
269	      MYwrite_char (mumkid[1], message);
270	      MYwrite_word (mumkid[1], x);
271	      MYwrite_char (mumkid[1], c);
272	      if (((c & 0xf) >= 5) && passon (debugsock, mumkid[1], 4))
273		goto panic_error;	/* bound */
274	      break;
275
276	    case RDP_ClearBreak:
277	      /* Clear Breakpoint */
278#ifdef DEBUG
279	      fprintf (stderr, "RDP Clear Breakpoint\n");
280#endif
281	      MYwrite_char (mumkid[1], message);
282	      if (passon (debugsock, mumkid[1], 4))
283		goto panic_error;	/* point */
284	      break;
285
286	    case RDP_SetWatch:
287	      /* Set Watchpoint */
288#ifdef DEBUG
289	      fprintf (stderr, "RDP Set Watchpoint\n");
290#endif
291	      if (MYread_word (debugsock, &x))
292		goto panic_error;	/* address */
293
294	      if (MYread_char (debugsock, &c))
295		goto panic_error;	/* type */
296
297	      if (MYread_char (debugsock, &d))
298		goto panic_error;	/* datatype */
299
300	      MYwrite_char (mumkid[1], message);
301	      MYwrite_word (mumkid[1], x);
302	      MYwrite_char (mumkid[1], c);
303	      MYwrite_char (mumkid[1], d);
304	      if (((c & 0xf) >= 5) && passon (debugsock, mumkid[1], 4))
305		goto panic_error;	/* bound */
306	      break;
307
308	    case RDP_ClearWatch:
309	      /* Clear Watchpoint */
310#ifdef DEBUG
311	      fprintf (stderr, "RDP Clear Watchpoint\n");
312#endif
313	      MYwrite_char (mumkid[1], message);
314	      if (passon (debugsock, mumkid[1], 4))
315		goto panic_error;	/* point */
316	      break;
317
318	    case RDP_Execute:
319	      /* Excecute */
320#ifdef DEBUG
321	      fprintf (stderr, "RDP Execute\n");
322#endif
323
324	      /* LEAVE THIS ONE 'TIL LATER... */
325	      /* NEED TO WORK THINGS OUT */
326
327	      /* NO ASCYNCHROUS RUNNING */
328
329	      if (MYread_char (debugsock, &c))
330		goto panic_error;	/* return */
331
332	      /* Remember incase bit 7 is set and we have to send back a word */
333	      exreturn = c;
334
335	      MYwrite_char (mumkid[1], message);
336	      MYwrite_char (mumkid[1], c);
337	      break;
338
339	    case RDP_Step:
340	      /* Step */
341#ifdef DEBUG
342	      fprintf (stderr, "RDP Step\n");
343#endif
344
345	      if (MYread_char (debugsock, &c))
346		goto panic_error;	/* return */
347
348	      if (MYread_word (debugsock, &x))
349		goto panic_error;	/* ninstr */
350
351	      MYwrite_char (mumkid[1], message);
352	      MYwrite_char (mumkid[1], c);
353	      MYwrite_word (mumkid[1], x);
354	      break;
355
356	    case RDP_Info:
357	      /* Info */
358#ifdef DEBUG
359	      fprintf (stderr, "RDP Info\n");
360#endif
361	      /* INFO TARGET, SET RDI LEVEL */
362	      if (MYread_word (debugsock, &messagetype))
363		goto panic_error;	/* info */
364
365	      switch (messagetype)
366		{
367		case RDIInfo_Target:
368		  MYwrite_char (mumkid[1], message);
369		  MYwrite_word (mumkid[1], messagetype);
370		  break;
371
372		case RDISet_RDILevel:
373		  MYwrite_char (mumkid[1], message);
374		  MYwrite_word (mumkid[1], messagetype);
375		  if (passon (debugsock, mumkid[1], 1))
376		    goto panic_error;	/* argument */
377		  break;
378
379		case RDISet_Cmdline:
380		  /* Got to pass on a string argument */
381		  MYwrite_char (mumkid[1], message);
382		  MYwrite_word (mumkid[1], messagetype);
383		  do
384		    {
385		      if (MYread_char (debugsock, &c))
386			goto panic_error;
387
388		      MYwrite_char (mumkid[1], c);
389		    }
390		  while (c);
391		  break;
392
393		case RDISignal_Stop:
394		  kill (child, SIGUSR1);
395		  MYwrite_char (debugsock, RDP_Return);
396		  MYwrite_char (debugsock, RDIError_UserInterrupt);
397		  break;
398
399		case RDIVector_Catch:
400		  MYread_word (debugsock, &x);
401		  MYwrite_char (mumkid[1], message);
402		  MYwrite_word (mumkid[1], messagetype);
403		  MYwrite_word (mumkid[1], x);
404		  break;
405
406		case RDIInfo_Step:
407		  MYwrite_char (mumkid[1], message);
408		  MYwrite_word (mumkid[1], messagetype);
409		  break;
410
411		case RDIInfo_Points:
412		  MYwrite_char (mumkid[1], message);
413		  MYwrite_word (mumkid[1], messagetype);
414		  break;
415
416		default:
417		  fprintf (stderr, "Unrecognized RDIInfo request %d\n",
418			   messagetype);
419		  goto panic_error;
420		}
421	      break;
422
423	    case RDP_OSOpReply:
424	      /* OS Operation Reply */
425#ifdef DEBUG
426	      fprintf (stderr, "RDP OS Reply\n");
427#endif
428	      MYwrite_char (mumkid[1], message);
429	      if (MYread_char (debugsock, &message))
430		goto panic_error;
431	      MYwrite_char (mumkid[1], message);
432	      switch (message)
433		{
434		case 0:	/* return value i.e. nothing else. */
435		  break;
436
437		case 1:	/* returns a byte... */
438		  if (MYread_char (debugsock, &c))
439		    goto panic_error;
440
441		  MYwrite_char (mumkid[1], c);
442		  break;
443
444		case 2:	/* returns a word... */
445		  if (MYread_word (debugsock, &x))
446		    goto panic_error;
447
448		  MYwrite_word (mumkid[1], x);
449		  break;
450		}
451	      break;
452
453	    case RDP_Reset:
454	      /* Reset */
455#ifdef DEBUG
456	      fprintf (stderr, "RDP Reset\n");
457#endif
458	      MYwrite_char (mumkid[1], message);
459	      break;
460
461	    default:
462	      /* Hmm.. bad RDP operation */
463	      fprintf (stderr, "RDP Bad RDP request (%d)\n", message);
464	      MYwrite_char (debugsock, RDP_Return);
465	      MYwrite_char (debugsock, RDIError_UnimplementedMessage);
466	      break;
467	    }
468	}
469
470      if (FD_ISSET (kidmum[0], &readfds))
471	{
472#ifdef DEBUG
473	  fprintf (stderr, "->ARMulator\n");
474#endif
475	  /* Anything we get from the ARMulator has to go to the debugger... */
476	  /* It is that simple! */
477
478	  passon (kidmum[0], debugsock, 1);
479	}
480    }
481}
482