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