21da64332aa67149f3aaaf7e8e9e86a0e66c63c2
[external/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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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