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