1 /* Remote debugging interface for AMD 290*0 Adapt Monitor Version 2.1d18.
2 Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
4 Adapted from work done at Cygnus Support in remote-eb.c.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
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
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. */
45 /* External data declarations */
46 extern int stop_soon_quietly; /* for wait_for_inferior */
48 /* Forward data declarations */
49 extern struct target_ops adapt_ops; /* Forward declaration */
51 /* Forward function declarations */
52 static void adapt_fetch_registers ();
53 static void adapt_store_registers ();
54 static void adapt_close ();
55 static int adapt_clear_breakpoints();
58 * Processor types. It is assumed that the adapt has the correct
59 * ROM for the given processor.
61 #define TYPE_UNKNOWN 0
65 static char *processor_name[] = { "Unknown", "A29000", "A29030", "A29050" };
66 static int processor_type=TYPE_UNKNOWN;
68 #define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
69 #define USE_SHADOW_PC ((processor_type == TYPE_A29050) && FREEZE_MODE)
71 /* Can't seem to get binary coff working */
72 #define ASCII_COFF /* Adapt will be downloaded with ascii coff */
74 #define LOG_FILE "adapt.log"
75 #if defined (LOG_FILE)
79 static int timeout = 5;
80 static char *dev_name;
82 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
83 adapt_open knows that we don't have a file open when the program
87 /* stream which is fdopen'd from adapt_desc. Only valid when
103 ioctl (desc, TIOCGETP, &sg);
107 sg.c_lflag &= ~(ICANON);
113 sg.c_lflag |= ICANON;
115 sg.sg_flags &= ~(RAW);
118 ioctl (desc, TIOCSETP, &sg);
121 /* Suck up all the input from the adapt */
127 /* termio does the timeout for us. */
128 while (read (adapt_desc, buf, 8) > 0);
131 while (read (adapt_desc, buf, 8) > 0);
136 /* Read a character from the remote system, doing all the fancy
145 /* termio does the timeout for us. */
146 read (adapt_desc, &buf, 1);
149 if (read (adapt_desc, &buf, 1) < 0)
152 error ("Timeout reading from remote system.");
154 perror_with_name ("remote");
160 error ("Timeout reading from remote system.");
161 #if defined (LOG_FILE)
162 putc (buf & 0x7f, log_file);
167 /* Keep discarding input from the remote system, until STRING is found.
168 Let the user break out immediately. */
175 fflush(adapt_stream);
179 if (readchar() == *p)
193 /* Keep discarding input until we see the adapt prompt.
195 The convention for dealing with the prompt is that you
197 o *then* wait for the prompt.
199 Thus the last thing that a procedure does with the serial line
200 will be an expect_prompt(). Exception: adapt_resume does not
201 wait for the prompt, because the terminal is being handed over
202 to the inferior. However, the next thing which happens after that
203 is a adapt_wait which does wait for the prompt.
204 Note that this includes abnormal exit, e.g. error(). This is
205 necessary to prevent getting into states from which we can't
210 #if defined (LOG_FILE)
211 /* This is a convenient place to do this. The idea is to do it often
212 enough that we never lose much data if we terminate abnormally. */
215 fflush(adapt_stream);
219 /* Get a hex digit from the remote system & return its value.
220 If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
222 get_hex_digit (ignore_space)
229 if (ch >= '0' && ch <= '9')
231 else if (ch >= 'A' && ch <= 'F')
232 return ch - 'A' + 10;
233 else if (ch >= 'a' && ch <= 'f')
234 return ch - 'a' + 10;
235 else if (ch == ' ' && ignore_space)
240 error ("Invalid hex digit from remote system.");
245 /* Get a byte from adapt_desc and put it in *BYT. Accept any number
253 val = get_hex_digit (1) << 4;
254 val |= get_hex_digit (0);
258 /* Read a 32-bit hex word from the adapt, preceded by a space */
266 for (j = 0; j < 8; j++)
267 val = (val << 4) + get_hex_digit (j == 0);
270 /* Get N 32-bit hex words from remote, each preceded by a space
271 and put them in registers starting at REGNO. */
273 get_hex_regs (n, regno)
279 val = get_hex_word();
280 supply_register(regno++,(char *) &val);
283 /* Called when SIGALRM signal sent due to alarm() timeout. */
288 # define volatile /**/
291 volatile int n_alarms;
298 printf ("adapt_timer called\n");
304 /* malloc'd name of the program on the remote system. */
305 static char *prog_name = NULL;
307 /* Number of SIGTRAPs we need to simulate. That is, the next
308 NEED_ARTIFICIAL_TRAP calls to adapt_wait should just return
309 SIGTRAP without actually waiting for anything. */
311 static int need_artificial_trap = 0;
314 adapt_kill(arg,from_tty)
318 fprintf (adapt_stream, "K");
319 fprintf (adapt_stream, "\r");
323 * Download a file specified in 'args', to the adapt.
324 * FIXME: Assumes the file to download is a binary coff file.
327 adapt_load(args,fromtty)
336 printf_filtered("Adapt not open. Use 'target' command to open adapt\n");
340 /* OK, now read in the file. Y=read, C=COFF, T=dTe port
343 #ifdef ASCII_COFF /* Ascii coff */
344 fprintf (adapt_stream, "YA T,0\r");
345 fflush(adapt_stream); /* Just in case */
346 /* FIXME: should check args for only 1 argument */
347 sprintf(buffer,"cat %s | btoa > /tmp/#adapt-btoa",args);
349 fp = fopen("/tmp/#adapt-btoa","r");
350 rawmode(adapt_desc,OFF);
351 while (n=fread(buffer,1,1024,fp)) {
352 do { n -= write(adapt_desc,buffer,n); } while (n>0);
353 if (n<0) { perror("writing ascii coff"); break; }
356 rawmode(adapt_desc,ON);
357 system("rm /tmp/#adapt-btoa");
358 #else /* Binary coff - can't get it to work .*/
359 fprintf (adapt_stream, "YC T,0\r");
360 fflush(adapt_stream); /* Just in case */
361 if (!(fp = fopen(args,"r"))) {
362 printf_filtered("Can't open %s\n",args);
365 while (n=fread(buffer,1,512,fp)) {
366 do { n -= write(adapt_desc,buffer,n); } while (n>0);
367 if (n<0) { perror("writing ascii coff"); break; }
371 expect_prompt (); /* Skip garbage that comes out */
372 fprintf (adapt_stream, "\r");
376 /* This is called not only when we first attach, but also when the
377 user types "run" after having attached. */
379 adapt_create_inferior (execfile, args, env)
387 error ("Can't pass arguments to remote adapt process.");
389 if (execfile == 0 || exec_bfd == 0)
390 error ("No exec file specified");
392 entry_pt = (int) bfd_get_start_address (exec_bfd);
395 adapt_kill(NULL,NULL);
396 adapt_clear_breakpoints();
397 init_wait_for_inferior ();
398 /* Clear the input because what the adapt sends back is different
399 * depending on whether it was running or not.
401 slurp_input(); /* After this there should be a prompt */
402 fprintf(adapt_stream,"\r");
404 printf_filtered("Do you want to download '%s' (y/n)? [y] : ",prog_name);
408 if (*buffer != 'n') {
409 adapt_load(prog_name,0);
414 /* Set the PC and wait for a go/cont */
415 fprintf (adapt_stream, "G %x,N\r",entry_pt);
416 printf_filtered("Now use the 'continue' command to start.\n");
419 insert_breakpoints (); /* Needed to get correct instruction in cache */
420 proceed(entry_pt, -1, 0);
424 printf_filtered("Adapt not open yet.\n");
428 /* Translate baud rates from integers to damn B_codes. Unix should
429 have outgrown this crap years ago, but even POSIX wouldn't buck it. */
438 static struct {int rate, damn_b;} baudtab[] = {
458 static int damn_b (rate)
463 for (i = 0; baudtab[i].rate != -1; i++)
464 if (rate == baudtab[i].rate) return baudtab[i].damn_b;
465 return B38400; /* Random */
469 /* Open a connection to a remote debugger.
470 NAME is the filename used for communication, then a space,
474 static int baudrate = 9600;
476 adapt_open (name, from_tty)
484 /* Find the first whitespace character, it separates dev_name from
490 *p != '\0' && !isspace (*p); p++)
495 Please include the name of the device for the serial port,\n\
496 the baud rate, and the name of the program to run on the remote system.");
497 dev_name = (char*)malloc(p - name + 1);
498 strncpy (dev_name, name, p - name);
499 dev_name[p - name] = '\0';
501 /* Skip over the whitespace after dev_name */
502 for (; isspace (*p); p++)
505 if (1 != sscanf (p, "%d ", &baudrate))
508 /* Skip the number and then the spaces */
509 for (; isdigit (*p); p++)
511 for (; isspace (*p); p++)
514 if (prog_name != NULL)
516 prog_name = savestring (p, strlen (p));
520 adapt_desc = open (dev_name, O_RDWR);
522 perror_with_name (dev_name);
523 ioctl (adapt_desc, TIOCGETP, &sg);
525 sg.c_cc[VMIN] = 0; /* read with timeout. */
526 sg.c_cc[VTIME] = timeout * 10;
527 sg.c_lflag &= ~(ICANON | ECHO);
528 sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
530 sg.sg_ispeed = damn_b (baudrate);
531 sg.sg_ospeed = damn_b (baudrate);
532 sg.sg_flags |= RAW | ANYP;
533 sg.sg_flags &= ~ECHO;
536 ioctl (adapt_desc, TIOCSETP, &sg);
537 adapt_stream = fdopen (adapt_desc, "r+");
539 push_target (&adapt_ops);
542 #ifndef NO_SIGINTERRUPT
543 /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
545 if (siginterrupt (SIGALRM, 1) != 0)
546 perror ("adapt_open: error in siginterrupt");
549 /* Set up read timeout timer. */
550 if ((void (*)) signal (SIGALRM, adapt_timer) == (void (*)) -1)
551 perror ("adapt_open: error in signal");
554 #if defined (LOG_FILE)
555 log_file = fopen (LOG_FILE, "w");
556 if (log_file == NULL)
557 perror_with_name (LOG_FILE);
560 /* Put this port into NORMAL mode, send the 'normal' character */
561 write(adapt_desc, "
\ 1", 1); /* Control A */
562 write(adapt_desc, "\r", 1);
565 /* Hello? Are you there? */
566 write (adapt_desc, "\r", 1);
570 /* Clear any break points */
571 adapt_clear_breakpoints();
573 /* Determine the processor revision level */
574 prl = (unsigned int)read_register(CFG_REGNUM) >> 24;
576 processor_type = TYPE_A29000;
577 } else if ((prl&0xf0) == 0x40) { /* 29030 = 0x4* */
578 processor_type = TYPE_A29030;
579 fprintf_filtered(stderr,"WARNING: debugging of A29030 not tested.\n");
580 } else if ((prl&0xf0) == 0x20) { /* 29050 = 0x2* */
581 processor_type = TYPE_A29050;
582 fprintf_filtered(stderr,"WARNING: debugging of A29050 not tested.\n");
584 processor_type = TYPE_UNKNOWN;
585 fprintf_filtered(stderr,"WARNING: processor type unknown.\n");
588 /* Print out some stuff, letting the user now what's going on */
589 printf_filtered("Remote debugging on an %s connect to an Adapt via %s.\n",
590 processor_name[processor_type],dev_name);
591 /* FIXME: can this restriction be removed? */
592 printf_filtered("Remote debugging using virtual addresses works only\n");
593 printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n");
594 if (processor_type != TYPE_A29050) {
595 fprintf_filtered(stderr,
596 "Freeze-mode debugging not available, and can only be done on an A29050.\n");
600 /* Close out all files and local state before this target loses control. */
603 adapt_close (quitting)
607 /* Clear any break points */
608 adapt_clear_breakpoints();
610 /* Put this port back into REMOTE mode */
612 fflush(adapt_stream);
613 sleep(1); /* Let any output make it all the way back */
614 write(adapt_desc, "R\r", 2);
617 /* Due to a bug in Unix, fclose closes not only the stdio stream,
618 but also the file descriptor. So we don't actually close
621 fclose (adapt_stream); /* This also closes adapt_desc */
623 /* close (adapt_desc); */
625 /* Do not try to close adapt_desc again, later in the program. */
629 #if defined (LOG_FILE)
631 if (ferror (log_file))
632 printf_filtered ("Error writing log file.\n");
633 if (fclose (log_file) != 0)
634 printf_filtered ("Error closing log file.\n");
640 /* Attach to the target that is already loaded and possibly running */
642 adapt_attach (args, from_tty)
648 printf_filtered ("Attaching to remote program %s.\n", prog_name);
650 /* Send the adapt a kill. It is ok if it is not already running */
651 fprintf(adapt_stream, "K\r"); fflush(adapt_stream);
652 expect_prompt(); /* Slurp the echo */
656 /* Terminate the open connection to the remote debugger.
657 Use this when you want to detach and do something else
660 adapt_detach (args,from_tty)
665 if (adapt_stream) { /* Send it on its way (tell it to continue) */
666 adapt_clear_breakpoints();
667 fprintf(adapt_stream,"G\r");
670 pop_target(); /* calls adapt_close to do the real work */
672 printf_filtered ("Ending remote %s debugging\n", target_shortname);
675 /* Tell the remote machine to resume. */
678 adapt_resume (pid, step, sig)
683 write (adapt_desc, "t 1,s\r", 6);
684 /* Wait for the echo. */
685 expect ("t 1,s\r\n");
686 /* Then comes a line containing the instruction we stepped to. */
688 /* Then we get the prompt. */
691 /* Force the next adapt_wait to return a trap. Not doing anything
692 about I/O from the target means that the user has to type
693 "continue" to see any. FIXME, this should be fixed. */
694 need_artificial_trap = 1;
698 write (adapt_desc, "G\r", 2);
699 /* Swallow the echo. */
704 /* Wait until the remote machine stops, then return,
705 storing status in STATUS just as `wait' would. */
711 /* Strings to look for. '?' means match any single character.
712 Note that with the algorithm we use, the initial character
713 of the string cannot recur in the string, or we will not
714 find some cases of the string in the input. */
716 static char bpt[] = "@";
717 /* It would be tempting to look for "\n[__exit + 0x8]\n"
718 but that requires loading symbols with "yc i" and even if
719 we did do that we don't know that the file has symbols. */
720 static char exitmsg[] = "@????????I JMPTI GR121,LR0";
724 /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
726 /* Current position in swallowed. */
727 char *swallowed_p = swallowed;
731 int old_timeout = timeout;
732 int old_immediate_quit = immediate_quit;
734 WSETEXIT ((*status), 0);
736 if (need_artificial_trap != 0)
738 WSETSTOP ((*status), SIGTRAP);
739 need_artificial_trap--;
743 timeout = 0; /* Don't time out -- user program is running. */
744 immediate_quit = 1; /* Helps ability to QUIT */
746 QUIT; /* Let user quit and leave process running */
758 if (ch == *ep || *ep == '?') {
770 /* Print out any characters which have been swallowed. */
771 for (p = swallowed; p < swallowed_p; ++p)
773 swallowed_p = swallowed;
779 WSETSTOP ((*status), SIGTRAP);
781 WSETEXIT ((*status), 0);
782 timeout = old_timeout;
783 immediate_quit = old_immediate_quit;
787 /* Return the name of register number REGNO
788 in the form input and output by adapt.
790 Returns a pointer to a static buffer containing the answer. */
796 if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32 )
797 sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
798 #if defined(GR64_REGNUM)
799 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
800 sprintf (buf, "GR%03d", regno - GR64_REGNUM + 64);
802 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
803 sprintf (buf, "LR%03d", regno - LR0_REGNUM);
804 else if (regno == Q_REGNUM)
805 strcpy (buf, "SR131");
806 else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
807 sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
808 else if (regno == ALU_REGNUM)
809 strcpy (buf, "SR132");
810 else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
811 sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
812 else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM) {
813 /* When a 29050 is in freeze-mode, read shadow pcs instead */
814 if ((regno >= NPC_REGNUM && regno <= PC2_REGNUM) && USE_SHADOW_PC)
815 sprintf (buf, "SR%03d", regno - NPC_REGNUM + 20);
817 sprintf (buf, "SR%03d", regno - VAB_REGNUM);
819 else if (regno == GR1_REGNUM)
820 strcpy (buf, "GR001");
824 /* Read the remote registers. */
827 adapt_fetch_registers ()
838 #if defined(GR64_REGNUM)
839 write (adapt_desc, "dw gr64,gr95\r", 13);
840 for (reg_index = 64, regnum_index = GR64_REGNUM;
842 reg_index += 4, regnum_index += 4)
844 sprintf (tempbuf, "GR%03d ", reg_index);
846 get_hex_regs (4, regnum_index);
850 write (adapt_desc, "dw gr96,gr127\r", 14);
851 for (reg_index = 96, regnum_index = GR96_REGNUM;
853 reg_index += 4, regnum_index += 4)
855 sprintf (tempbuf, "GR%03d ", reg_index);
857 get_hex_regs (4, regnum_index);
864 for (i = 0; i < 128; i += 32)
866 /* The PC has a tendency to hang if we get these
867 all in one fell swoop ("dw lr0,lr127"). */
868 sprintf (tempbuf, "dw lr%d\r", i);
869 write (adapt_desc, tempbuf, strlen (tempbuf));
870 for (reg_index = i, regnum_index = LR0_REGNUM + i;
872 reg_index += 4, regnum_index += 4)
874 sprintf (tempbuf, "LR%03d ", reg_index);
876 get_hex_regs (4, regnum_index);
884 sprintf (tempbuf, "dw sr0\r");
885 write (adapt_desc, tempbuf, strlen (tempbuf));
886 for (i=0 ; i<4 ; i++) { /* SR0 - SR14 */
887 sprintf (tempbuf, "SR%3d",i*4);
889 for (j=0 ; j < (i==3 ? 3 : 4) ; j++)
890 sreg_buf[i*4 + j] = get_hex_word();
894 * Read the pcs individually if we are in freeze mode.
895 * See get_reg_name(), it translates the register names for the pcs to
896 * the names of the shadow pcs.
899 sreg_buf[10] = read_register(NPC_REGNUM); /* pc0 */
900 sreg_buf[11] = read_register(PC_REGNUM); /* pc1 */
901 sreg_buf[12] = read_register(PC2_REGNUM); /* pc2 */
903 for (i=0 ; i<14 ; i++) /* Supply vab -> lru */
904 supply_register(VAB_REGNUM+i, (char *) &sreg_buf[i]);
905 sprintf (tempbuf, "dw sr128\r");
906 write (adapt_desc, tempbuf, strlen (tempbuf));
907 for (i=0 ; i<2 ; i++) { /* SR128 - SR135 */
908 sprintf (tempbuf, "SR%3d",128 + i*4);
910 for (j=0 ; j<4 ; j++)
911 sreg_buf[i*4 + j] = get_hex_word();
914 supply_register(IPC_REGNUM,(char *) &sreg_buf[0]);
915 supply_register(IPA_REGNUM,(char *) &sreg_buf[1]);
916 supply_register(IPB_REGNUM,(char *) &sreg_buf[2]);
917 supply_register(Q_REGNUM, (char *) &sreg_buf[3]);
919 supply_register(BP_REGNUM, (char *) &sreg_buf[5]);
920 supply_register(FC_REGNUM, (char *) &sreg_buf[6]);
921 supply_register(CR_REGNUM, (char *) &sreg_buf[7]);
923 /* There doesn't seem to be any way to get these. */
926 supply_register (FPE_REGNUM, (char *) &val);
927 supply_register (INTE_REGNUM, (char *) &val);
928 supply_register (FPS_REGNUM, (char *) &val);
929 supply_register (EXO_REGNUM, (char *) &val);
932 write (adapt_desc, "dw gr1,gr1\r", 11);
934 get_hex_regs (1, GR1_REGNUM);
938 /* Fetch register REGNO, or all registers if REGNO is -1.
941 adapt_fetch_register (regno)
945 adapt_fetch_registers ();
948 char *name = get_reg_name (regno);
949 fprintf (adapt_stream, "dw %s,%s\r", name, name);
952 get_hex_regs (1, regno);
957 /* Store the remote registers from the contents of the block REGS. */
960 adapt_store_registers ()
964 fprintf (adapt_stream, "s gr1,%x\r", read_register (GR1_REGNUM));
967 #if defined(GR64_REGNUM)
968 for (j = 0; j < 32; j += 16)
970 fprintf (adapt_stream, "s gr%d,", j + 64);
971 for (i = 0; i < 15; ++i)
972 fprintf (adapt_stream, "%x,", read_register (GR64_REGNUM + j + i));
973 fprintf (adapt_stream, "%x\r", read_register (GR64_REGNUM + j + 15));
977 for (j = 0; j < 32; j += 16)
979 fprintf (adapt_stream, "s gr%d,", j + 96);
980 for (i = 0; i < 15; ++i)
981 fprintf (adapt_stream, "%x,", read_register (GR96_REGNUM + j + i));
982 fprintf (adapt_stream, "%x\r", read_register (GR96_REGNUM + j + 15));
986 for (j = 0; j < 128; j += 16)
988 fprintf (adapt_stream, "s lr%d,", j);
989 for (i = 0; i < 15; ++i)
990 fprintf (adapt_stream, "%x,", read_register (LR0_REGNUM + j + i));
991 fprintf (adapt_stream, "%x\r", read_register (LR0_REGNUM + j + 15));
995 fprintf (adapt_stream, "s sr128,%x,%x,%x\r", read_register (IPC_REGNUM),
996 read_register (IPA_REGNUM), read_register (IPB_REGNUM));
998 fprintf (adapt_stream, "s sr133,%x,%x,%x\r", read_register (BP_REGNUM),
999 read_register (FC_REGNUM), read_register (CR_REGNUM));
1001 fprintf (adapt_stream, "s sr131,%x\r", read_register (Q_REGNUM));
1003 fprintf (adapt_stream, "s sr0,");
1004 for (i=0 ; i<7 ; ++i)
1005 fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
1007 fprintf (adapt_stream, "s sr7,");
1008 for (i=7; i<14 ; ++i)
1009 fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
1013 /* Store register REGNO, or all if REGNO == -1.
1014 Return errno value. */
1016 adapt_store_register (regno)
1019 /* printf("adapt_store_register() called.\n"); fflush(stdout); /* */
1021 adapt_store_registers ();
1024 char *name = get_reg_name (regno);
1025 fprintf (adapt_stream, "s %s,%x\r", name, read_register (regno));
1026 /* Setting GR1 changes the numbers of all the locals, so
1027 invalidate the register cache. Do this *after* calling
1028 read_register, because we want read_register to return the
1029 value that write_register has just stuffed into the registers
1030 array, not the value of the register fetched from the
1032 if (regno == GR1_REGNUM)
1033 registers_changed ();
1038 /* Get ready to modify the registers array. On machines which store
1039 individual registers, this doesn't need to do anything. On machines
1040 which store all the registers in one fell swoop, this makes sure
1041 that registers contains all the registers from the program being
1045 adapt_prepare_to_store ()
1047 /* Do nothing, since we can store individual regs */
1051 translate_addr(addr)
1054 #if defined(KERNEL_DEBUGGING)
1055 /* Check for a virtual address in the kernel */
1056 /* Assume physical address of ublock is in paddr_u register */
1057 if (addr >= UVADDR) {
1058 /* PADDR_U register holds the physical address of the ublock */
1059 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
1060 return(i + addr - (CORE_ADDR)UVADDR);
1070 /* FIXME! Merge these two. */
1072 adapt_xfer_inferior_memory (memaddr, myaddr, len, write)
1079 memaddr = translate_addr(memaddr);
1082 return adapt_write_inferior_memory (memaddr, myaddr, len);
1084 return adapt_read_inferior_memory (memaddr, myaddr, len);
1090 printf_filtered("\tAttached to %s at %d baud and running program %s\n",
1091 dev_name, baudrate, prog_name);
1092 printf_filtered("\ton an %s processor.\n", processor_name[processor_type]);
1095 /* Copy LEN bytes of data from debugger memory at MYADDR
1096 to inferior's memory at MEMADDR. Returns errno value.
1097 * sb/sh instructions don't work on unaligned addresses, when TU=1.
1100 adapt_write_inferior_memory (memaddr, myaddr, len)
1108 /* Turn TU bit off so we can do 'sb' commands */
1109 cps = read_register(CPS_REGNUM);
1110 if (cps & 0x00000800)
1111 write_register(CPS_REGNUM,cps&~(0x00000800));
1113 for (i = 0; i < len; i++)
1116 fprintf (adapt_stream, "sb %x,", memaddr + i);
1117 if ((i % 16) == 15 || i == len - 1)
1119 fprintf (adapt_stream, "%x\r", ((unsigned char *)myaddr)[i]);
1123 fprintf (adapt_stream, "%x,", ((unsigned char *)myaddr)[i]);
1125 /* Restore the old value of cps if the TU bit was on */
1126 if (cps & 0x00000800)
1127 write_register(CPS_REGNUM,cps);
1131 /* Read LEN bytes from inferior memory at MEMADDR. Put the result
1132 at debugger address MYADDR. Returns errno value. */
1134 adapt_read_inferior_memory(memaddr, myaddr, len)
1141 /* Number of bytes read so far. */
1144 /* Starting address of this pass. */
1145 unsigned long startaddr;
1147 /* Number of bytes to read in this pass. */
1150 /* Note that this code works correctly if startaddr is just less
1151 than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
1152 thing). That is, something like
1153 adapt_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
1154 works--it never adds len to memaddr and gets 0. */
1155 /* However, something like
1156 adapt_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
1157 doesn't need to work. Detect it and give up if there's an attempt
1160 if (((memaddr - 1) + len) < memaddr)
1163 startaddr = memaddr;
1168 if ((startaddr % 16) != 0)
1169 len_this_pass -= startaddr % 16;
1170 if (len_this_pass > (len - count))
1171 len_this_pass = (len - count);
1173 fprintf (adapt_stream, "db %x,%x\r", startaddr,
1174 (startaddr - 1) + len_this_pass);
1176 #ifdef NOTDEF /* Why do this */
1178 /* Look for 8 hex digits. */
1182 if (isxdigit (readchar ()))
1187 error ("Hex digit expected from remote system.");
1196 for (i = 0; i < len_this_pass; i++)
1197 get_hex_byte (&myaddr[count++]);
1201 startaddr += len_this_pass;
1206 #define MAX_BREAKS 8
1207 static int num_brkpts=0;
1209 adapt_insert_breakpoint(addr, save)
1211 char *save; /* Throw away, let adapt save instructions */
1213 if (num_brkpts < MAX_BREAKS) {
1215 fprintf (adapt_stream, "B %x", addr);
1216 fprintf (adapt_stream, "\r");
1218 return(0); /* Success */
1220 fprintf_filtered(stderr,
1221 "Too many break points, break point not installed\n");
1222 return(1); /* Failure */
1227 adapt_remove_breakpoint(addr, save)
1229 char *save; /* Throw away, let adapt save instructions */
1231 if (num_brkpts > 0) {
1233 fprintf (adapt_stream, "BR %x", addr);
1234 fprintf (adapt_stream, "\r");
1235 fflush (adapt_stream);
1241 /* Clear the adapts notion of what the break points are */
1243 adapt_clear_breakpoints()
1246 fprintf (adapt_stream, "BR"); /* Clear all break points */
1247 fprintf (adapt_stream, "\r");
1248 fflush(adapt_stream);
1256 adapt_clear_breakpoints();
1257 pop_target (); /* Pop back to no-child state */
1258 generic_mourn_inferior ();
1261 /* Display everthing we read in from the adapt until we match/see the
1270 while (c=readchar()) {
1273 if (i == strlen(str)) return;
1276 for (j=0 ; j<i ; j++) /* Put everthing we matched */
1287 /* Put a command string, in args, out to the adapt. The adapt is assumed to
1288 be in raw mode, all writing/reading done through adapt_desc.
1289 Ouput from the adapt is placed on the users terminal until the
1290 prompt from the adapt is seen.
1291 FIXME: Can't handle commands that take input. */
1294 adapt_com (args, fromtty)
1298 if (!adapt_stream) {
1299 printf_filtered("Adapt not open. Use the 'target' command to open.\n");
1303 /* Clear all input so only command relative output is displayed */
1306 switch(islower(args[0]) ? toupper(args[0]) : args[0]) {
1308 printf_filtered("Unknown/Unimplemented adapt command '%s'\n",args);
1310 case 'G': /* Go, begin execution */
1311 write(adapt_desc,args,strlen(args));
1312 write(adapt_desc,"\r",1);
1315 case 'B': /* Break points, B or BR */
1316 case 'C': /* Check current 29k status (running/halted) */
1317 case 'D': /* Display data/registers */
1318 case 'I': /* Input from i/o space */
1319 case 'J': /* Jam an instruction */
1320 case 'K': /* Kill, stop execution */
1321 case 'L': /* Disassemble */
1322 case 'O': /* Output to i/o space */
1323 case 'T': /* Trace */
1324 case 'P': /* Pulse an input line */
1325 case 'X': /* Examine special purpose registers */
1326 case 'Z': /* Display trace buffer */
1327 write(adapt_desc,args,strlen(args));
1328 write(adapt_desc,"\r",1);
1329 expect(args); /* Don't display the command */
1330 display_until("# ");
1332 /* Begin commands that take input in the form 'c x,y[,z...]' */
1333 case 'S': /* Set memory or register */
1334 if (index(args,',')) { /* Assume it is properly formatted */
1335 write(adapt_desc,args,strlen(args));
1336 write(adapt_desc,"\r",1);
1343 /* Define the target subroutine names */
1345 struct target_ops adapt_ops = {
1346 "adapt", "Remote AMD `Adapt' target",
1347 "Remote debug an AMD 290*0 using an `Adapt' monitor via RS232",
1348 adapt_open, adapt_close,
1349 adapt_attach, adapt_detach, adapt_resume, adapt_wait,
1350 adapt_fetch_register, adapt_store_register,
1351 adapt_prepare_to_store,
1352 adapt_xfer_inferior_memory,
1354 adapt_insert_breakpoint, adapt_remove_breakpoint, /* Breakpoints */
1355 0, 0, 0, 0, 0, /* Terminal handling */
1356 adapt_kill, /* FIXME, kill */
1358 0, /* lookup_symbol */
1359 adapt_create_inferior, /* create_inferior */
1360 adapt_mourn, /* mourn_inferior FIXME */
1362 0, /* notice_signals */
1363 process_stratum, 0, /* next */
1364 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1365 0,0, /* Section pointers */
1366 OPS_MAGIC, /* Always the last thing */
1370 _initialize_remote_adapt ()
1372 add_target (&adapt_ops);
1373 add_com ("adapt <command>", class_obscure, adapt_com,
1374 "Send a command to the AMD Adapt remote monitor.");