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