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