* breakpoint.c, breakpoint.h (breakpoint_init_inferior): New function
[deliverable/binutils-gdb.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 (wood@lab.ultra.nyu.edu).
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.056625 seconds and 4 git commands to generate.