]>
Commit | Line | Data |
---|---|---|
2494eaf6 SC |
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., 675 Mass Ave, Cambridge, MA 02139, 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 | |
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 | #ifdef DEBUG | |
102 | fprintf (stderr, "->debugger\n"); | |
103 | #endif | |
104 | ||
105 | /* Inside this rather large if statement with simply pass on a complete | |
106 | message to the ARMulator. The reason we need to pass messages on one | |
107 | at a time is that we have to know whether the message is an OSOpReply | |
108 | or an info(stop), so that we can take different action in those | |
109 | cases. */ | |
110 | ||
111 | if (MYread_char (debugsock, &message)) | |
112 | goto panic_error; | |
113 | ||
114 | switch (message) | |
115 | { | |
116 | case RDP_Start: | |
117 | /* Open and/or Initialise */ | |
118 | #ifdef DEBUG | |
119 | fprintf (stderr, "RDP Open\n"); | |
120 | #endif | |
121 | if (MYread_char(debugsock, &c)) /* type */ | |
122 | goto panic_error; | |
123 | ||
124 | if (MYread_word(debugsock, &x)) /* memory size */ | |
125 | goto panic_error; | |
126 | ||
127 | MYwrite_char (mumkid[1], message); | |
128 | MYwrite_char (mumkid[1], c); | |
129 | MYwrite_word (mumkid[1], x); | |
130 | if (c & 0x2) | |
131 | { | |
132 | passon (debugsock, mumkid[1], 1); /* speed */ | |
133 | } | |
134 | break; | |
135 | ||
136 | case RDP_End: | |
137 | /* Close and Finalise */ | |
138 | #ifdef DEBUG | |
139 | fprintf(stderr, "RDP Close\n"); | |
140 | #endif | |
141 | MYwrite_char (mumkid[1], message); | |
142 | break; | |
143 | ||
144 | case RDP_Read: | |
145 | /* Read Memory Address */ | |
146 | #ifdef DEBUG | |
147 | fprintf (stderr, "RDP Read Memory\n"); | |
148 | #endif | |
149 | MYwrite_char (mumkid[1], message); | |
150 | if (passon (debugsock, mumkid[1], 4)) | |
151 | goto panic_error; /* address */ | |
152 | if (MYread_word(debugsock, &nbytes)) | |
153 | goto panic_error; /* nbytes */ | |
154 | MYwrite_word (mumkid[1], nbytes); | |
155 | break; | |
156 | ||
157 | case RDP_Write : | |
158 | /* Write Memory Address */ | |
159 | #ifdef DEBUG | |
160 | fprintf (stderr, "RDP Write Memory\n"); | |
161 | #endif | |
162 | if (MYread_word (debugsock, &x)) | |
163 | goto panic_error; /* address */ | |
164 | ||
165 | if (MYread_word (debugsock, &y)) | |
166 | goto panic_error; /* nbytes */ | |
167 | ||
168 | MYwrite_char (mumkid[1], message); | |
169 | MYwrite_word (mumkid[1], x); | |
170 | MYwrite_word (mumkid[1], y); | |
171 | passon (debugsock, mumkid[1], y); /* actual data */ | |
172 | break; | |
173 | ||
174 | case RDP_CPUread: | |
175 | /* Read CPU State */ | |
176 | #ifdef DEBUG | |
177 | fprintf (stderr, "RDP Read CPU\n"); | |
178 | #endif | |
179 | if (MYread_char(debugsock, &c)) | |
180 | goto panic_error; /* mode */ | |
181 | ||
182 | if (MYread_word (debugsock, &mask)) | |
183 | goto panic_error; /* mask */ | |
184 | ||
185 | MYwrite_char (mumkid[1], message); | |
186 | MYwrite_char (mumkid[1], c); | |
187 | MYwrite_word (mumkid[1], mask); | |
188 | break; | |
189 | ||
190 | case RDP_CPUwrite : | |
191 | /* Write CPU State */ | |
192 | #ifdef DEBUG | |
193 | fprintf (stderr, "RDP Write CPU\n"); | |
194 | #endif | |
195 | if (MYread_char (debugsock, &c)) | |
196 | goto panic_error; /* mode */ | |
197 | ||
198 | if (MYread_word (debugsock, &x)) | |
199 | goto panic_error; /* mask */ | |
200 | ||
201 | MYwrite_char (mumkid[1], message); | |
202 | MYwrite_char (mumkid[1], c); | |
203 | MYwrite_word (mumkid[1], x); | |
204 | for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) | |
205 | if ((k & x) | |
206 | && 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) | |
273 | && passon(debugsock, mumkid[1], 4)) | |
274 | goto panic_error; /* bound */ | |
275 | break; | |
276 | ||
277 | case RDP_ClearBreak: | |
278 | /* Clear Breakpoint */ | |
279 | #ifdef DEBUG | |
280 | fprintf (stderr, "RDP Clear Breakpoint\n"); | |
281 | #endif | |
282 | MYwrite_char (mumkid[1], message); | |
283 | if (passon (debugsock, mumkid[1], 4)) | |
284 | goto panic_error; /* point */ | |
285 | break; | |
286 | ||
287 | case RDP_SetWatch: | |
288 | /* Set Watchpoint */ | |
289 | #ifdef DEBUG | |
290 | fprintf (stderr, "RDP Set Watchpoint\n"); | |
291 | #endif | |
292 | if (MYread_word (debugsock, &x)) | |
293 | goto panic_error; /* address */ | |
294 | ||
295 | if (MYread_char(debugsock, &c)) | |
296 | goto panic_error; /* type */ | |
297 | ||
298 | if (MYread_char (debugsock, &d)) | |
299 | goto panic_error; /* datatype */ | |
300 | ||
301 | MYwrite_char (mumkid[1], message); | |
302 | MYwrite_word (mumkid[1], x); | |
303 | MYwrite_char (mumkid[1], c); | |
304 | MYwrite_char (mumkid[1], d); | |
305 | if (((c & 0xf) >= 5) | |
306 | && passon(debugsock, mumkid[1], 4)) | |
307 | goto panic_error; /* bound */ | |
308 | break; | |
309 | ||
310 | case RDP_ClearWatch: | |
311 | /* Clear Watchpoint */ | |
312 | #ifdef DEBUG | |
313 | fprintf (stderr, "RDP Clear Watchpoint\n"); | |
314 | #endif | |
315 | MYwrite_char (mumkid[1], message); | |
316 | if (passon (debugsock, mumkid[1], 4)) | |
317 | goto panic_error; /* point */ | |
318 | break; | |
319 | ||
320 | case RDP_Execute: | |
321 | /* Excecute */ | |
322 | #ifdef DEBUG | |
323 | fprintf (stderr, "RDP Execute\n"); | |
324 | #endif | |
325 | ||
326 | /* LEAVE THIS ONE 'TIL LATER... */ | |
327 | /* NEED TO WORK THINGS OUT */ | |
328 | ||
329 | /* NO ASCYNCHROUS RUNNING */ | |
330 | ||
331 | if (MYread_char(debugsock, &c)) | |
332 | goto panic_error; /* return */ | |
333 | ||
334 | /* Remember incase bit 7 is set and we have to send back a word */ | |
335 | exreturn = c; | |
336 | ||
337 | MYwrite_char(mumkid[1], message); | |
338 | MYwrite_char(mumkid[1], c); | |
339 | break; | |
340 | ||
341 | case RDP_Step: | |
342 | /* Step */ | |
343 | #ifdef DEBUG | |
344 | fprintf (stderr, "RDP Step\n"); | |
345 | #endif | |
346 | ||
347 | if (MYread_char(debugsock, &c)) | |
348 | goto panic_error; /* return */ | |
349 | ||
350 | if (MYread_word(debugsock, &x)) | |
351 | goto panic_error; /* ninstr */ | |
352 | ||
353 | MYwrite_char (mumkid[1], message); | |
354 | MYwrite_char (mumkid[1], c); | |
355 | MYwrite_word (mumkid[1], x); | |
356 | break; | |
357 | ||
358 | case RDP_Info: | |
359 | /* Info */ | |
360 | #ifdef DEBUG | |
361 | fprintf (stderr, "RDP Info\n"); | |
362 | #endif | |
363 | /* INFO TARGET, SET RDI LEVEL */ | |
364 | if (MYread_word (debugsock, &messagetype)) | |
365 | goto panic_error; /* info */ | |
366 | ||
367 | switch (messagetype) | |
368 | { | |
369 | case RDIInfo_Target: | |
370 | MYwrite_char (mumkid[1], message); | |
371 | MYwrite_word (mumkid[1], messagetype); | |
372 | break; | |
373 | ||
374 | case RDISet_RDILevel: | |
375 | MYwrite_char (mumkid[1], message); | |
376 | MYwrite_word (mumkid[1], messagetype); | |
377 | if (passon (debugsock, mumkid[1], 1)) | |
378 | goto panic_error; /* argument */ | |
379 | break; | |
380 | ||
381 | case RDISet_Cmdline: | |
382 | /* Got to pass on a string argument */ | |
383 | MYwrite_char (mumkid[1], message); | |
384 | MYwrite_word (mumkid[1], messagetype); | |
385 | do | |
386 | { | |
387 | if (MYread_char (debugsock, &c)) | |
388 | goto panic_error; | |
389 | ||
390 | MYwrite_char (mumkid[1], c); | |
391 | } while (c); | |
392 | break; | |
393 | ||
394 | case RDISignal_Stop: | |
395 | kill (child, SIGUSR1); | |
396 | MYwrite_char (debugsock, RDP_Return); | |
397 | MYwrite_char (debugsock, RDIError_UserInterrupt); | |
398 | break; | |
399 | ||
400 | case RDIVector_Catch: | |
401 | MYread_word (debugsock, &x); | |
402 | MYwrite_char (mumkid[1], message); | |
403 | MYwrite_word (mumkid[1], messagetype); | |
404 | MYwrite_word (mumkid[1], x); | |
405 | break; | |
406 | ||
407 | case RDIInfo_Step: | |
408 | MYwrite_char (mumkid[1], message); | |
409 | MYwrite_word (mumkid[1], messagetype); | |
410 | break; | |
411 | ||
412 | case RDIInfo_Points: | |
413 | MYwrite_char (mumkid[1], message); | |
414 | MYwrite_word (mumkid[1], messagetype); | |
415 | break; | |
416 | ||
417 | default: | |
418 | fprintf (stderr, "Unrecognized RDIInfo request %d\n", | |
419 | messagetype); | |
420 | goto panic_error; | |
421 | } | |
422 | break; | |
423 | ||
424 | case RDP_OSOpReply: | |
425 | /* OS Operation Reply */ | |
426 | #ifdef DEBUG | |
427 | fprintf (stderr, "RDP OS Reply\n"); | |
428 | #endif | |
429 | MYwrite_char (mumkid[1], message); | |
430 | if (MYread_char (debugsock, &message)) | |
431 | goto panic_error; | |
432 | MYwrite_char (mumkid[1], message); | |
433 | switch(message) | |
434 | { | |
435 | case 0: /* return value i.e. nothing else.*/ | |
436 | break; | |
437 | ||
438 | case 1: /* returns a byte... */ | |
439 | if (MYread_char(debugsock, &c)) | |
440 | goto panic_error; | |
441 | ||
442 | MYwrite_char (mumkid[1], c); | |
443 | break; | |
444 | ||
445 | case 2: /* returns a word... */ | |
446 | if (MYread_word(debugsock, &x)) | |
447 | goto panic_error; | |
448 | ||
449 | MYwrite_word (mumkid[1], x); | |
450 | break; | |
451 | } | |
452 | break; | |
453 | ||
454 | case RDP_Reset: | |
455 | /* Reset */ | |
456 | #ifdef DEBUG | |
457 | fprintf (stderr, "RDP Reset\n"); | |
458 | #endif | |
459 | MYwrite_char (mumkid[1], message); | |
460 | break; | |
461 | ||
462 | default: | |
463 | /* Hmm.. bad RDP operation */ | |
464 | fprintf (stderr, "RDP Bad RDP request (%d)\n", message); | |
465 | MYwrite_char (debugsock, RDP_Return); | |
466 | MYwrite_char (debugsock, RDIError_UnimplementedMessage); | |
467 | break; | |
468 | } | |
469 | } | |
470 | ||
471 | if (FD_ISSET (kidmum[0], &readfds)) | |
472 | { | |
473 | #ifdef DEBUG | |
474 | fprintf (stderr, "->ARMulator\n"); | |
475 | #endif | |
476 | /* Anything we get from the ARMulator has to go to the debugger... */ | |
477 | /* It is that simple! */ | |
478 | ||
479 | passon (kidmum[0], debugsock, 1); | |
480 | } | |
481 | } | |
482 | } | |
483 |