]> Git Repo - binutils.git/blob - gdb/remote-adapt.c
* symfile.c (deduce_language_from_filename): Accept .cxx for C++.
[binutils.git] / gdb / remote-adapt.c
1 /* Remote debugging interface for AMD 290*0 Adapt Monitor Version 2.1d18. 
2    Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
3    Contributed by David Wood at New York University ([email protected]).
4    Adapted from work done at Cygnus Support in remote-eb.c.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21
22 /* This is like remote.c but is for an esoteric situation--
23    having a 29k board attached to an Adapt inline monitor. 
24    The  monitor is connected via serial line to a unix machine 
25    running gdb. 
26
27    3/91 -  developed on Sun3 OS 4.1, by David Wood
28         o - I can't get binary coff to load. 
29         o - I can't get 19200 baud rate to work. 
30    7/91 o - Freeze mode tracing can be done on a 29050.  */
31
32 #include "defs.h"
33 #include <string.h>
34 #include "inferior.h"
35 #include "wait.h"
36 #include "value.h"
37 #include <ctype.h>
38 #include <fcntl.h>
39 #include <signal.h>
40 #include <errno.h>
41 #include "terminal.h"
42 #include "target.h"
43 #include "gdbcore.h"
44
45 /* External data declarations */
46 extern int stop_soon_quietly;           /* for wait_for_inferior */
47
48 /* Forward data declarations */
49 extern struct target_ops adapt_ops;             /* Forward declaration */
50
51 /* Forward function declarations */
52 static void adapt_fetch_registers ();
53 static void adapt_store_registers ();
54 static void adapt_close ();
55 static int  adapt_clear_breakpoints();
56
57 #define FREEZE_MODE     (read_register(CPS_REGNUM) && 0x400) 
58 #define USE_SHADOW_PC   ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
59
60 /* Can't seem to get binary coff working */
61 #define ASCII_COFF              /* Adapt will be downloaded with ascii coff */
62
63 /* FIXME: Replace with `set remotedebug'.  */
64 #define LOG_FILE "adapt.log"
65 #if defined (LOG_FILE)
66 FILE *log_file=NULL;
67 #endif
68
69 static int timeout = 5;
70 static char *dev_name;
71
72 /* Descriptor for I/O to remote machine.  Initialize it to -1 so that
73    adapt_open knows that we don't have a file open when the program
74    starts.  */
75 int adapt_desc = -1;
76
77 /* stream which is fdopen'd from adapt_desc.  Only valid when
78    adapt_desc != -1.  */
79 FILE *adapt_stream;
80
81 #define ON      1
82 #define OFF     0
83 static void
84 rawmode(desc, turnon)
85 int     desc;
86 int     turnon;
87 {
88   TERMINAL sg;
89
90   if (desc < 0)
91     return;
92
93   ioctl (desc, TIOCGETP, &sg);
94
95   if (turnon) {
96 #ifdef HAVE_TERMIO
97         sg.c_lflag &= ~(ICANON);
98 #else
99         sg.sg_flags |= RAW;
100 #endif
101   } else {
102 #ifdef HAVE_TERMIO
103         sg.c_lflag |= ICANON;
104 #else
105         sg.sg_flags &= ~(RAW);
106 #endif
107   }
108   ioctl (desc, TIOCSETP, &sg);
109 }
110
111 /* Suck up all the input from the adapt */
112 slurp_input()
113 {
114   char buf[8];
115
116 #ifdef HAVE_TERMIO
117   /* termio does the timeout for us.  */
118   while (read (adapt_desc, buf, 8) > 0);
119 #else
120   alarm (timeout);
121   while (read (adapt_desc, buf, 8) > 0);
122   alarm (0);
123 #endif
124 }
125
126 /* Read a character from the remote system, doing all the fancy
127    timeout stuff.  */
128 static int
129 readchar ()
130 {
131   char buf;
132
133   buf = '\0';
134 #ifdef HAVE_TERMIO
135   /* termio does the timeout for us.  */
136   read (adapt_desc, &buf, 1);
137 #else
138   alarm (timeout);
139   if (read (adapt_desc, &buf, 1) < 0)
140     {
141       if (errno == EINTR)
142         error ("Timeout reading from remote system.");
143       else
144         perror_with_name ("remote");
145     }
146   alarm (0);
147 #endif
148
149   if (buf == '\0')
150     error ("Timeout reading from remote system.");
151 #if defined (LOG_FILE)
152   putc (buf & 0x7f, log_file);
153 #endif
154   return buf & 0x7f;
155 }
156
157 /* Keep discarding input from the remote system, until STRING is found. 
158    Let the user break out immediately.  */
159 static void
160 expect (string)
161      char *string;
162 {
163   char *p = string;
164
165   fflush(adapt_stream);
166   immediate_quit = 1;
167   while (1)
168     {
169       if (readchar() == *p)
170         {
171           p++;
172           if (*p == '\0')
173             {
174               immediate_quit = 0;
175               return;
176             }
177         }
178       else
179         p = string;
180     }
181 }
182
183 /* Keep discarding input until we see the adapt prompt.
184
185    The convention for dealing with the prompt is that you
186    o give your command
187    o *then* wait for the prompt.
188
189    Thus the last thing that a procedure does with the serial line
190    will be an expect_prompt().  Exception:  adapt_resume does not
191    wait for the prompt, because the terminal is being handed over
192    to the inferior.  However, the next thing which happens after that
193    is a adapt_wait which does wait for the prompt.
194    Note that this includes abnormal exit, e.g. error().  This is
195    necessary to prevent getting into states from which we can't
196    recover.  */
197 static void
198 expect_prompt ()
199 {
200 #if defined (LOG_FILE)
201   /* This is a convenient place to do this.  The idea is to do it often
202      enough that we never lose much data if we terminate abnormally.  */
203   fflush (log_file);
204 #endif
205   fflush(adapt_stream);
206   expect ("\n# ");
207 }
208
209 /* Get a hex digit from the remote system & return its value.
210    If ignore_space is nonzero, ignore spaces (not newline, tab, etc).  */
211 static int
212 get_hex_digit (ignore_space)
213      int ignore_space;
214 {
215   int ch;
216   while (1)
217     {
218       ch = readchar ();
219       if (ch >= '0' && ch <= '9')
220         return ch - '0';
221       else if (ch >= 'A' && ch <= 'F')
222         return ch - 'A' + 10;
223       else if (ch >= 'a' && ch <= 'f')
224         return ch - 'a' + 10;
225       else if (ch == ' ' && ignore_space)
226         ;
227       else
228         {
229           expect_prompt ();
230           error ("Invalid hex digit from remote system.");
231         }
232     }
233 }
234
235 /* Get a byte from adapt_desc and put it in *BYT.  Accept any number
236    leading spaces.  */
237 static void
238 get_hex_byte (byt)
239      char *byt;
240 {
241   int val;
242
243   val = get_hex_digit (1) << 4;
244   val |= get_hex_digit (0);
245   *byt = val;
246 }
247
248 /* Read a 32-bit hex word from the adapt, preceded by a space  */
249 static long 
250 get_hex_word()
251 {
252   long val;
253   int j;
254       
255   val = 0;
256   for (j = 0; j < 8; j++)
257         val = (val << 4) + get_hex_digit (j == 0);
258   return val;
259 }
260 /* Get N 32-bit hex words from remote, each preceded by a space 
261    and put them in registers starting at REGNO.  */
262 static void
263 get_hex_regs (n, regno)
264      int n;
265      int regno;
266 {
267         long val;
268         while (n--) {
269                 val = get_hex_word();
270                 supply_register(regno++,(char *) &val);
271         }
272 }
273 /* Called when SIGALRM signal sent due to alarm() timeout.  */
274 #ifndef HAVE_TERMIO
275
276 #ifndef __STDC__
277 # ifndef volatile
278 #  define volatile /**/
279 # endif
280 #endif
281 volatile int n_alarms;
282
283 void
284 adapt_timer ()
285 {
286 #if 0
287   if (kiodebug)
288     printf ("adapt_timer called\n");
289 #endif
290   n_alarms++;
291 }
292 #endif
293
294 /* malloc'd name of the program on the remote system.  */
295 static char *prog_name = NULL;
296
297 /* Number of SIGTRAPs we need to simulate.  That is, the next
298    NEED_ARTIFICIAL_TRAP calls to adapt_wait should just return
299    SIGTRAP without actually waiting for anything.  */
300
301 static int need_artificial_trap = 0;
302
303 void
304 adapt_kill(arg,from_tty)
305 char    *arg;
306 int     from_tty;
307 {
308         fprintf (adapt_stream, "K");
309         fprintf (adapt_stream, "\r");
310         expect_prompt ();
311 }
312 /*
313  * Download a file specified in 'args', to the adapt. 
314  * FIXME: Assumes the file to download is a binary coff file.
315  */
316 static void
317 adapt_load(args,fromtty)
318 char    *args;
319 int     fromtty;
320 {
321         FILE *fp;
322         int     n;
323         char    buffer[1024];
324         
325         if (!adapt_stream) {
326                 printf_filtered("Adapt not open. Use 'target' command to open adapt\n");
327                 return;
328         }
329
330         /* OK, now read in the file.  Y=read, C=COFF, T=dTe port
331                 0=start address.  */
332
333 #ifdef ASCII_COFF       /* Ascii coff */
334         fprintf (adapt_stream, "YA T,0\r");
335         fflush(adapt_stream);   /* Just in case */
336         /* FIXME: should check args for only 1 argument */
337         sprintf(buffer,"cat %s | btoa > /tmp/#adapt-btoa",args);
338         system(buffer);
339         fp = fopen("/tmp/#adapt-btoa","r");
340         rawmode(adapt_desc,OFF);        
341         while (n=fread(buffer,1,1024,fp)) {
342                 do { n -= write(adapt_desc,buffer,n); } while (n>0);
343                 if (n<0) { perror("writing ascii coff"); break; }
344         }
345         fclose(fp);
346         rawmode(adapt_desc,ON); 
347         system("rm /tmp/#adapt-btoa");
348 #else   /* Binary coff - can't get it to work .*/
349         fprintf (adapt_stream, "YC T,0\r");
350         fflush(adapt_stream);   /* Just in case */
351         if (!(fp = fopen(args,"r"))) {
352                 printf_filtered("Can't open %s\n",args);
353                 return;
354         }
355         while (n=fread(buffer,1,512,fp)) {
356                 do { n -= write(adapt_desc,buffer,n); } while (n>0);
357                 if (n<0) { perror("writing ascii coff"); break; }
358         }
359         fclose(fp);
360 #endif
361         expect_prompt ();       /* Skip garbage that comes out */
362         fprintf (adapt_stream, "\r");
363         expect_prompt ();
364 }
365
366 /* This is called not only when we first attach, but also when the
367    user types "run" after having attached.  */
368 void
369 adapt_create_inferior (execfile, args, env)
370      char *execfile;
371      char *args;
372      char **env;
373 {
374   int entry_pt;
375
376   if (args && *args)
377     error ("Can't pass arguments to remote adapt process.");
378
379   if (execfile == 0 || exec_bfd == 0)
380     error ("No exec file specified");
381
382   entry_pt = (int) bfd_get_start_address (exec_bfd);
383
384   if (adapt_stream) {
385         adapt_kill(NULL,NULL);   
386         adapt_clear_breakpoints();
387         init_wait_for_inferior ();
388         /* Clear the input because what the adapt sends back is different
389          * depending on whether it was running or not.
390          */
391         slurp_input();  /* After this there should be a prompt */
392         fprintf(adapt_stream,"\r"); 
393         expect_prompt();
394         printf_filtered("Do you want to download '%s' (y/n)? [y] : ",prog_name);
395         {       
396                 char buffer[10];
397                 gets(buffer);
398                 if (*buffer != 'n') {
399                         adapt_load(prog_name,0);
400                 }
401         }
402
403 #ifdef NOTDEF
404         /* Set the PC and wait for a go/cont */
405           fprintf (adapt_stream, "G %x,N\r",entry_pt);
406           printf_filtered("Now use the 'continue' command to start.\n"); 
407           expect_prompt ();
408 #else
409         insert_breakpoints ();  /* Needed to get correct instruction in cache */
410         proceed(entry_pt, -1, 0);
411 #endif
412
413   } else {
414         printf_filtered("Adapt not open yet.\n");
415   }
416 }
417
418 /* Translate baud rates from integers to damn B_codes.  Unix should
419    have outgrown this crap years ago, but even POSIX wouldn't buck it.  */
420
421 #ifndef B19200
422 #define B19200 EXTA
423 #endif
424 #ifndef B38400
425 #define B38400 EXTB
426 #endif
427
428 static struct {int rate, damn_b;} baudtab[] = {
429         {0, B0},
430         {50, B50},
431         {75, B75},
432         {110, B110},
433         {134, B134},
434         {150, B150},
435         {200, B200},
436         {300, B300},
437         {600, B600},
438         {1200, B1200},
439         {1800, B1800},
440         {2400, B2400},
441         {4800, B4800},
442         {9600, B9600},
443         {19200, B19200},
444         {38400, B38400},
445         {-1, -1},
446 };
447
448 static int damn_b (rate)
449      int rate;
450 {
451   int i;
452
453   for (i = 0; baudtab[i].rate != -1; i++)
454     if (rate == baudtab[i].rate) return baudtab[i].damn_b;
455   return B38400;        /* Random */
456 }
457
458
459 /* Open a connection to a remote debugger.
460    NAME is the filename used for communication, then a space,
461    then the baud rate.
462  */
463
464 static int baudrate = 9600;
465 static void
466 adapt_open (name, from_tty)
467      char *name;
468      int from_tty;
469 {
470   TERMINAL sg;
471   unsigned int prl;
472   char *p;
473
474   /* Find the first whitespace character, it separates dev_name from
475      prog_name.  */
476   if (name == 0)
477     goto erroid;
478
479   for (p = name;
480        *p != '\0' && !isspace (*p); p++)
481     ;
482   if (*p == '\0')
483 erroid:
484     error ("\
485 Please include the name of the device for the serial port,\n\
486 the baud rate, and the name of the program to run on the remote system.");
487   dev_name = (char*)malloc(p - name + 1);
488   strncpy (dev_name, name, p - name);
489   dev_name[p - name] = '\0';
490
491   /* Skip over the whitespace after dev_name */
492   for (; isspace (*p); p++)
493     /*EMPTY*/;
494   
495   if (1 != sscanf (p, "%d ", &baudrate))
496     goto erroid;
497
498   /* Skip the number and then the spaces */
499   for (; isdigit (*p); p++)
500     /*EMPTY*/;
501   for (; isspace (*p); p++)
502     /*EMPTY*/;
503   
504   if (prog_name != NULL)
505     free (prog_name);
506   prog_name = savestring (p, strlen (p));
507
508   adapt_close (0);
509
510   adapt_desc = open (dev_name, O_RDWR);
511   if (adapt_desc < 0)
512     perror_with_name (dev_name);
513   ioctl (adapt_desc, TIOCGETP, &sg);
514 #ifdef HAVE_TERMIO
515   sg.c_cc[VMIN] = 0;            /* read with timeout.  */
516   sg.c_cc[VTIME] = timeout * 10;
517   sg.c_lflag &= ~(ICANON | ECHO);
518   sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
519 #else
520   sg.sg_ispeed = damn_b (baudrate);
521   sg.sg_ospeed = damn_b (baudrate);
522   sg.sg_flags |= RAW | ANYP;
523   sg.sg_flags &= ~ECHO;
524 #endif
525
526   ioctl (adapt_desc, TIOCSETP, &sg);
527   adapt_stream = fdopen (adapt_desc, "r+");
528
529   push_target (&adapt_ops);
530
531 #ifndef HAVE_TERMIO
532 #ifndef NO_SIGINTERRUPT
533   /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
534      the read.  */
535   if (siginterrupt (SIGALRM, 1) != 0)
536     perror ("adapt_open: error in siginterrupt");
537 #endif
538
539   /* Set up read timeout timer.  */
540   if ((void (*)) signal (SIGALRM, adapt_timer) == (void (*)) -1)
541     perror ("adapt_open: error in signal");
542 #endif
543
544 #if defined (LOG_FILE)
545   log_file = fopen (LOG_FILE, "w");
546   if (log_file == NULL)
547     perror_with_name (LOG_FILE);
548 #endif
549
550   /* Put this port into NORMAL mode, send the 'normal' character */
551   write(adapt_desc, "\ 1", 1);    /* Control A */
552   write(adapt_desc, "\r", 1);   
553   expect_prompt ();
554   
555   /* Hello?  Are you there?  */
556   write (adapt_desc, "\r", 1);
557  
558   expect_prompt ();
559
560   /* Clear any break points */
561   adapt_clear_breakpoints();
562
563   /* Print out some stuff, letting the user now what's going on */
564   printf_filtered("Connected to an Adapt via %s.\n", dev_name);
565     /* FIXME: can this restriction be removed? */
566   printf_filtered("Remote debugging using virtual addresses works only\n");
567   printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n"); 
568   if (processor_type != a29k_freeze_mode) {
569         fprintf_filtered(stderr,
570         "Freeze-mode debugging not available, and can only be done on an A29050.\n");
571   }
572 }
573
574 /* Close out all files and local state before this target loses control. */
575
576 static void
577 adapt_close (quitting)
578      int quitting;
579 {
580
581   /* Clear any break points */
582   adapt_clear_breakpoints();
583
584   /* Put this port back into REMOTE mode */ 
585   if (adapt_stream) {
586      fflush(adapt_stream);
587      sleep(1);          /* Let any output make it all the way back */
588      write(adapt_desc, "R\r", 2);
589   }
590
591   /* Due to a bug in Unix, fclose closes not only the stdio stream,
592      but also the file descriptor.  So we don't actually close
593      adapt_desc.  */
594   if (adapt_stream)
595     fclose (adapt_stream);      /* This also closes adapt_desc */
596   if (adapt_desc >= 0)
597     /* close (adapt_desc); */
598
599   /* Do not try to close adapt_desc again, later in the program.  */
600   adapt_stream = NULL;
601   adapt_desc = -1;
602
603 #if defined (LOG_FILE)
604   if (log_file) {
605     if (ferror (log_file))
606       printf_filtered ("Error writing log file.\n");
607     if (fclose (log_file) != 0)
608       printf_filtered ("Error closing log file.\n");
609     log_file = NULL;
610   }
611 #endif
612 }
613
614 /* Attach to the target that is already loaded and possibly running */
615 static void
616 adapt_attach (args, from_tty)
617      char *args;
618      int from_tty;
619 {
620
621   if (from_tty)
622       printf_filtered ("Attaching to remote program %s.\n", prog_name);
623
624   /* Send the adapt a kill. It is ok if it is not already running */
625   fprintf(adapt_stream, "K\r"); fflush(adapt_stream);
626   expect_prompt();              /* Slurp the echo */
627 }
628
629
630 /* Terminate the open connection to the remote debugger.
631    Use this when you want to detach and do something else
632    with your gdb.  */
633 void
634 adapt_detach (args,from_tty)
635      char *args;
636      int from_tty;
637 {
638
639   if (adapt_stream) { /* Send it on its way (tell it to continue)  */
640         adapt_clear_breakpoints();
641         fprintf(adapt_stream,"G\r");
642   }
643  
644   pop_target();         /* calls adapt_close to do the real work */
645   if (from_tty)
646     printf_filtered ("Ending remote %s debugging\n", target_shortname);
647 }
648  
649 /* Tell the remote machine to resume.  */
650
651 void
652 adapt_resume (pid, step, sig)
653      int pid, step, sig;
654 {
655   if (step)     
656     {
657       write (adapt_desc, "t 1,s\r", 6);
658       /* Wait for the echo.  */
659       expect ("t 1,s\r\n");
660       /* Then comes a line containing the instruction we stepped to.  */
661       expect ("@");
662       /* Then we get the prompt.  */
663       expect_prompt ();
664
665       /* Force the next adapt_wait to return a trap.  Not doing anything
666          about I/O from the target means that the user has to type
667          "continue" to see any.  FIXME, this should be fixed.  */
668       need_artificial_trap = 1;
669     }
670   else
671     {
672       write (adapt_desc, "G\r", 2);
673       /* Swallow the echo.  */
674       expect_prompt(); 
675     }
676 }
677
678 /* Wait until the remote machine stops, then return,
679    storing status in STATUS just as `wait' would.  */
680
681 int
682 adapt_wait (status)
683      WAITTYPE *status;
684 {
685   /* Strings to look for.  '?' means match any single character.  
686      Note that with the algorithm we use, the initial character
687      of the string cannot recur in the string, or we will not
688      find some cases of the string in the input.  */
689   
690   static char bpt[] = "@";
691   /* It would be tempting to look for "\n[__exit + 0x8]\n"
692      but that requires loading symbols with "yc i" and even if
693      we did do that we don't know that the file has symbols.  */
694   static char exitmsg[] = "@????????I    JMPTI     GR121,LR0";
695   char *bp = bpt;
696   char *ep = exitmsg;
697
698   /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars.  */
699   char swallowed[50];
700   /* Current position in swallowed.  */
701   char *swallowed_p = swallowed;
702
703   int ch;
704   int ch_handled;
705   int old_timeout = timeout;
706   int old_immediate_quit = immediate_quit;
707
708   WSETEXIT ((*status), 0);
709
710   if (need_artificial_trap != 0)
711     {
712       WSETSTOP ((*status), SIGTRAP);
713       need_artificial_trap--;
714       return 0;
715     }
716
717   timeout = 0;          /* Don't time out -- user program is running. */
718   immediate_quit = 1;   /* Helps ability to QUIT */
719   while (1) {
720       QUIT;             /* Let user quit and leave process running */
721       ch_handled = 0;
722       ch = readchar ();
723       if (ch == *bp) {
724           bp++;
725           if (*bp == '\0')
726             break;
727           ch_handled = 1;
728
729           *swallowed_p++ = ch;
730       } else
731         bp = bpt;
732       if (ch == *ep || *ep == '?') {
733           ep++;
734           if (*ep == '\0')
735             break;
736
737           if (!ch_handled)
738             *swallowed_p++ = ch;
739           ch_handled = 1;
740       } else
741         ep = exitmsg;
742       if (!ch_handled) {
743           char *p;
744           /* Print out any characters which have been swallowed.  */
745           for (p = swallowed; p < swallowed_p; ++p)
746             putc (*p, stdout);
747           swallowed_p = swallowed;
748           putc (ch, stdout);
749       }
750   }
751   expect_prompt ();
752   if (*bp== '\0')
753     WSETSTOP ((*status), SIGTRAP);
754   else
755     WSETEXIT ((*status), 0);
756   timeout = old_timeout;
757   immediate_quit = old_immediate_quit;
758   return 0;
759 }
760
761 /* Return the name of register number REGNO
762    in the form input and output by adapt.
763
764    Returns a pointer to a static buffer containing the answer.  */
765 static char *
766 get_reg_name (regno)
767      int regno;
768 {
769   static char buf[80];
770   if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32 )
771     sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
772 #if defined(GR64_REGNUM)
773   else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
774     sprintf (buf, "GR%03d", regno - GR64_REGNUM + 64);
775 #endif
776   else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
777     sprintf (buf, "LR%03d", regno - LR0_REGNUM);
778   else if (regno == Q_REGNUM) 
779     strcpy (buf, "SR131");
780   else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
781     sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
782   else if (regno == ALU_REGNUM)
783     strcpy (buf, "SR132");
784   else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
785     sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
786   else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM) {
787     /* When a 29050 is in freeze-mode, read shadow pcs instead */
788     if ((regno >= NPC_REGNUM && regno <= PC2_REGNUM) && USE_SHADOW_PC)
789         sprintf (buf, "SR%03d", regno - NPC_REGNUM + 20);
790     else
791         sprintf (buf, "SR%03d", regno - VAB_REGNUM);
792   }
793   else if (regno == GR1_REGNUM)
794     strcpy (buf, "GR001");
795   return buf;
796 }
797
798 /* Read the remote registers.  */
799
800 static void
801 adapt_fetch_registers ()
802 {
803   int reg_index;
804   int regnum_index;
805   char tempbuf[10];
806   int   sreg_buf[16];
807   int i,j;
808
809 /* 
810  * Global registers
811  */
812 #if defined(GR64_REGNUM)
813   write (adapt_desc, "dw gr64,gr95\r", 13);
814   for (reg_index = 64, regnum_index = GR64_REGNUM;
815        reg_index < 96;
816        reg_index += 4, regnum_index += 4)
817     {
818       sprintf (tempbuf, "GR%03d ", reg_index);
819       expect (tempbuf);
820       get_hex_regs (4, regnum_index);
821       expect ("\n");
822     }
823 #endif
824   write (adapt_desc, "dw gr96,gr127\r", 14);
825   for (reg_index = 96, regnum_index = GR96_REGNUM;
826        reg_index < 128;
827        reg_index += 4, regnum_index += 4)
828     {
829       sprintf (tempbuf, "GR%03d ", reg_index);
830       expect (tempbuf);
831       get_hex_regs (4, regnum_index);
832       expect ("\n");
833     }
834
835 /* 
836  * Local registers
837  */
838   for (i = 0; i < 128; i += 32)
839     {
840       /* The PC has a tendency to hang if we get these
841          all in one fell swoop ("dw lr0,lr127").  */
842       sprintf (tempbuf, "dw lr%d\r", i);
843       write (adapt_desc, tempbuf, strlen (tempbuf));
844       for (reg_index = i, regnum_index = LR0_REGNUM + i;
845            reg_index < i + 32;
846            reg_index += 4, regnum_index += 4)
847         {
848           sprintf (tempbuf, "LR%03d ", reg_index);
849           expect (tempbuf);
850           get_hex_regs (4, regnum_index);
851           expect ("\n");
852         }
853     }
854
855 /* 
856  * Special registers
857  */
858   sprintf (tempbuf, "dw sr0\r");
859   write (adapt_desc, tempbuf, strlen (tempbuf));
860   for (i=0 ; i<4 ; i++) {                       /* SR0 - SR14 */
861         sprintf (tempbuf, "SR%3d",i*4);
862         expect(tempbuf);
863         for (j=0 ; j < (i==3 ? 3 : 4) ; j++)
864                 sreg_buf[i*4 + j] = get_hex_word();
865   }             
866   expect_prompt();
867   /* 
868    * Read the pcs individually if we are in freeze mode.
869    * See get_reg_name(), it translates the register names for the pcs to
870    * the names of the shadow pcs.
871    */ 
872   if (USE_SHADOW_PC)  {
873           sreg_buf[10] = read_register(NPC_REGNUM);     /* pc0 */
874           sreg_buf[11] = read_register(PC_REGNUM);      /* pc1 */
875           sreg_buf[12] = read_register(PC2_REGNUM);     /* pc2 */
876   }
877   for (i=0 ; i<14 ; i++)                /* Supply vab -> lru */
878         supply_register(VAB_REGNUM+i, (char *) &sreg_buf[i]);
879   sprintf (tempbuf, "dw sr128\r");
880   write (adapt_desc, tempbuf, strlen (tempbuf));
881   for (i=0 ; i<2 ; i++) {                       /* SR128 - SR135 */
882         sprintf (tempbuf, "SR%3d",128 + i*4);
883         expect(tempbuf);
884         for (j=0 ; j<4 ; j++)
885                 sreg_buf[i*4 + j] = get_hex_word();
886   }             
887   expect_prompt();
888   supply_register(IPC_REGNUM,(char *) &sreg_buf[0]);
889   supply_register(IPA_REGNUM,(char *) &sreg_buf[1]);
890   supply_register(IPB_REGNUM,(char *) &sreg_buf[2]);
891   supply_register(Q_REGNUM,  (char *) &sreg_buf[3]);
892                 /* Skip ALU */
893   supply_register(BP_REGNUM, (char *) &sreg_buf[5]);
894   supply_register(FC_REGNUM, (char *) &sreg_buf[6]);
895   supply_register(CR_REGNUM, (char *) &sreg_buf[7]);
896
897   /* There doesn't seem to be any way to get these.  */
898   {
899     int val = -1;
900     supply_register (FPE_REGNUM, (char *) &val);
901     supply_register (INTE_REGNUM, (char *) &val);
902     supply_register (FPS_REGNUM, (char *) &val);
903     supply_register (EXO_REGNUM, (char *) &val);
904   }
905
906   write (adapt_desc, "dw gr1,gr1\r", 11);
907   expect ("GR001 ");
908   get_hex_regs (1, GR1_REGNUM);
909   expect_prompt ();
910 }
911
912 /* Fetch register REGNO, or all registers if REGNO is -1.
913  */
914 static void
915 adapt_fetch_register (regno)
916      int regno;
917 {
918   if (regno == -1)
919     adapt_fetch_registers ();
920   else
921     {
922       char *name = get_reg_name (regno);
923       fprintf (adapt_stream, "dw %s,%s\r", name, name);
924       expect (name);
925       expect (" ");
926       get_hex_regs (1, regno);
927       expect_prompt ();
928     }
929 }
930
931 /* Store the remote registers from the contents of the block REGS.  */
932
933 static void
934 adapt_store_registers ()
935 {
936   int i, j;
937
938   fprintf (adapt_stream, "s gr1,%x\r", read_register (GR1_REGNUM));
939   expect_prompt ();
940
941 #if defined(GR64_REGNUM)
942   for (j = 0; j < 32; j += 16)
943     {
944       fprintf (adapt_stream, "s gr%d,", j + 64);
945       for (i = 0; i < 15; ++i) 
946         fprintf (adapt_stream, "%x,", read_register (GR64_REGNUM + j + i));
947       fprintf (adapt_stream, "%x\r", read_register (GR64_REGNUM + j + 15));
948       expect_prompt ();
949     }
950 #endif
951   for (j = 0; j < 32; j += 16)
952     {
953       fprintf (adapt_stream, "s gr%d,", j + 96);
954       for (i = 0; i < 15; ++i) 
955         fprintf (adapt_stream, "%x,", read_register (GR96_REGNUM + j + i));
956       fprintf (adapt_stream, "%x\r", read_register (GR96_REGNUM + j + 15));
957       expect_prompt ();
958     }
959
960   for (j = 0; j < 128; j += 16)
961     {
962       fprintf (adapt_stream, "s lr%d,", j);
963       for (i = 0; i < 15; ++i) 
964         fprintf (adapt_stream, "%x,", read_register (LR0_REGNUM + j + i));
965       fprintf (adapt_stream, "%x\r", read_register (LR0_REGNUM + j + 15));
966       expect_prompt ();
967     }
968
969   fprintf (adapt_stream, "s sr128,%x,%x,%x\r", read_register (IPC_REGNUM),
970            read_register (IPA_REGNUM), read_register (IPB_REGNUM));
971   expect_prompt ();
972   fprintf (adapt_stream, "s sr133,%x,%x,%x\r", read_register (BP_REGNUM),
973            read_register (FC_REGNUM), read_register (CR_REGNUM));
974   expect_prompt ();
975   fprintf (adapt_stream, "s sr131,%x\r", read_register (Q_REGNUM));
976   expect_prompt ();
977   fprintf (adapt_stream, "s sr0,");
978   for (i=0 ; i<7 ; ++i)
979     fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
980   expect_prompt ();
981   fprintf (adapt_stream, "s sr7,");
982   for (i=7; i<14 ; ++i)
983     fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
984   expect_prompt ();
985 }
986
987 /* Store register REGNO, or all if REGNO == -1.
988    Return errno value.  */
989 void
990 adapt_store_register (regno)
991      int regno;
992 {
993   /* printf("adapt_store_register() called.\n"); fflush(stdout); /* */
994   if (regno == -1)
995     adapt_store_registers ();
996   else
997     {
998       char *name = get_reg_name (regno);
999       fprintf (adapt_stream, "s %s,%x\r", name, read_register (regno));
1000       /* Setting GR1 changes the numbers of all the locals, so
1001          invalidate the register cache.  Do this *after* calling
1002          read_register, because we want read_register to return the
1003          value that write_register has just stuffed into the registers
1004          array, not the value of the register fetched from the
1005          inferior.  */
1006       if (regno == GR1_REGNUM)
1007         registers_changed ();
1008       expect_prompt ();
1009     }
1010 }
1011
1012 /* Get ready to modify the registers array.  On machines which store
1013    individual registers, this doesn't need to do anything.  On machines
1014    which store all the registers in one fell swoop, this makes sure
1015    that registers contains all the registers from the program being
1016    debugged.  */
1017
1018 void
1019 adapt_prepare_to_store ()
1020 {
1021   /* Do nothing, since we can store individual regs */
1022 }
1023
1024 static CORE_ADDR 
1025 translate_addr(addr)
1026 CORE_ADDR addr;
1027 {
1028 #if defined(KERNEL_DEBUGGING)
1029         /* Check for a virtual address in the kernel */
1030         /* Assume physical address of ublock is in  paddr_u register */
1031         if (addr >= UVADDR) {
1032                 /* PADDR_U register holds the physical address of the ublock */
1033                 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM); 
1034                 return(i + addr - (CORE_ADDR)UVADDR);
1035         } else {
1036                 return(addr);
1037         }
1038 #else
1039         return(addr);
1040 #endif
1041 }
1042
1043
1044 /* FIXME!  Merge these two.  */
1045 int
1046 adapt_xfer_inferior_memory (memaddr, myaddr, len, write)
1047      CORE_ADDR memaddr;
1048      char *myaddr;
1049      int len;
1050      int write;
1051 {
1052
1053   memaddr = translate_addr(memaddr);
1054
1055   if (write)
1056     return adapt_write_inferior_memory (memaddr, myaddr, len);
1057   else
1058     return adapt_read_inferior_memory (memaddr, myaddr, len);
1059 }
1060
1061 void
1062 adapt_files_info ()
1063 {
1064   printf_filtered("\tAttached to %s at %d baud and running program %s\n",
1065           dev_name, baudrate, prog_name);
1066   printf_filtered("\ton an %s processor.\n", processor_name[processor_type]);
1067 }
1068
1069 /* Copy LEN bytes of data from debugger memory at MYADDR
1070    to inferior's memory at MEMADDR.  Returns errno value.  
1071  * sb/sh instructions don't work on unaligned addresses, when TU=1. 
1072  */
1073 int
1074 adapt_write_inferior_memory (memaddr, myaddr, len)
1075      CORE_ADDR memaddr;
1076      char *myaddr;
1077      int len;
1078 {
1079   int i;
1080   unsigned int cps;
1081
1082   /* Turn TU bit off so we can do 'sb' commands */
1083   cps = read_register(CPS_REGNUM);
1084   if (cps & 0x00000800)
1085         write_register(CPS_REGNUM,cps&~(0x00000800));
1086
1087   for (i = 0; i < len; i++)
1088     {
1089       if ((i % 16) == 0)
1090         fprintf (adapt_stream, "sb %x,", memaddr + i);
1091       if ((i % 16) == 15 || i == len - 1)
1092         {
1093           fprintf (adapt_stream, "%x\r", ((unsigned char *)myaddr)[i]);
1094           expect_prompt ();
1095         }
1096       else
1097         fprintf (adapt_stream, "%x,", ((unsigned char *)myaddr)[i]);
1098     }
1099   /* Restore the old value of cps if the TU bit was on */
1100   if (cps & 0x00000800)
1101         write_register(CPS_REGNUM,cps);
1102   return len;
1103 }
1104
1105 /* Read LEN bytes from inferior memory at MEMADDR.  Put the result
1106    at debugger address MYADDR.  Returns errno value.  */
1107 int
1108 adapt_read_inferior_memory(memaddr, myaddr, len)
1109      CORE_ADDR memaddr;
1110      char *myaddr;
1111      int len;
1112 {
1113   int i;
1114
1115   /* Number of bytes read so far.  */
1116   int count;
1117
1118   /* Starting address of this pass.  */
1119   unsigned long startaddr;
1120
1121   /* Number of bytes to read in this pass.  */
1122   int len_this_pass;
1123
1124   /* Note that this code works correctly if startaddr is just less
1125      than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
1126      thing).  That is, something like
1127      adapt_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
1128      works--it never adds len to memaddr and gets 0.  */
1129   /* However, something like
1130      adapt_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
1131      doesn't need to work.  Detect it and give up if there's an attempt
1132      to do that.  */
1133
1134   if (((memaddr - 1) + len) < memaddr)
1135     return EIO;
1136   
1137   startaddr = memaddr;
1138   count = 0;
1139   while (count < len)
1140     {
1141       len_this_pass = 16;
1142       if ((startaddr % 16) != 0)
1143         len_this_pass -= startaddr % 16;
1144       if (len_this_pass > (len - count))
1145         len_this_pass = (len - count);
1146
1147       fprintf (adapt_stream, "db %x,%x\r", startaddr,
1148                (startaddr - 1) + len_this_pass);
1149
1150 #ifdef NOTDEF   /* Why do this */
1151       expect ("\n");
1152       /* Look for 8 hex digits.  */
1153       i = 0;
1154       while (1)
1155         {
1156           if (isxdigit (readchar ()))
1157             ++i;
1158           else
1159             {
1160               expect_prompt ();
1161               error ("Hex digit expected from remote system.");
1162             }
1163           if (i >= 8)
1164             break;
1165         }
1166 #endif /* NOTDEF */
1167
1168       expect ("  ");
1169
1170       for (i = 0; i < len_this_pass; i++)
1171         get_hex_byte (&myaddr[count++]);
1172
1173       expect_prompt ();
1174
1175       startaddr += len_this_pass;
1176     }
1177   return count;
1178 }
1179
1180 #define MAX_BREAKS      8
1181 static int num_brkpts=0;
1182 static int
1183 adapt_insert_breakpoint(addr, save)
1184 CORE_ADDR       addr;
1185 char            *save;  /* Throw away, let adapt save instructions */
1186 {
1187   if (num_brkpts < MAX_BREAKS) {
1188         num_brkpts++;
1189         fprintf (adapt_stream, "B %x", addr);
1190         fprintf (adapt_stream, "\r");
1191         expect_prompt ();
1192         return(0);      /* Success */
1193   } else {
1194         fprintf_filtered(stderr,
1195                 "Too many break points, break point not installed\n");
1196         return(1);      /* Failure */
1197   }
1198
1199 }
1200 static int
1201 adapt_remove_breakpoint(addr, save)
1202 CORE_ADDR       addr;
1203 char            *save;  /* Throw away, let adapt save instructions */
1204 {
1205   if (num_brkpts > 0) {
1206           num_brkpts--;
1207           fprintf (adapt_stream, "BR %x", addr);
1208           fprintf (adapt_stream, "\r");
1209           fflush (adapt_stream);
1210           expect_prompt ();
1211   }
1212   return(0);
1213 }
1214
1215 /* Clear the adapts notion of what the break points are */
1216 static int
1217 adapt_clear_breakpoints() 
1218
1219   if (adapt_stream) {
1220         fprintf (adapt_stream, "BR");   /* Clear all break points */
1221         fprintf (adapt_stream, "\r");
1222         fflush(adapt_stream);
1223         expect_prompt ();
1224   }
1225   num_brkpts = 0;
1226 }
1227 static void
1228 adapt_mourn() 
1229
1230   adapt_clear_breakpoints();
1231   pop_target ();                /* Pop back to no-child state */
1232   generic_mourn_inferior ();
1233 }
1234
1235 /* Display everthing we read in from the adapt until we match/see the
1236  * specified string
1237  */
1238 static int
1239 display_until(str)
1240 char    *str;
1241 {
1242         int     i=0,j,c;
1243
1244         while (c=readchar()) {
1245                 if (c==str[i]) {
1246                         i++;
1247                         if (i == strlen(str)) return;
1248                 } else {
1249                         if (i) {
1250                             for (j=0 ; j<i ; j++) /* Put everthing we matched */
1251                                 putchar(str[j]);
1252                             i=0;
1253                         }
1254                         putchar(c);
1255                 }       
1256         }
1257
1258 }
1259
1260
1261 /* Put a command string, in args, out to the adapt.  The adapt is assumed to
1262    be in raw mode, all writing/reading done through adapt_desc.
1263    Ouput from the adapt is placed on the users terminal until the
1264    prompt from the adapt is seen.
1265    FIXME: Can't handle commands that take input.  */
1266
1267 void
1268 adapt_com (args, fromtty)
1269      char       *args;
1270      int        fromtty;
1271 {
1272         if (!adapt_stream) {
1273                 printf_filtered("Adapt not open.  Use the 'target' command to open.\n");
1274                 return;
1275         }
1276
1277         /* Clear all input so only command relative output is displayed */
1278         slurp_input();  
1279
1280         switch(islower(args[0]) ? toupper(args[0]) : args[0]) {
1281         default:
1282                 printf_filtered("Unknown/Unimplemented adapt command '%s'\n",args);
1283                 break;
1284         case 'G':       /* Go, begin execution */
1285                 write(adapt_desc,args,strlen(args));
1286                 write(adapt_desc,"\r",1);
1287                 expect_prompt();
1288                 break;
1289         case 'B':       /* Break points, B or BR */
1290         case 'C':       /* Check current 29k status (running/halted) */
1291         case 'D':       /* Display data/registers */ 
1292         case 'I':       /* Input from i/o space */
1293         case 'J':       /* Jam an instruction */
1294         case 'K':       /* Kill, stop execution */
1295         case 'L':       /* Disassemble */
1296         case 'O':       /* Output to i/o space */
1297         case 'T':       /* Trace */ 
1298         case 'P':       /* Pulse an input line */ 
1299         case 'X':       /* Examine special purpose registers */ 
1300         case 'Z':       /* Display trace buffer */ 
1301                 write(adapt_desc,args,strlen(args));
1302                 write(adapt_desc,"\r",1);
1303                 expect(args);           /* Don't display the command */
1304                 display_until("# ");
1305                 break;
1306         /* Begin commands that take input in the form 'c x,y[,z...]' */
1307         case 'S':       /* Set memory or register */
1308                 if (strchr(args,',')) { /* Assume it is properly formatted */
1309                         write(adapt_desc,args,strlen(args));
1310                         write(adapt_desc,"\r",1);
1311                         expect_prompt();
1312                 }
1313                 break;
1314         }
1315 }
1316
1317 /* Define the target subroutine names */
1318
1319 struct target_ops adapt_ops = {
1320         "adapt", "Remote AMD `Adapt' target",
1321         "Remote debug an AMD 290*0 using an `Adapt' monitor via RS232",
1322         adapt_open, adapt_close, 
1323         adapt_attach, adapt_detach, adapt_resume, adapt_wait,
1324         adapt_fetch_register, adapt_store_register,
1325         adapt_prepare_to_store,
1326         adapt_xfer_inferior_memory, 
1327         adapt_files_info,
1328         adapt_insert_breakpoint, adapt_remove_breakpoint, /* Breakpoints */
1329         0, 0, 0, 0, 0,          /* Terminal handling */
1330         adapt_kill,             /* FIXME, kill */
1331         adapt_load, 
1332         0,                      /* lookup_symbol */
1333         adapt_create_inferior,  /* create_inferior */ 
1334         adapt_mourn,            /* mourn_inferior FIXME */
1335         0, /* can_run */
1336         0, /* notice_signals */
1337         process_stratum, 0, /* next */
1338         1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
1339         0,0,            /* Section pointers */
1340         OPS_MAGIC,              /* Always the last thing */
1341 };
1342
1343 void
1344 _initialize_remote_adapt ()
1345 {
1346   add_target (&adapt_ops);
1347   add_com ("adapt <command>", class_obscure, adapt_com,
1348         "Send a command to the AMD Adapt remote monitor.");
1349 }
This page took 0.096891 seconds and 4 git commands to generate.