common/
[platform/upstream/binutils.git] / sim / arm / kid.c
1 /*  kid.c -- ARMulator RDP/RDI interface:  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 child process continues here...                           */
20 /* It waits on a pipe from the parent and translates the RDP     */
21 /* messages into RDI calls to the ARMulator passing RDP replies  */
22 /* back up a pipe to the parent.                                 */
23 /*****************************************************************/
24
25 #include <sys/types.h>
26 #include <signal.h>
27
28 #include "armdefs.h"
29 #include "dbg_conf.h"
30 #include "dbg_hif.h"
31 #include "dbg_rdi.h"
32 #include "gdbhost.h"
33 #include "communicate.h"
34
35 /* The pipes between the two processes */
36 extern int mumkid[2];
37 extern int kidmum[2];
38
39 /* The maximum number of file descriptors */
40 extern int nfds;
41
42 /* The machine name */
43 #define MAXHOSTNAMELENGTH 64
44 extern char localhost[MAXHOSTNAMELENGTH + 1];
45
46 /* The socket number */
47 extern unsigned int socketnumber;
48
49 /* RDI interface */
50 extern const struct RDIProcVec armul_rdi;
51
52 static int MYrdp_level = 0;
53
54 static int rdi_state = 0;
55
56 /**************************************************************/
57 /* Signal handler that terminates excecution in the ARMulator */
58 /**************************************************************/
59 void
60 kid_handlesignal (int sig)
61 {
62 #ifdef DEBUG
63   fprintf (stderr, "Terminate ARMulator excecution\n");
64 #endif
65   if (sig != SIGUSR1)
66     {
67       fprintf (stderr, "Unsupported signal.\n");
68       return;
69     }
70   armul_rdi.info (RDISignal_Stop, (unsigned long *) 0, (unsigned long *) 0);
71 }
72
73 /********************************************************************/
74 /* Waits on a pipe from the socket demon for RDP and                */
75 /* acts as an RDP to RDI interpreter on the front of the ARMulator. */
76 /********************************************************************/
77 void
78 kid ()
79 {
80   char *p, *q;
81   int i, j, k;
82   long outofthebag;
83   unsigned char c, d, message;
84   ARMword x, y, z;
85   struct sigaction action;
86   PointHandle point;
87   Dbg_ConfigBlock config;
88   Dbg_HostosInterface hostif;
89   struct Dbg_MCState *MCState;
90   char command_line[256];
91   struct fd_set readfds;
92
93   /* Setup a signal handler for SIGUSR1 */
94   action.sa_handler = kid_handlesignal;
95   action.sa_mask = 0;
96   action.sa_flags = 0;
97
98   sigaction (SIGUSR1, &action, (struct sigaction *) 0);
99
100   while (1)
101     {
102       /* Wait for ever */
103       FD_ZERO (&readfds);
104       FD_SET (mumkid[0], &readfds);
105
106       i = select (nfds, &readfds,
107                   (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);
108
109       if (i < 0)
110         {
111           perror ("select");
112         }
113
114       if (read (mumkid[0], &message, 1) < 1)
115         {
116           perror ("read");
117         }
118
119       switch (message)
120         {
121         case RDP_Start:
122           /* Open and/or Initialise */
123           BAG_newbag ();
124
125           MYread_char (mumkid[0], &c);  /* type */
126           MYread_word (mumkid[0], &x);  /* memorysize */
127           if (c & 0x2)
128             MYread_char (mumkid[0], &d);        /* speed */
129           config.processor = 0;
130           config.memorysize = x;
131           config.bytesex = (c & 0x4) ? RDISex_Big : RDISex_Little;
132           if (c & 0x8)
133             config.bytesex = RDISex_DontCare;
134
135           hostif.dbgprint = myprint;
136           hostif.dbgpause = mypause;
137           hostif.dbgarg = stdout;
138           hostif.writec = mywritec;
139           hostif.readc = myreadc;
140           hostif.write = mywrite;
141           hostif.gets = mygets;
142           hostif.reset = mypause;       /* do nothing */
143           hostif.resetarg = "Do I love resetting or what!\n";
144
145           if (rdi_state)
146             {
147               /* we have restarted, so kill off the existing run.  */
148               /* armul_rdi.close(); */
149             }
150           i = armul_rdi.open (c & 0x3, &config, &hostif, MCState);
151           rdi_state = 1;
152
153           MYwrite_char (kidmum[1], RDP_Return);
154           MYwrite_char (kidmum[1], (unsigned char) i);
155
156           x = ~0x4;
157           armul_rdi.info (RDIVector_Catch, &x, 0);
158
159           break;
160
161         case RDP_End:
162           /* Close and Finalise */
163           i = armul_rdi.close ();
164           rdi_state = 0;
165           MYwrite_char (kidmum[1], RDP_Return);
166           MYwrite_char (kidmum[1], (unsigned char) i);
167           break;
168
169         case RDP_Read:
170           /* Read Memory Address */
171           MYread_word (mumkid[0], &x);  /* address */
172           MYread_word (mumkid[0], &y);  /* nbytes */
173           p = (char *) malloc (y);
174           i = armul_rdi.read (x, p, (unsigned *) &y);
175           MYwrite_char (kidmum[1], RDP_Return);
176           for (k = 0; k < y; k++)
177             MYwrite_char (kidmum[1], p[k]);
178           free (p);
179           MYwrite_char (kidmum[1], (unsigned char) i);
180           if (i)
181             MYwrite_word (kidmum[1], y);        /* number of bytes sent without error */
182           break;
183
184         case RDP_Write:
185           /* Write Memory Address */
186           MYread_word (mumkid[0], &x);  /* address */
187           MYread_word (mumkid[0], &y);  /* nbytes */
188           p = (char *) malloc (y);
189           for (k = 0; k < y; k++)
190             MYread_char (mumkid[0], &p[k]);
191           i = armul_rdi.write (p, x, (unsigned *) &y);
192           free (p);
193           MYwrite_char (kidmum[1], RDP_Return);
194           MYwrite_char (kidmum[1], (unsigned char) i);
195           if (i)
196             MYwrite_word (kidmum[1], y);        /* number of bytes sent without error */
197           break;
198
199         case RDP_CPUread:
200           /* Read CPU State */
201           MYread_char (mumkid[0], &c);  /* mode */
202           MYread_word (mumkid[0], &x);  /* mask */
203           p = (char *) malloc (4 * RDINumCPURegs);
204           i = armul_rdi.CPUread (c, x, (ARMword *) p);
205           MYwrite_char (kidmum[1], RDP_Return);
206           for (k = 1, j = 0; k != 0x80000000; k *= 2)
207             if (k & x)
208               MYwrite_word (kidmum[1], ((ARMword *) p)[j++]);
209           free (p);
210           if (i)
211             MYwrite_char (kidmum[1], (unsigned char) j);
212           MYwrite_char (kidmum[1], (unsigned char) i);
213           break;
214
215         case RDP_CPUwrite:
216           /* Write CPU State */
217           MYread_char (mumkid[0], &c);  /* mode */
218           MYread_word (mumkid[0], &x);  /* mask */
219
220           p = (char *) malloc (4 * RDINumCPURegs);
221           for (k = 1, j = 0; k != 0x80000000; k *= 2)
222             if (k & x)
223               MYread_word (mumkid[0], &(((ARMword *) p)[j++]));
224           i = armul_rdi.CPUwrite (c, x, (ARMword *) p);
225           MYwrite_char (kidmum[1], RDP_Return);
226           MYwrite_char (kidmum[1], (unsigned char) i);
227           free (p);
228           break;
229
230         case RDP_CPread:
231           /* Read Co-Processor State */
232           MYread_char (mumkid[0], &c);  /* CPnum */
233           MYread_word (mumkid[0], &x);  /* mask */
234           p = q = (char *) malloc (16 * RDINumCPRegs);
235           i = armul_rdi.CPread (c, x, (ARMword *) p);
236           MYwrite_char (kidmum[1], RDP_Return);
237           for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
238             if (k & x)
239               {
240                 if ((c == 1 || c == 2) && k <= 128)
241                   {
242                     MYwrite_FPword (kidmum[1], q);
243                     q += 16;
244                   }
245                 else
246                   {
247                     MYwrite_word (kidmum[1], *q);
248                     q += 4;
249                   }
250               }
251           free (p);
252           if (i)
253             MYwrite_char (kidmum[1], (unsigned char) j);
254           MYwrite_char (kidmum[1], (unsigned char) i);
255           break;
256
257         case RDP_CPwrite:
258           /* Write Co-Processor State */
259           MYread_char (mumkid[0], &c);  /* CPnum */
260           MYread_word (mumkid[0], &x);  /* mask */
261           p = q = (char *) malloc (16 * RDINumCPURegs);
262           for (k = 1, j = 0; k != 0x80000000; k *= 2, j++)
263             if (k & x)
264               {
265                 if ((c == 1 || c == 2) && k <= 128)
266                   {
267                     MYread_FPword (kidmum[1], q);
268                     q += 16;
269                   }
270                 else
271                   {
272                     MYread_word (mumkid[0], (ARMword *) q);
273                     q += 4;
274                   }
275               }
276           i = armul_rdi.CPwrite (c, x, (ARMword *) p);
277           MYwrite_char (kidmum[1], RDP_Return);
278           MYwrite_char (kidmum[1], (unsigned char) i);
279           free (p);
280           break;
281
282         case RDP_SetBreak:
283           /* Set Breakpoint */
284           MYread_word (mumkid[0], &x);  /* address */
285           MYread_char (mumkid[0], &c);  /* type */
286           if ((c & 0xf) >= 5)
287             MYread_word (mumkid[0], &y);        /* bound */
288           i = armul_rdi.setbreak (x, c, y, &point);
289           if (!MYrdp_level)
290             BAG_putpair ((long) x, (long) point);
291           MYwrite_char (kidmum[1], RDP_Return);
292           if (MYrdp_level)
293             MYwrite_word (kidmum[1], point);
294           MYwrite_char (kidmum[1], (unsigned char) i);
295           break;
296
297         case RDP_ClearBreak:
298           /* Clear Breakpoint */
299           MYread_word (mumkid[0], &point);      /* PointHandle */
300           if (!MYrdp_level)
301             {
302               BAG_getsecond ((long) point, &outofthebag);       /* swap pointhandle for address */
303               BAG_killpair_byfirst (outofthebag);
304               point = outofthebag;
305             }
306           i = armul_rdi.clearbreak (point);
307           MYwrite_char (kidmum[1], RDP_Return);
308           MYwrite_char (kidmum[1], (unsigned char) i);
309           break;
310
311         case RDP_SetWatch:
312           /* Set Watchpoint */
313           MYread_word (mumkid[0], &x);  /* address */
314           MYread_char (mumkid[0], &c);  /* type */
315           MYread_char (mumkid[0], &d);  /* datatype */
316           if ((c & 0xf) >= 5)
317             MYread_word (mumkid[0], &y);        /* bound */
318           i = armul_rdi.setwatch (x, c, d, y, &point);
319           MYwrite_char (kidmum[1], RDP_Return);
320           MYwrite_word (kidmum[1], point);
321           MYwrite_char (kidmum[1], (unsigned char) i);
322           break;
323
324         case RDP_ClearWatch:
325           /* Clear Watchpoint */
326           MYread_word (mumkid[0], &point);      /* PointHandle */
327           i = armul_rdi.clearwatch (point);
328           MYwrite_char (kidmum[1], RDP_Return);
329           MYwrite_char (kidmum[1], (unsigned char) i);
330           break;
331
332         case RDP_Execute:
333           /* Excecute */
334
335           MYread_char (mumkid[0], &c);  /* return */
336
337 #ifdef DEBUG
338           fprintf (stderr, "Starting execution\n");
339 #endif
340           i = armul_rdi.execute (&point);
341 #ifdef DEBUG
342           fprintf (stderr, "Completed execution\n");
343 #endif
344           MYwrite_char (kidmum[1], RDP_Return);
345           if (c & 0x80)
346             MYwrite_word (kidmum[1], point);
347           MYwrite_char (kidmum[1], (unsigned char) i);
348           break;
349
350         case RDP_Step:
351           /* Step */
352           MYread_char (mumkid[0], &c);  /* return */
353           MYread_word (mumkid[0], &x);  /* ninstr */
354           point = 0x87654321;
355           i = armul_rdi.step (x, &point);
356           MYwrite_char (kidmum[1], RDP_Return);
357           if (c & 0x80)
358             MYwrite_word (kidmum[1], point);
359           MYwrite_char (kidmum[1], (unsigned char) i);
360           break;
361
362         case RDP_Info:
363           /* Info */
364           MYread_word (mumkid[0], &x);
365           switch (x)
366             {
367             case RDIInfo_Target:
368               i = armul_rdi.info (RDIInfo_Target, &y, &z);
369               MYwrite_char (kidmum[1], RDP_Return);
370               MYwrite_word (kidmum[1], y);      /* Loads of info... */
371               MYwrite_word (kidmum[1], z);      /* Model */
372               MYwrite_char (kidmum[1], (unsigned char) i);
373               break;
374
375             case RDISet_RDILevel:
376               MYread_word (mumkid[0], &x);      /* arg1, debug level */
377               i = armul_rdi.info (RDISet_RDILevel, &x, 0);
378               if (i == RDIError_NoError)
379                 MYrdp_level = x;
380               MYwrite_char (kidmum[1], RDP_Return);
381               MYwrite_char (kidmum[1], (unsigned char) i);
382               break;
383
384             case RDISet_Cmdline:
385               for (p = command_line; MYread_char (mumkid[0], p), *p; p++)
386                 ;               /* String */
387               i = armul_rdi.info (RDISet_Cmdline,
388                                   (unsigned long *) command_line, 0);
389               MYwrite_char (kidmum[1], RDP_Return);
390               MYwrite_char (kidmum[1], (unsigned char) i);
391               break;
392
393             case RDIInfo_Step:
394               i = armul_rdi.info (RDIInfo_Step, &x, 0);
395               MYwrite_char (kidmum[1], RDP_Return);
396               MYwrite_word (kidmum[1], x);
397               MYwrite_char (kidmum[1], (unsigned char) i);
398               break;
399
400             case RDIVector_Catch:
401               MYread_word (mumkid[0], &x);
402               i = armul_rdi.info (RDIVector_Catch, &x, 0);
403               MYwrite_char (kidmum[1], RDP_Return);
404               MYwrite_char (kidmum[1], i);
405               break;
406
407             case RDIInfo_Points:
408               i = armul_rdi.info (RDIInfo_Points, &x, 0);
409               MYwrite_char (kidmum[1], RDP_Return);
410               MYwrite_word (kidmum[1], x);
411               MYwrite_char (kidmum[1], (unsigned char) i);
412               break;
413
414             default:
415               fprintf (stderr, "Unsupported info code %d\n", x);
416               break;
417             }
418           break;
419
420         case RDP_OSOpReply:
421           /* OS Operation Reply */
422           MYwrite_char (kidmum[1], RDP_Fatal);
423           break;
424
425         case RDP_Reset:
426           /* Reset */
427           for (i = 0; i < 50; i++)
428             MYwrite_char (kidmum[1], RDP_Reset);
429           p = (char *) malloc (MAXHOSTNAMELENGTH + 5 + 20);
430           sprintf (p, "Running on %s:%d\n", localhost, socketnumber);
431           MYwrite_string (kidmum[1], p);
432           free (p);
433
434           break;
435         default:
436           fprintf (stderr, "Oh dear: Something is seriously wrong :-(\n");
437           /* Hmm.. bad RDP operation */
438           break;
439         }
440     }
441 }
442
443
444 /* Handles memory read operations until an OS Operation Reply Message is */
445 /* encounterd. It then returns the byte info value (0, 1, or 2) and fills  */
446 /* in 'putinr0' with the data if appropriate. */
447 int
448 wait_for_osreply (ARMword * reply)
449 {
450   char *p, *q;
451   int i, j, k;
452   unsigned char c, d, message;
453   ARMword x, y, z;
454   struct sigaction action;
455   PointHandle point;
456   Dbg_ConfigBlock config;
457   Dbg_HostosInterface hostif;
458   struct Dbg_MCState *MCState;
459   char command_line[256];
460   struct fd_set readfds;
461
462 #ifdef DEBUG
463   fprintf (stderr, "wait_for_osreply ().\n");
464 #endif
465
466   /* Setup a signal handler for SIGUSR1 */
467   action.sa_handler = kid_handlesignal;
468   action.sa_mask = 0;
469   action.sa_flags = 0;
470
471   sigaction (SIGUSR1, &action, (struct sigaction *) 0);
472
473   while (1)
474     {
475       /* Wait for ever */
476       FD_ZERO (&readfds);
477       FD_SET (mumkid[0], &readfds);
478
479       i = select (nfds, &readfds,
480                   (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);
481
482       if (i < 0)
483         {
484           perror ("select");
485         }
486
487       if (read (mumkid[0], &message, 1) < 1)
488         {
489           perror ("read");
490         }
491
492       switch (message)
493         {
494         case RDP_Read:
495           /* Read Memory Address */
496           MYread_word (mumkid[0], &x);  /* address */
497           MYread_word (mumkid[0], &y);  /* nbytes */
498           p = (char *) malloc (y);
499           i = armul_rdi.read (x, p, (unsigned *) &y);
500           MYwrite_char (kidmum[1], RDP_Return);
501           for (k = 0; k < y; k++)
502             MYwrite_char (kidmum[1], p[k]);
503           free (p);
504           MYwrite_char (kidmum[1], (unsigned char) i);
505           if (i)
506             MYwrite_word (kidmum[1], y);        /* number of bytes sent without error */
507           break;
508
509         case RDP_Write:
510           /* Write Memory Address */
511           MYread_word (mumkid[0], &x);  /* address */
512           MYread_word (mumkid[0], &y);  /* nbytes */
513           p = (char *) malloc (y);
514           for (k = 0; k < y; k++)
515             MYread_char (mumkid[0], &p[k]);
516           i = armul_rdi.write (p, x, (unsigned *) &y);
517           free (p);
518           MYwrite_char (kidmum[1], RDP_Return);
519           MYwrite_char (kidmum[1], (unsigned char) i);
520           if (i)
521             MYwrite_word (kidmum[1], y);        /* number of bytes sent without error */
522           break;
523
524         case RDP_OSOpReply:
525           /* OS Operation Reply */
526           MYread_char (mumkid[0], &c);
527           if (c == 1)
528             MYread_char (mumkid[0], (char *) reply);
529           if (c == 2)
530             MYread_word (mumkid[0], reply);
531           return c;
532           break;
533
534         default:
535           fprintf (stderr,
536                    "HELP! Unaccounted-for message during OS request. \n");
537           MYwrite_char (kidmum[1], RDP_Fatal);
538         }
539     }
540 }