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