unit at a time
[platform/upstream/binutils.git] / sim / arm / parent.c
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 3 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, see <http://www.gnu.org/licenses/>. */
16
17 /*****************************************************************/
18 /* The Parent process continues here...                          */
19 /* It waits on the socket and passes on RDP messages down a pipe */
20 /* to the ARMulator RDP to RDI interpreter.                      */
21 /*****************************************************************/
22
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <signal.h>
26 #include "time.h"
27 #include "armdefs.h"
28 #include "dbg_rdi.h"
29 #include "communicate.h"
30
31 /* The socket to the debugger */
32 extern int debugsock;
33
34 /* The pipes between the two processes */
35 extern int mumkid[2];
36 extern int kidmum[2];
37
38 /* A pipe for handling SWI return values that goes straight from the */
39 /* parent to the ARMulator host interface, bypassing the child's RDP */
40 /* to RDI interpreter */
41 extern int DebuggerARMul[2];
42
43 /* The maximum number of file descriptors */
44 extern int nfds;
45
46 /* The child process id. */
47 extern pid_t child;
48
49 void
50 parent ()
51 {
52   int i, j, k;
53   unsigned char message, CPnum, exreturn;
54   ARMword mask, nbytes, messagetype;
55   unsigned char c, d;
56   ARMword x, y;
57   int virgin = 1;
58   struct fd_set readfds;
59
60 #ifdef DEBUG
61   fprintf (stderr, "parent ()...\n");
62 #endif
63
64 panic_error:
65
66   if (!virgin)
67     {
68 #ifdef DEBUG
69       fprintf (stderr, "Arghh! What is going on?\n");
70 #endif
71       kill (child, SIGHUP);
72       MYwrite_char (debugsock, RDP_Reset);
73     }
74
75   virgin = 0;
76
77   while (1)
78     {
79
80       /* Wait either for the ARMulator or the debugger */
81
82       FD_ZERO (&readfds);
83       FD_SET (kidmum[0], &readfds);     /* Wait for messages from ARMulator */
84       FD_SET (debugsock, &readfds);     /* Wait for messages from debugger */
85
86 #ifdef DEBUG
87       fprintf (stderr, "Waiting for ARMulator or debugger... ");
88 #endif
89
90       while ((i = select (nfds, &readfds, (fd_set *) 0, (fd_set *) 0, 0)) < 0)
91         {
92           perror ("select");
93         }
94
95 #ifdef DEBUG
96       fprintf (stderr, "(%d/2)", i);
97 #endif
98
99       if (FD_ISSET (debugsock, &readfds))
100         {
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) && passon (debugsock, mumkid[1], 4))
206                   goto panic_error;
207               break;
208
209             case RDP_CPread:
210               /* Read Co-Processor State */
211 #ifdef DEBUG
212               fprintf (stderr, "RDP Read CP state\n");
213 #endif
214               if (MYread_char (debugsock, &CPnum))
215                 goto panic_error;
216
217               if (MYread_word (debugsock, &mask))
218                 goto panic_error;
219
220               MYwrite_char (mumkid[1], message);
221               MYwrite_char (mumkid[1], CPnum);
222               MYwrite_word (mumkid[1], mask);
223               break;
224
225             case RDP_CPwrite:
226               /* Write Co-Processor State */
227 #ifdef DEBUG
228               fprintf (stderr, "RDP Write CP state\n");
229 #endif
230               if (MYread_char (debugsock, &CPnum))
231                 goto panic_error;
232
233               if (MYread_word (debugsock, &mask))
234                 goto panic_error;
235
236               MYwrite_char (mumkid[1], message);
237               MYwrite_char (mumkid[1], c);
238               MYwrite_char (mumkid[1], x);
239               for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
240                 if (k & x)
241                   {
242                     if ((c == 1 || c == 2) && k <= 128)
243                       {
244                         /* FP register = 12 bytes + 4 bytes format */
245                         if (passon (debugsock, mumkid[1], 16))
246                           goto panic_error;
247                       }
248                     else
249                       {
250                         /* Normal register = 4 bytes */
251                         if (passon (debugsock, mumkid[1], 4))
252                           goto panic_error;
253                       }
254                   }
255               break;
256
257             case RDP_SetBreak:
258               /* Set Breakpoint */
259 #ifdef DEBUG
260               fprintf (stderr, "RDP Set Breakpoint\n");
261 #endif
262               if (MYread_word (debugsock, &x))
263                 goto panic_error;       /* address */
264
265               if (MYread_char (debugsock, &c))
266                 goto panic_error;       /* type */
267
268               MYwrite_char (mumkid[1], message);
269               MYwrite_word (mumkid[1], x);
270               MYwrite_char (mumkid[1], c);
271               if (((c & 0xf) >= 5) && passon (debugsock, mumkid[1], 4))
272                 goto panic_error;       /* bound */
273               break;
274
275             case RDP_ClearBreak:
276               /* Clear Breakpoint */
277 #ifdef DEBUG
278               fprintf (stderr, "RDP Clear Breakpoint\n");
279 #endif
280               MYwrite_char (mumkid[1], message);
281               if (passon (debugsock, mumkid[1], 4))
282                 goto panic_error;       /* point */
283               break;
284
285             case RDP_SetWatch:
286               /* Set Watchpoint */
287 #ifdef DEBUG
288               fprintf (stderr, "RDP Set Watchpoint\n");
289 #endif
290               if (MYread_word (debugsock, &x))
291                 goto panic_error;       /* address */
292
293               if (MYread_char (debugsock, &c))
294                 goto panic_error;       /* type */
295
296               if (MYread_char (debugsock, &d))
297                 goto panic_error;       /* datatype */
298
299               MYwrite_char (mumkid[1], message);
300               MYwrite_word (mumkid[1], x);
301               MYwrite_char (mumkid[1], c);
302               MYwrite_char (mumkid[1], d);
303               if (((c & 0xf) >= 5) && passon (debugsock, mumkid[1], 4))
304                 goto panic_error;       /* bound */
305               break;
306
307             case RDP_ClearWatch:
308               /* Clear Watchpoint */
309 #ifdef DEBUG
310               fprintf (stderr, "RDP Clear Watchpoint\n");
311 #endif
312               MYwrite_char (mumkid[1], message);
313               if (passon (debugsock, mumkid[1], 4))
314                 goto panic_error;       /* point */
315               break;
316
317             case RDP_Execute:
318               /* Excecute */
319 #ifdef DEBUG
320               fprintf (stderr, "RDP Execute\n");
321 #endif
322
323               /* LEAVE THIS ONE 'TIL LATER... */
324               /* NEED TO WORK THINGS OUT */
325
326               /* NO ASCYNCHROUS RUNNING */
327
328               if (MYread_char (debugsock, &c))
329                 goto panic_error;       /* return */
330
331               /* Remember incase bit 7 is set and we have to send back a word */
332               exreturn = c;
333
334               MYwrite_char (mumkid[1], message);
335               MYwrite_char (mumkid[1], c);
336               break;
337
338             case RDP_Step:
339               /* Step */
340 #ifdef DEBUG
341               fprintf (stderr, "RDP Step\n");
342 #endif
343
344               if (MYread_char (debugsock, &c))
345                 goto panic_error;       /* return */
346
347               if (MYread_word (debugsock, &x))
348                 goto panic_error;       /* ninstr */
349
350               MYwrite_char (mumkid[1], message);
351               MYwrite_char (mumkid[1], c);
352               MYwrite_word (mumkid[1], x);
353               break;
354
355             case RDP_Info:
356               /* Info */
357 #ifdef DEBUG
358               fprintf (stderr, "RDP Info\n");
359 #endif
360               /* INFO TARGET, SET RDI LEVEL */
361               if (MYread_word (debugsock, &messagetype))
362                 goto panic_error;       /* info */
363
364               switch (messagetype)
365                 {
366                 case RDIInfo_Target:
367                   MYwrite_char (mumkid[1], message);
368                   MYwrite_word (mumkid[1], messagetype);
369                   break;
370
371                 case RDISet_RDILevel:
372                   MYwrite_char (mumkid[1], message);
373                   MYwrite_word (mumkid[1], messagetype);
374                   if (passon (debugsock, mumkid[1], 1))
375                     goto panic_error;   /* argument */
376                   break;
377
378                 case RDISet_Cmdline:
379                   /* Got to pass on a string argument */
380                   MYwrite_char (mumkid[1], message);
381                   MYwrite_word (mumkid[1], messagetype);
382                   do
383                     {
384                       if (MYread_char (debugsock, &c))
385                         goto panic_error;
386
387                       MYwrite_char (mumkid[1], c);
388                     }
389                   while (c);
390                   break;
391
392                 case RDISignal_Stop:
393                   kill (child, SIGUSR1);
394                   MYwrite_char (debugsock, RDP_Return);
395                   MYwrite_char (debugsock, RDIError_UserInterrupt);
396                   break;
397
398                 case RDIVector_Catch:
399                   MYread_word (debugsock, &x);
400                   MYwrite_char (mumkid[1], message);
401                   MYwrite_word (mumkid[1], messagetype);
402                   MYwrite_word (mumkid[1], x);
403                   break;
404
405                 case RDIInfo_Step:
406                   MYwrite_char (mumkid[1], message);
407                   MYwrite_word (mumkid[1], messagetype);
408                   break;
409
410                 case RDIInfo_Points:
411                   MYwrite_char (mumkid[1], message);
412                   MYwrite_word (mumkid[1], messagetype);
413                   break;
414
415                 default:
416                   fprintf (stderr, "Unrecognized RDIInfo request %d\n",
417                            messagetype);
418                   goto panic_error;
419                 }
420               break;
421
422             case RDP_OSOpReply:
423               /* OS Operation Reply */
424 #ifdef DEBUG
425               fprintf (stderr, "RDP OS Reply\n");
426 #endif
427               MYwrite_char (mumkid[1], message);
428               if (MYread_char (debugsock, &message))
429                 goto panic_error;
430               MYwrite_char (mumkid[1], message);
431               switch (message)
432                 {
433                 case 0: /* return value i.e. nothing else. */
434                   break;
435
436                 case 1: /* returns a byte... */
437                   if (MYread_char (debugsock, &c))
438                     goto panic_error;
439
440                   MYwrite_char (mumkid[1], c);
441                   break;
442
443                 case 2: /* returns a word... */
444                   if (MYread_word (debugsock, &x))
445                     goto panic_error;
446
447                   MYwrite_word (mumkid[1], x);
448                   break;
449                 }
450               break;
451
452             case RDP_Reset:
453               /* Reset */
454 #ifdef DEBUG
455               fprintf (stderr, "RDP Reset\n");
456 #endif
457               MYwrite_char (mumkid[1], message);
458               break;
459
460             default:
461               /* Hmm.. bad RDP operation */
462               fprintf (stderr, "RDP Bad RDP request (%d)\n", message);
463               MYwrite_char (debugsock, RDP_Return);
464               MYwrite_char (debugsock, RDIError_UnimplementedMessage);
465               break;
466             }
467         }
468
469       if (FD_ISSET (kidmum[0], &readfds))
470         {
471 #ifdef DEBUG
472           fprintf (stderr, "->ARMulator\n");
473 #endif
474           /* Anything we get from the ARMulator has to go to the debugger... */
475           /* It is that simple! */
476
477           passon (kidmum[0], debugsock, 1);
478         }
479     }
480 }