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 */
33 extern int debugsock;
34
35 /* The pipes between the two processes */
36 extern int mumkid[2];
37 extern 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 */
42 extern int DebuggerARMul[2];
43
44 /* The maximum number of file descriptors */
45 extern int nfds;
46
47 /* The child process id. */
48 extern pid_t child;
49
50 void
parent()51 parent ()
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
65 panic_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