* config/pa/tm-hppa.h: Define lots register offsets needed by
[deliverable/binutils-gdb.git] / gdb / remote-adapt.c
CommitLineData
7c18a68f 1/* Remote debugging interface for AMD 290*0 Adapt Monitor Version 2.1d18.
e17960fb 2 Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
7c18a68f
JG
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
7c18a68f 32#include "defs.h"
d747e0af 33#include <string.h>
7c18a68f
JG
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 */
46extern int stop_soon_quietly; /* for wait_for_inferior */
47
7c18a68f
JG
48/* Forward data declarations */
49extern struct target_ops adapt_ops; /* Forward declaration */
50
51/* Forward function declarations */
52static void adapt_fetch_registers ();
e95bfbf1 53static void adapt_store_registers ();
15f27b29 54static void adapt_close ();
e36ca74a 55static int adapt_clear_breakpoints();
7c18a68f 56
7c18a68f 57#define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
ca0622e7 58#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
7c18a68f 59
7c18a68f
JG
60/* Can't seem to get binary coff working */
61#define ASCII_COFF /* Adapt will be downloaded with ascii coff */
62
ca0622e7 63/* FIXME: Replace with `set remotedebug'. */
7c18a68f
JG
64#define LOG_FILE "adapt.log"
65#if defined (LOG_FILE)
66FILE *log_file=NULL;
67#endif
68
69static int timeout = 5;
70static 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. */
75int adapt_desc = -1;
76
77/* stream which is fdopen'd from adapt_desc. Only valid when
78 adapt_desc != -1. */
79FILE *adapt_stream;
80
81#define ON 1
82#define OFF 0
83static void
84rawmode(desc, turnon)
85int desc;
86int 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 */
112slurp_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. */
128static int
129readchar ()
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. */
159static void
160expect (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. */
197static void
198expect_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). */
211static int
212get_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. */
237static void
238get_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 */
249static long
250get_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. */
262static void
263get_hex_regs (n, regno)
264 int n;
265 int regno;
266{
267 long val;
268 while (n--) {
269 val = get_hex_word();
a058c1e8 270 supply_register(regno++,(char *) &val);
7c18a68f
JG
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
281volatile int n_alarms;
282
283void
284adapt_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. */
295static 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
301static int need_artificial_trap = 0;
302
303void
304adapt_kill(arg,from_tty)
305char *arg;
306int from_tty;
307{
7c18a68f
JG
308 fprintf (adapt_stream, "K");
309 fprintf (adapt_stream, "\r");
310 expect_prompt ();
7c18a68f
JG
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 */
316static void
317adapt_load(args,fromtty)
318char *args;
319int fromtty;
320{
321 FILE *fp;
322 int n;
323 char buffer[1024];
324
7c18a68f
JG
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 ();
7c18a68f
JG
364}
365
366/* This is called not only when we first attach, but also when the
367 user types "run" after having attached. */
368void
369adapt_create_inferior (execfile, args, env)
370 char *execfile;
371 char *args;
372 char **env;
373{
374 int entry_pt;
375
7c18a68f
JG
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 */
45dc9be3 410 proceed(entry_pt, TARGET_SIGNAL_DEFAULT, 0);
7c18a68f
JG
411#endif
412
413 } else {
414 printf_filtered("Adapt not open yet.\n");
415 }
7c18a68f
JG
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
428static 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
448static 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
464static int baudrate = 9600;
465static void
466adapt_open (name, from_tty)
467 char *name;
468 int from_tty;
469{
470 TERMINAL sg;
471 unsigned int prl;
472 char *p;
473
7c18a68f
JG
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')
483erroid:
484 error ("\
485Please include the name of the device for the serial port,\n\
486the 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);
7c18a68f
JG
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
7c18a68f 563 /* Print out some stuff, letting the user now what's going on */
ca0622e7 564 printf_filtered("Connected to an Adapt via %s.\n", dev_name);
7c18a68f
JG
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");
ca0622e7 568 if (processor_type != a29k_freeze_mode) {
7c18a68f
JG
569 fprintf_filtered(stderr,
570 "Freeze-mode debugging not available, and can only be done on an A29050.\n");
571 }
7c18a68f
JG
572}
573
574/* Close out all files and local state before this target loses control. */
575
576static void
577adapt_close (quitting)
578 int quitting;
579{
580
7c18a68f
JG
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
7c18a68f
JG
612}
613
614/* Attach to the target that is already loaded and possibly running */
615static void
616adapt_attach (args, from_tty)
617 char *args;
618 int from_tty;
619{
620
7c18a68f
JG
621 if (from_tty)
622 printf_filtered ("Attaching to remote program %s.\n", prog_name);
623
7c18a68f
JG
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 */
7c18a68f
JG
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. */
633void
634adapt_detach (args,from_tty)
635 char *args;
636 int from_tty;
637{
836e343b 638
7c18a68f
JG
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);
7c18a68f
JG
647}
648
649/* Tell the remote machine to resume. */
650
651void
25286543 652adapt_resume (pid, step, sig)
67ac9759
JK
653 int pid, step;
654 enum target_signal sig;
7c18a68f 655{
7c18a68f
JG
656 if (step)
657 {
658 write (adapt_desc, "t 1,s\r", 6);
659 /* Wait for the echo. */
660 expect ("t 1,s\r\n");
661 /* Then comes a line containing the instruction we stepped to. */
662 expect ("@");
663 /* Then we get the prompt. */
664 expect_prompt ();
665
666 /* Force the next adapt_wait to return a trap. Not doing anything
667 about I/O from the target means that the user has to type
668 "continue" to see any. FIXME, this should be fixed. */
669 need_artificial_trap = 1;
670 }
671 else
672 {
673 write (adapt_desc, "G\r", 2);
674 /* Swallow the echo. */
675 expect_prompt();
676 }
7c18a68f
JG
677}
678
679/* Wait until the remote machine stops, then return,
680 storing status in STATUS just as `wait' would. */
681
682int
683adapt_wait (status)
67ac9759 684 struct target_waitstatus *status;
7c18a68f
JG
685{
686 /* Strings to look for. '?' means match any single character.
687 Note that with the algorithm we use, the initial character
688 of the string cannot recur in the string, or we will not
689 find some cases of the string in the input. */
690
691 static char bpt[] = "@";
692 /* It would be tempting to look for "\n[__exit + 0x8]\n"
693 but that requires loading symbols with "yc i" and even if
694 we did do that we don't know that the file has symbols. */
695 static char exitmsg[] = "@????????I JMPTI GR121,LR0";
696 char *bp = bpt;
697 char *ep = exitmsg;
698
699 /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
700 char swallowed[50];
701 /* Current position in swallowed. */
702 char *swallowed_p = swallowed;
703
704 int ch;
705 int ch_handled;
706 int old_timeout = timeout;
707 int old_immediate_quit = immediate_quit;
708
67ac9759
JK
709 status->kind = TARGET_WAITKIND_EXITED;
710 status->value.integer = 0;
7c18a68f
JG
711
712 if (need_artificial_trap != 0)
713 {
67ac9759
JK
714 status->kind = TARGET_WAITKIND_STOPPED;
715 status->value.sig = TARGET_SIGNAL_TRAP;
7c18a68f
JG
716 need_artificial_trap--;
717 return 0;
718 }
719
720 timeout = 0; /* Don't time out -- user program is running. */
721 immediate_quit = 1; /* Helps ability to QUIT */
722 while (1) {
723 QUIT; /* Let user quit and leave process running */
724 ch_handled = 0;
725 ch = readchar ();
726 if (ch == *bp) {
727 bp++;
728 if (*bp == '\0')
729 break;
730 ch_handled = 1;
731
732 *swallowed_p++ = ch;
733 } else
734 bp = bpt;
735 if (ch == *ep || *ep == '?') {
736 ep++;
737 if (*ep == '\0')
738 break;
739
740 if (!ch_handled)
741 *swallowed_p++ = ch;
742 ch_handled = 1;
743 } else
744 ep = exitmsg;
745 if (!ch_handled) {
746 char *p;
747 /* Print out any characters which have been swallowed. */
748 for (p = swallowed; p < swallowed_p; ++p)
749 putc (*p, stdout);
750 swallowed_p = swallowed;
751 putc (ch, stdout);
752 }
753 }
754 expect_prompt ();
755 if (*bp== '\0')
67ac9759
JK
756 {
757 status->kind = TARGET_WAITKIND_STOPPED;
758 status->value.sig = TARGET_SIGNAL_TRAP;
759 }
7c18a68f 760 else
67ac9759
JK
761 {
762 status->kind = TARGET_WAITKIND_EXITED;
763 status->value.integer = 0;
764 }
7c18a68f
JG
765 timeout = old_timeout;
766 immediate_quit = old_immediate_quit;
7c18a68f
JG
767 return 0;
768}
769
770/* Return the name of register number REGNO
771 in the form input and output by adapt.
772
773 Returns a pointer to a static buffer containing the answer. */
774static char *
775get_reg_name (regno)
776 int regno;
777{
778 static char buf[80];
779 if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32 )
780 sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
781#if defined(GR64_REGNUM)
782 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
783 sprintf (buf, "GR%03d", regno - GR64_REGNUM + 64);
784#endif
785 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
786 sprintf (buf, "LR%03d", regno - LR0_REGNUM);
787 else if (regno == Q_REGNUM)
788 strcpy (buf, "SR131");
789 else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
790 sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
791 else if (regno == ALU_REGNUM)
792 strcpy (buf, "SR132");
793 else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
794 sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
795 else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM) {
796 /* When a 29050 is in freeze-mode, read shadow pcs instead */
797 if ((regno >= NPC_REGNUM && regno <= PC2_REGNUM) && USE_SHADOW_PC)
798 sprintf (buf, "SR%03d", regno - NPC_REGNUM + 20);
799 else
800 sprintf (buf, "SR%03d", regno - VAB_REGNUM);
801 }
802 else if (regno == GR1_REGNUM)
803 strcpy (buf, "GR001");
804 return buf;
805}
806
807/* Read the remote registers. */
808
809static void
810adapt_fetch_registers ()
811{
812 int reg_index;
813 int regnum_index;
814 char tempbuf[10];
815 int sreg_buf[16];
816 int i,j;
817
7c18a68f
JG
818/*
819 * Global registers
820 */
821#if defined(GR64_REGNUM)
822 write (adapt_desc, "dw gr64,gr95\r", 13);
823 for (reg_index = 64, regnum_index = GR64_REGNUM;
824 reg_index < 96;
825 reg_index += 4, regnum_index += 4)
826 {
827 sprintf (tempbuf, "GR%03d ", reg_index);
828 expect (tempbuf);
829 get_hex_regs (4, regnum_index);
830 expect ("\n");
831 }
832#endif
833 write (adapt_desc, "dw gr96,gr127\r", 14);
834 for (reg_index = 96, regnum_index = GR96_REGNUM;
835 reg_index < 128;
836 reg_index += 4, regnum_index += 4)
837 {
838 sprintf (tempbuf, "GR%03d ", reg_index);
839 expect (tempbuf);
840 get_hex_regs (4, regnum_index);
841 expect ("\n");
842 }
843
844/*
845 * Local registers
846 */
847 for (i = 0; i < 128; i += 32)
848 {
849 /* The PC has a tendency to hang if we get these
850 all in one fell swoop ("dw lr0,lr127"). */
851 sprintf (tempbuf, "dw lr%d\r", i);
852 write (adapt_desc, tempbuf, strlen (tempbuf));
853 for (reg_index = i, regnum_index = LR0_REGNUM + i;
854 reg_index < i + 32;
855 reg_index += 4, regnum_index += 4)
856 {
857 sprintf (tempbuf, "LR%03d ", reg_index);
858 expect (tempbuf);
859 get_hex_regs (4, regnum_index);
860 expect ("\n");
861 }
862 }
863
864/*
865 * Special registers
866 */
867 sprintf (tempbuf, "dw sr0\r");
868 write (adapt_desc, tempbuf, strlen (tempbuf));
869 for (i=0 ; i<4 ; i++) { /* SR0 - SR14 */
870 sprintf (tempbuf, "SR%3d",i*4);
871 expect(tempbuf);
872 for (j=0 ; j < (i==3 ? 3 : 4) ; j++)
873 sreg_buf[i*4 + j] = get_hex_word();
874 }
875 expect_prompt();
876 /*
877 * Read the pcs individually if we are in freeze mode.
878 * See get_reg_name(), it translates the register names for the pcs to
879 * the names of the shadow pcs.
880 */
881 if (USE_SHADOW_PC) {
882 sreg_buf[10] = read_register(NPC_REGNUM); /* pc0 */
883 sreg_buf[11] = read_register(PC_REGNUM); /* pc1 */
884 sreg_buf[12] = read_register(PC2_REGNUM); /* pc2 */
885 }
886 for (i=0 ; i<14 ; i++) /* Supply vab -> lru */
a058c1e8 887 supply_register(VAB_REGNUM+i, (char *) &sreg_buf[i]);
7c18a68f
JG
888 sprintf (tempbuf, "dw sr128\r");
889 write (adapt_desc, tempbuf, strlen (tempbuf));
890 for (i=0 ; i<2 ; i++) { /* SR128 - SR135 */
891 sprintf (tempbuf, "SR%3d",128 + i*4);
892 expect(tempbuf);
893 for (j=0 ; j<4 ; j++)
894 sreg_buf[i*4 + j] = get_hex_word();
895 }
896 expect_prompt();
a058c1e8
RP
897 supply_register(IPC_REGNUM,(char *) &sreg_buf[0]);
898 supply_register(IPA_REGNUM,(char *) &sreg_buf[1]);
899 supply_register(IPB_REGNUM,(char *) &sreg_buf[2]);
900 supply_register(Q_REGNUM, (char *) &sreg_buf[3]);
7c18a68f 901 /* Skip ALU */
a058c1e8
RP
902 supply_register(BP_REGNUM, (char *) &sreg_buf[5]);
903 supply_register(FC_REGNUM, (char *) &sreg_buf[6]);
904 supply_register(CR_REGNUM, (char *) &sreg_buf[7]);
7c18a68f
JG
905
906 /* There doesn't seem to be any way to get these. */
907 {
908 int val = -1;
a058c1e8
RP
909 supply_register (FPE_REGNUM, (char *) &val);
910 supply_register (INTE_REGNUM, (char *) &val);
911 supply_register (FPS_REGNUM, (char *) &val);
912 supply_register (EXO_REGNUM, (char *) &val);
7c18a68f
JG
913 }
914
915 write (adapt_desc, "dw gr1,gr1\r", 11);
916 expect ("GR001 ");
917 get_hex_regs (1, GR1_REGNUM);
918 expect_prompt ();
7c18a68f
JG
919}
920
921/* Fetch register REGNO, or all registers if REGNO is -1.
922 */
923static void
924adapt_fetch_register (regno)
925 int regno;
926{
7c18a68f
JG
927 if (regno == -1)
928 adapt_fetch_registers ();
929 else
930 {
931 char *name = get_reg_name (regno);
932 fprintf (adapt_stream, "dw %s,%s\r", name, name);
933 expect (name);
934 expect (" ");
935 get_hex_regs (1, regno);
936 expect_prompt ();
937 }
7c18a68f
JG
938}
939
940/* Store the remote registers from the contents of the block REGS. */
941
e95bfbf1 942static void
7c18a68f
JG
943adapt_store_registers ()
944{
945 int i, j;
946
7c18a68f
JG
947 fprintf (adapt_stream, "s gr1,%x\r", read_register (GR1_REGNUM));
948 expect_prompt ();
949
950#if defined(GR64_REGNUM)
951 for (j = 0; j < 32; j += 16)
952 {
953 fprintf (adapt_stream, "s gr%d,", j + 64);
954 for (i = 0; i < 15; ++i)
955 fprintf (adapt_stream, "%x,", read_register (GR64_REGNUM + j + i));
956 fprintf (adapt_stream, "%x\r", read_register (GR64_REGNUM + j + 15));
957 expect_prompt ();
958 }
959#endif
960 for (j = 0; j < 32; j += 16)
961 {
962 fprintf (adapt_stream, "s gr%d,", j + 96);
963 for (i = 0; i < 15; ++i)
964 fprintf (adapt_stream, "%x,", read_register (GR96_REGNUM + j + i));
965 fprintf (adapt_stream, "%x\r", read_register (GR96_REGNUM + j + 15));
966 expect_prompt ();
967 }
968
969 for (j = 0; j < 128; j += 16)
970 {
971 fprintf (adapt_stream, "s lr%d,", j);
972 for (i = 0; i < 15; ++i)
973 fprintf (adapt_stream, "%x,", read_register (LR0_REGNUM + j + i));
974 fprintf (adapt_stream, "%x\r", read_register (LR0_REGNUM + j + 15));
975 expect_prompt ();
976 }
977
978 fprintf (adapt_stream, "s sr128,%x,%x,%x\r", read_register (IPC_REGNUM),
979 read_register (IPA_REGNUM), read_register (IPB_REGNUM));
980 expect_prompt ();
981 fprintf (adapt_stream, "s sr133,%x,%x,%x\r", read_register (BP_REGNUM),
982 read_register (FC_REGNUM), read_register (CR_REGNUM));
983 expect_prompt ();
984 fprintf (adapt_stream, "s sr131,%x\r", read_register (Q_REGNUM));
985 expect_prompt ();
986 fprintf (adapt_stream, "s sr0,");
987 for (i=0 ; i<7 ; ++i)
988 fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
989 expect_prompt ();
990 fprintf (adapt_stream, "s sr7,");
991 for (i=7; i<14 ; ++i)
992 fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
993 expect_prompt ();
994}
995
996/* Store register REGNO, or all if REGNO == -1.
997 Return errno value. */
e95bfbf1 998void
7c18a68f
JG
999adapt_store_register (regno)
1000 int regno;
1001{
1002 /* printf("adapt_store_register() called.\n"); fflush(stdout); /* */
1003 if (regno == -1)
1004 adapt_store_registers ();
1005 else
1006 {
1007 char *name = get_reg_name (regno);
1008 fprintf (adapt_stream, "s %s,%x\r", name, read_register (regno));
1009 /* Setting GR1 changes the numbers of all the locals, so
1010 invalidate the register cache. Do this *after* calling
1011 read_register, because we want read_register to return the
1012 value that write_register has just stuffed into the registers
1013 array, not the value of the register fetched from the
1014 inferior. */
1015 if (regno == GR1_REGNUM)
1016 registers_changed ();
1017 expect_prompt ();
1018 }
7c18a68f
JG
1019}
1020
1021/* Get ready to modify the registers array. On machines which store
1022 individual registers, this doesn't need to do anything. On machines
1023 which store all the registers in one fell swoop, this makes sure
1024 that registers contains all the registers from the program being
1025 debugged. */
1026
1027void
1028adapt_prepare_to_store ()
1029{
1030 /* Do nothing, since we can store individual regs */
1031}
1032
1033static CORE_ADDR
1034translate_addr(addr)
1035CORE_ADDR addr;
1036{
1037#if defined(KERNEL_DEBUGGING)
1038 /* Check for a virtual address in the kernel */
1039 /* Assume physical address of ublock is in paddr_u register */
1040 if (addr >= UVADDR) {
1041 /* PADDR_U register holds the physical address of the ublock */
1042 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
1043 return(i + addr - (CORE_ADDR)UVADDR);
1044 } else {
1045 return(addr);
1046 }
1047#else
1048 return(addr);
1049#endif
1050}
1051
1052
1053/* FIXME! Merge these two. */
1054int
1055adapt_xfer_inferior_memory (memaddr, myaddr, len, write)
1056 CORE_ADDR memaddr;
1057 char *myaddr;
1058 int len;
1059 int write;
1060{
1061
1062 memaddr = translate_addr(memaddr);
1063
1064 if (write)
1065 return adapt_write_inferior_memory (memaddr, myaddr, len);
1066 else
1067 return adapt_read_inferior_memory (memaddr, myaddr, len);
1068}
1069
1070void
1071adapt_files_info ()
1072{
1073 printf_filtered("\tAttached to %s at %d baud and running program %s\n",
1074 dev_name, baudrate, prog_name);
1075 printf_filtered("\ton an %s processor.\n", processor_name[processor_type]);
1076}
1077
1078/* Copy LEN bytes of data from debugger memory at MYADDR
1079 to inferior's memory at MEMADDR. Returns errno value.
1080 * sb/sh instructions don't work on unaligned addresses, when TU=1.
1081 */
1082int
1083adapt_write_inferior_memory (memaddr, myaddr, len)
1084 CORE_ADDR memaddr;
1085 char *myaddr;
1086 int len;
1087{
1088 int i;
1089 unsigned int cps;
1090
836e343b 1091 /* Turn TU bit off so we can do 'sb' commands */
7c18a68f
JG
1092 cps = read_register(CPS_REGNUM);
1093 if (cps & 0x00000800)
1094 write_register(CPS_REGNUM,cps&~(0x00000800));
1095
1096 for (i = 0; i < len; i++)
1097 {
1098 if ((i % 16) == 0)
1099 fprintf (adapt_stream, "sb %x,", memaddr + i);
1100 if ((i % 16) == 15 || i == len - 1)
1101 {
1102 fprintf (adapt_stream, "%x\r", ((unsigned char *)myaddr)[i]);
1103 expect_prompt ();
1104 }
1105 else
1106 fprintf (adapt_stream, "%x,", ((unsigned char *)myaddr)[i]);
1107 }
1108 /* Restore the old value of cps if the TU bit was on */
1109 if (cps & 0x00000800)
1110 write_register(CPS_REGNUM,cps);
7c18a68f
JG
1111 return len;
1112}
1113
1114/* Read LEN bytes from inferior memory at MEMADDR. Put the result
1115 at debugger address MYADDR. Returns errno value. */
1116int
1117adapt_read_inferior_memory(memaddr, myaddr, len)
1118 CORE_ADDR memaddr;
1119 char *myaddr;
1120 int len;
1121{
1122 int i;
1123
1124 /* Number of bytes read so far. */
1125 int count;
1126
1127 /* Starting address of this pass. */
1128 unsigned long startaddr;
1129
1130 /* Number of bytes to read in this pass. */
1131 int len_this_pass;
1132
1133 /* Note that this code works correctly if startaddr is just less
1134 than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
1135 thing). That is, something like
1136 adapt_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
1137 works--it never adds len to memaddr and gets 0. */
1138 /* However, something like
1139 adapt_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
1140 doesn't need to work. Detect it and give up if there's an attempt
1141 to do that. */
7c18a68f
JG
1142
1143 if (((memaddr - 1) + len) < memaddr)
1144 return EIO;
1145
1146 startaddr = memaddr;
1147 count = 0;
1148 while (count < len)
1149 {
1150 len_this_pass = 16;
1151 if ((startaddr % 16) != 0)
1152 len_this_pass -= startaddr % 16;
1153 if (len_this_pass > (len - count))
1154 len_this_pass = (len - count);
1155
1156 fprintf (adapt_stream, "db %x,%x\r", startaddr,
1157 (startaddr - 1) + len_this_pass);
1158
1159#ifdef NOTDEF /* Why do this */
1160 expect ("\n");
1161 /* Look for 8 hex digits. */
1162 i = 0;
1163 while (1)
1164 {
1165 if (isxdigit (readchar ()))
1166 ++i;
1167 else
1168 {
1169 expect_prompt ();
1170 error ("Hex digit expected from remote system.");
1171 }
1172 if (i >= 8)
1173 break;
1174 }
1175#endif /* NOTDEF */
1176
1177 expect (" ");
1178
1179 for (i = 0; i < len_this_pass; i++)
1180 get_hex_byte (&myaddr[count++]);
1181
1182 expect_prompt ();
1183
1184 startaddr += len_this_pass;
1185 }
7c18a68f
JG
1186 return count;
1187}
1188
1189#define MAX_BREAKS 8
1190static int num_brkpts=0;
1191static int
1192adapt_insert_breakpoint(addr, save)
1193CORE_ADDR addr;
1194char *save; /* Throw away, let adapt save instructions */
1195{
7c18a68f
JG
1196 if (num_brkpts < MAX_BREAKS) {
1197 num_brkpts++;
1198 fprintf (adapt_stream, "B %x", addr);
1199 fprintf (adapt_stream, "\r");
1200 expect_prompt ();
7c18a68f
JG
1201 return(0); /* Success */
1202 } else {
1203 fprintf_filtered(stderr,
1204 "Too many break points, break point not installed\n");
7c18a68f
JG
1205 return(1); /* Failure */
1206 }
1207
1208}
1209static int
1210adapt_remove_breakpoint(addr, save)
1211CORE_ADDR addr;
1212char *save; /* Throw away, let adapt save instructions */
1213{
7c18a68f
JG
1214 if (num_brkpts > 0) {
1215 num_brkpts--;
1216 fprintf (adapt_stream, "BR %x", addr);
1217 fprintf (adapt_stream, "\r");
1218 fflush (adapt_stream);
1219 expect_prompt ();
1220 }
7c18a68f
JG
1221 return(0);
1222}
1223
1224/* Clear the adapts notion of what the break points are */
1225static int
1226adapt_clear_breakpoints()
1227{
7c18a68f
JG
1228 if (adapt_stream) {
1229 fprintf (adapt_stream, "BR"); /* Clear all break points */
1230 fprintf (adapt_stream, "\r");
1231 fflush(adapt_stream);
1232 expect_prompt ();
1233 }
1234 num_brkpts = 0;
7c18a68f
JG
1235}
1236static void
1237adapt_mourn()
1238{
7c18a68f
JG
1239 adapt_clear_breakpoints();
1240 pop_target (); /* Pop back to no-child state */
1241 generic_mourn_inferior ();
7c18a68f
JG
1242}
1243
1244/* Display everthing we read in from the adapt until we match/see the
1245 * specified string
1246 */
1247static int
1248display_until(str)
1249char *str;
1250{
1251 int i=0,j,c;
1252
1253 while (c=readchar()) {
1254 if (c==str[i]) {
1255 i++;
1256 if (i == strlen(str)) return;
1257 } else {
1258 if (i) {
1259 for (j=0 ; j<i ; j++) /* Put everthing we matched */
1260 putchar(str[j]);
1261 i=0;
1262 }
1263 putchar(c);
1264 }
1265 }
1266
1267}
1268
1269
1270/* Put a command string, in args, out to the adapt. The adapt is assumed to
1271 be in raw mode, all writing/reading done through adapt_desc.
1272 Ouput from the adapt is placed on the users terminal until the
1273 prompt from the adapt is seen.
1274 FIXME: Can't handle commands that take input. */
1275
1276void
1277adapt_com (args, fromtty)
1278 char *args;
1279 int fromtty;
1280{
1281 if (!adapt_stream) {
1282 printf_filtered("Adapt not open. Use the 'target' command to open.\n");
1283 return;
1284 }
1285
1286 /* Clear all input so only command relative output is displayed */
1287 slurp_input();
1288
1289 switch(islower(args[0]) ? toupper(args[0]) : args[0]) {
1290 default:
1291 printf_filtered("Unknown/Unimplemented adapt command '%s'\n",args);
1292 break;
1293 case 'G': /* Go, begin execution */
1294 write(adapt_desc,args,strlen(args));
1295 write(adapt_desc,"\r",1);
1296 expect_prompt();
1297 break;
1298 case 'B': /* Break points, B or BR */
1299 case 'C': /* Check current 29k status (running/halted) */
1300 case 'D': /* Display data/registers */
1301 case 'I': /* Input from i/o space */
1302 case 'J': /* Jam an instruction */
1303 case 'K': /* Kill, stop execution */
1304 case 'L': /* Disassemble */
1305 case 'O': /* Output to i/o space */
1306 case 'T': /* Trace */
1307 case 'P': /* Pulse an input line */
1308 case 'X': /* Examine special purpose registers */
1309 case 'Z': /* Display trace buffer */
1310 write(adapt_desc,args,strlen(args));
1311 write(adapt_desc,"\r",1);
1312 expect(args); /* Don't display the command */
1313 display_until("# ");
1314 break;
1315 /* Begin commands that take input in the form 'c x,y[,z...]' */
1316 case 'S': /* Set memory or register */
c398de0c 1317 if (strchr(args,',')) { /* Assume it is properly formatted */
7c18a68f
JG
1318 write(adapt_desc,args,strlen(args));
1319 write(adapt_desc,"\r",1);
1320 expect_prompt();
1321 }
1322 break;
1323 }
1324}
1325
1326/* Define the target subroutine names */
1327
1328struct target_ops adapt_ops = {
1329 "adapt", "Remote AMD `Adapt' target",
1330 "Remote debug an AMD 290*0 using an `Adapt' monitor via RS232",
1331 adapt_open, adapt_close,
1332 adapt_attach, adapt_detach, adapt_resume, adapt_wait,
1333 adapt_fetch_register, adapt_store_register,
a03d4f8e 1334 adapt_prepare_to_store,
7c18a68f
JG
1335 adapt_xfer_inferior_memory,
1336 adapt_files_info,
1337 adapt_insert_breakpoint, adapt_remove_breakpoint, /* Breakpoints */
1338 0, 0, 0, 0, 0, /* Terminal handling */
1339 adapt_kill, /* FIXME, kill */
1340 adapt_load,
7c18a68f
JG
1341 0, /* lookup_symbol */
1342 adapt_create_inferior, /* create_inferior */
1343 adapt_mourn, /* mourn_inferior FIXME */
5ee4e16c 1344 0, /* can_run */
3950a34e 1345 0, /* notice_signals */
78b459a7 1346 0, /* to_stop */
7c18a68f
JG
1347 process_stratum, 0, /* next */
1348 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1349 0,0, /* Section pointers */
1350 OPS_MAGIC, /* Always the last thing */
1351};
1352
1353void
1354_initialize_remote_adapt ()
1355{
1356 add_target (&adapt_ops);
1357 add_com ("adapt <command>", class_obscure, adapt_com,
1358 "Send a command to the AMD Adapt remote monitor.");
1359}
This page took 0.247951 seconds and 4 git commands to generate.