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();
57 #define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
58 #define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
60 /* Can't seem to get binary coff working */
61 #define ASCII_COFF /* Adapt will be downloaded with ascii coff */
63 /* FIXME: Replace with `set remotedebug'. */
64 #define LOG_FILE "adapt.log"
65 #if defined (LOG_FILE)
69 static int timeout = 5;
70 static char *dev_name;
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
77 /* stream which is fdopen'd from adapt_desc. Only valid when
93 ioctl (desc, TIOCGETP, &sg);
97 sg.c_lflag &= ~(ICANON);
103 sg.c_lflag |= ICANON;
105 sg.sg_flags &= ~(RAW);
108 ioctl (desc, TIOCSETP, &sg);
111 /* Suck up all the input from the adapt */
117 /* termio does the timeout for us. */
118 while (read (adapt_desc, buf, 8) > 0);
121 while (read (adapt_desc, buf, 8) > 0);
126 /* Read a character from the remote system, doing all the fancy
135 /* termio does the timeout for us. */
136 read (adapt_desc, &buf, 1);
139 if (read (adapt_desc, &buf, 1) < 0)
142 error ("Timeout reading from remote system.");
144 perror_with_name ("remote");
150 error ("Timeout reading from remote system.");
151 #if defined (LOG_FILE)
152 putc (buf & 0x7f, log_file);
157 /* Keep discarding input from the remote system, until STRING is found.
158 Let the user break out immediately. */
165 fflush(adapt_stream);
169 if (readchar() == *p)
183 /* Keep discarding input until we see the adapt prompt.
185 The convention for dealing with the prompt is that you
187 o *then* wait for the prompt.
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
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. */
205 fflush(adapt_stream);
209 /* Get a hex digit from the remote system & return its value.
210 If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
212 get_hex_digit (ignore_space)
219 if (ch >= '0' && ch <= '9')
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)
230 error ("Invalid hex digit from remote system.");
235 /* Get a byte from adapt_desc and put it in *BYT. Accept any number
243 val = get_hex_digit (1) << 4;
244 val |= get_hex_digit (0);
248 /* Read a 32-bit hex word from the adapt, preceded by a space */
256 for (j = 0; j < 8; j++)
257 val = (val << 4) + get_hex_digit (j == 0);
260 /* Get N 32-bit hex words from remote, each preceded by a space
261 and put them in registers starting at REGNO. */
263 get_hex_regs (n, regno)
269 val = get_hex_word();
270 supply_register(regno++,(char *) &val);
273 /* Called when SIGALRM signal sent due to alarm() timeout. */
278 # define volatile /**/
281 volatile int n_alarms;
288 printf ("adapt_timer called\n");
294 /* malloc'd name of the program on the remote system. */
295 static char *prog_name = NULL;
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. */
301 static int need_artificial_trap = 0;
304 adapt_kill(arg,from_tty)
308 fprintf (adapt_stream, "K");
309 fprintf (adapt_stream, "\r");
313 * Download a file specified in 'args', to the adapt.
314 * FIXME: Assumes the file to download is a binary coff file.
317 adapt_load(args,fromtty)
326 printf_filtered("Adapt not open. Use 'target' command to open adapt\n");
330 /* OK, now read in the file. Y=read, C=COFF, T=dTe port
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);
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; }
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);
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; }
361 expect_prompt (); /* Skip garbage that comes out */
362 fprintf (adapt_stream, "\r");
366 /* This is called not only when we first attach, but also when the
367 user types "run" after having attached. */
369 adapt_create_inferior (execfile, args, env)
377 error ("Can't pass arguments to remote adapt process.");
379 if (execfile == 0 || exec_bfd == 0)
380 error ("No exec file specified");
382 entry_pt = (int) bfd_get_start_address (exec_bfd);
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.
391 slurp_input(); /* After this there should be a prompt */
392 fprintf(adapt_stream,"\r");
394 printf_filtered("Do you want to download '%s' (y/n)? [y] : ",prog_name);
398 if (*buffer != 'n') {
399 adapt_load(prog_name,0);
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");
409 insert_breakpoints (); /* Needed to get correct instruction in cache */
410 proceed(entry_pt, -1, 0);
414 printf_filtered("Adapt not open yet.\n");
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. */
428 static struct {int rate, damn_b;} baudtab[] = {
448 static int damn_b (rate)
453 for (i = 0; baudtab[i].rate != -1; i++)
454 if (rate == baudtab[i].rate) return baudtab[i].damn_b;
455 return B38400; /* Random */
459 /* Open a connection to a remote debugger.
460 NAME is the filename used for communication, then a space,
464 static int baudrate = 9600;
466 adapt_open (name, from_tty)
474 /* Find the first whitespace character, it separates dev_name from
480 *p != '\0' && !isspace (*p); p++)
485 Please include the name of the device for the serial port,\n\
486 the 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';
491 /* Skip over the whitespace after dev_name */
492 for (; isspace (*p); p++)
495 if (1 != sscanf (p, "%d ", &baudrate))
498 /* Skip the number and then the spaces */
499 for (; isdigit (*p); p++)
501 for (; isspace (*p); p++)
504 if (prog_name != NULL)
506 prog_name = savestring (p, strlen (p));
510 adapt_desc = open (dev_name, O_RDWR);
512 perror_with_name (dev_name);
513 ioctl (adapt_desc, TIOCGETP, &sg);
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);
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;
526 ioctl (adapt_desc, TIOCSETP, &sg);
527 adapt_stream = fdopen (adapt_desc, "r+");
529 push_target (&adapt_ops);
532 #ifndef NO_SIGINTERRUPT
533 /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
535 if (siginterrupt (SIGALRM, 1) != 0)
536 perror ("adapt_open: error in siginterrupt");
539 /* Set up read timeout timer. */
540 if ((void (*)) signal (SIGALRM, adapt_timer) == (void (*)) -1)
541 perror ("adapt_open: error in signal");
544 #if defined (LOG_FILE)
545 log_file = fopen (LOG_FILE, "w");
546 if (log_file == NULL)
547 perror_with_name (LOG_FILE);
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);
555 /* Hello? Are you there? */
556 write (adapt_desc, "\r", 1);
560 /* Clear any break points */
561 adapt_clear_breakpoints();
563 /* Print out some stuff, letting the user now what's going on */
564 printf_filtered("Connected to an Adapt via %s.\n", dev_name);
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");
568 if (processor_type != a29k_freeze_mode) {
569 fprintf_filtered(stderr,
570 "Freeze-mode debugging not available, and can only be done on an A29050.\n");
574 /* Close out all files and local state before this target loses control. */
577 adapt_close (quitting)
581 /* Clear any break points */
582 adapt_clear_breakpoints();
584 /* Put this port back into REMOTE mode */
586 fflush(adapt_stream);
587 sleep(1); /* Let any output make it all the way back */
588 write(adapt_desc, "R\r", 2);
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
595 fclose (adapt_stream); /* This also closes adapt_desc */
597 /* close (adapt_desc); */
599 /* Do not try to close adapt_desc again, later in the program. */
603 #if defined (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");
614 /* Attach to the target that is already loaded and possibly running */
616 adapt_attach (args, from_tty)
622 printf_filtered ("Attaching to remote program %s.\n", prog_name);
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 */
630 /* Terminate the open connection to the remote debugger.
631 Use this when you want to detach and do something else
634 adapt_detach (args,from_tty)
639 if (adapt_stream) { /* Send it on its way (tell it to continue) */
640 adapt_clear_breakpoints();
641 fprintf(adapt_stream,"G\r");
644 pop_target(); /* calls adapt_close to do the real work */
646 printf_filtered ("Ending remote %s debugging\n", target_shortname);
649 /* Tell the remote machine to resume. */
652 adapt_resume (pid, step, sig)
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. */
662 /* Then we get the prompt. */
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;
672 write (adapt_desc, "G\r", 2);
673 /* Swallow the echo. */
678 /* Wait until the remote machine stops, then return,
679 storing status in STATUS just as `wait' would. */
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. */
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";
698 /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
700 /* Current position in swallowed. */
701 char *swallowed_p = swallowed;
705 int old_timeout = timeout;
706 int old_immediate_quit = immediate_quit;
708 WSETEXIT ((*status), 0);
710 if (need_artificial_trap != 0)
712 WSETSTOP ((*status), SIGTRAP);
713 need_artificial_trap--;
717 timeout = 0; /* Don't time out -- user program is running. */
718 immediate_quit = 1; /* Helps ability to QUIT */
720 QUIT; /* Let user quit and leave process running */
732 if (ch == *ep || *ep == '?') {
744 /* Print out any characters which have been swallowed. */
745 for (p = swallowed; p < swallowed_p; ++p)
747 swallowed_p = swallowed;
753 WSETSTOP ((*status), SIGTRAP);
755 WSETEXIT ((*status), 0);
756 timeout = old_timeout;
757 immediate_quit = old_immediate_quit;
761 /* Return the name of register number REGNO
762 in the form input and output by adapt.
764 Returns a pointer to a static buffer containing the answer. */
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);
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);
791 sprintf (buf, "SR%03d", regno - VAB_REGNUM);
793 else if (regno == GR1_REGNUM)
794 strcpy (buf, "GR001");
798 /* Read the remote registers. */
801 adapt_fetch_registers ()
812 #if defined(GR64_REGNUM)
813 write (adapt_desc, "dw gr64,gr95\r", 13);
814 for (reg_index = 64, regnum_index = GR64_REGNUM;
816 reg_index += 4, regnum_index += 4)
818 sprintf (tempbuf, "GR%03d ", reg_index);
820 get_hex_regs (4, regnum_index);
824 write (adapt_desc, "dw gr96,gr127\r", 14);
825 for (reg_index = 96, regnum_index = GR96_REGNUM;
827 reg_index += 4, regnum_index += 4)
829 sprintf (tempbuf, "GR%03d ", reg_index);
831 get_hex_regs (4, regnum_index);
838 for (i = 0; i < 128; i += 32)
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;
846 reg_index += 4, regnum_index += 4)
848 sprintf (tempbuf, "LR%03d ", reg_index);
850 get_hex_regs (4, regnum_index);
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);
863 for (j=0 ; j < (i==3 ? 3 : 4) ; j++)
864 sreg_buf[i*4 + j] = get_hex_word();
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.
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 */
877 for (i=0 ; i<14 ; i++) /* Supply vab -> lru */
878 supply_register(VAB_REGNUM+i, (char *) &sreg_buf[i]);
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);
884 for (j=0 ; j<4 ; j++)
885 sreg_buf[i*4 + j] = get_hex_word();
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]);
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]);
897 /* There doesn't seem to be any way to get these. */
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);
906 write (adapt_desc, "dw gr1,gr1\r", 11);
908 get_hex_regs (1, GR1_REGNUM);
912 /* Fetch register REGNO, or all registers if REGNO is -1.
915 adapt_fetch_register (regno)
919 adapt_fetch_registers ();
922 char *name = get_reg_name (regno);
923 fprintf (adapt_stream, "dw %s,%s\r", name, name);
926 get_hex_regs (1, regno);
931 /* Store the remote registers from the contents of the block REGS. */
934 adapt_store_registers ()
938 fprintf (adapt_stream, "s gr1,%x\r", read_register (GR1_REGNUM));
941 #if defined(GR64_REGNUM)
942 for (j = 0; j < 32; j += 16)
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));
951 for (j = 0; j < 32; j += 16)
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));
960 for (j = 0; j < 128; j += 16)
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));
969 fprintf (adapt_stream, "s sr128,%x,%x,%x\r", read_register (IPC_REGNUM),
970 read_register (IPA_REGNUM), read_register (IPB_REGNUM));
972 fprintf (adapt_stream, "s sr133,%x,%x,%x\r", read_register (BP_REGNUM),
973 read_register (FC_REGNUM), read_register (CR_REGNUM));
975 fprintf (adapt_stream, "s sr131,%x\r", read_register (Q_REGNUM));
977 fprintf (adapt_stream, "s sr0,");
978 for (i=0 ; i<7 ; ++i)
979 fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
981 fprintf (adapt_stream, "s sr7,");
982 for (i=7; i<14 ; ++i)
983 fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
987 /* Store register REGNO, or all if REGNO == -1.
988 Return errno value. */
990 adapt_store_register (regno)
993 /* printf("adapt_store_register() called.\n"); fflush(stdout); /* */
995 adapt_store_registers ();
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
1006 if (regno == GR1_REGNUM)
1007 registers_changed ();
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
1019 adapt_prepare_to_store ()
1021 /* Do nothing, since we can store individual regs */
1025 translate_addr(addr)
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);
1044 /* FIXME! Merge these two. */
1046 adapt_xfer_inferior_memory (memaddr, myaddr, len, write)
1053 memaddr = translate_addr(memaddr);
1056 return adapt_write_inferior_memory (memaddr, myaddr, len);
1058 return adapt_read_inferior_memory (memaddr, myaddr, len);
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]);
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.
1074 adapt_write_inferior_memory (memaddr, myaddr, len)
1082 /* Turn TU bit off so we can do 'sb' commands */
1083 cps = read_register(CPS_REGNUM);
1084 if (cps & 0x00000800)
1085 write_register(CPS_REGNUM,cps&~(0x00000800));
1087 for (i = 0; i < len; i++)
1090 fprintf (adapt_stream, "sb %x,", memaddr + i);
1091 if ((i % 16) == 15 || i == len - 1)
1093 fprintf (adapt_stream, "%x\r", ((unsigned char *)myaddr)[i]);
1097 fprintf (adapt_stream, "%x,", ((unsigned char *)myaddr)[i]);
1099 /* Restore the old value of cps if the TU bit was on */
1100 if (cps & 0x00000800)
1101 write_register(CPS_REGNUM,cps);
1105 /* Read LEN bytes from inferior memory at MEMADDR. Put the result
1106 at debugger address MYADDR. Returns errno value. */
1108 adapt_read_inferior_memory(memaddr, myaddr, len)
1115 /* Number of bytes read so far. */
1118 /* Starting address of this pass. */
1119 unsigned long startaddr;
1121 /* Number of bytes to read in this pass. */
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
1134 if (((memaddr - 1) + len) < memaddr)
1137 startaddr = memaddr;
1142 if ((startaddr % 16) != 0)
1143 len_this_pass -= startaddr % 16;
1144 if (len_this_pass > (len - count))
1145 len_this_pass = (len - count);
1147 fprintf (adapt_stream, "db %x,%x\r", startaddr,
1148 (startaddr - 1) + len_this_pass);
1150 #ifdef NOTDEF /* Why do this */
1152 /* Look for 8 hex digits. */
1156 if (isxdigit (readchar ()))
1161 error ("Hex digit expected from remote system.");
1170 for (i = 0; i < len_this_pass; i++)
1171 get_hex_byte (&myaddr[count++]);
1175 startaddr += len_this_pass;
1180 #define MAX_BREAKS 8
1181 static int num_brkpts=0;
1183 adapt_insert_breakpoint(addr, save)
1185 char *save; /* Throw away, let adapt save instructions */
1187 if (num_brkpts < MAX_BREAKS) {
1189 fprintf (adapt_stream, "B %x", addr);
1190 fprintf (adapt_stream, "\r");
1192 return(0); /* Success */
1194 fprintf_filtered(stderr,
1195 "Too many break points, break point not installed\n");
1196 return(1); /* Failure */
1201 adapt_remove_breakpoint(addr, save)
1203 char *save; /* Throw away, let adapt save instructions */
1205 if (num_brkpts > 0) {
1207 fprintf (adapt_stream, "BR %x", addr);
1208 fprintf (adapt_stream, "\r");
1209 fflush (adapt_stream);
1215 /* Clear the adapts notion of what the break points are */
1217 adapt_clear_breakpoints()
1220 fprintf (adapt_stream, "BR"); /* Clear all break points */
1221 fprintf (adapt_stream, "\r");
1222 fflush(adapt_stream);
1230 adapt_clear_breakpoints();
1231 pop_target (); /* Pop back to no-child state */
1232 generic_mourn_inferior ();
1235 /* Display everthing we read in from the adapt until we match/see the
1244 while (c=readchar()) {
1247 if (i == strlen(str)) return;
1250 for (j=0 ; j<i ; j++) /* Put everthing we matched */
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. */
1268 adapt_com (args, fromtty)
1272 if (!adapt_stream) {
1273 printf_filtered("Adapt not open. Use the 'target' command to open.\n");
1277 /* Clear all input so only command relative output is displayed */
1280 switch(islower(args[0]) ? toupper(args[0]) : args[0]) {
1282 printf_filtered("Unknown/Unimplemented adapt command '%s'\n",args);
1284 case 'G': /* Go, begin execution */
1285 write(adapt_desc,args,strlen(args));
1286 write(adapt_desc,"\r",1);
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("# ");
1306 /* Begin commands that take input in the form 'c x,y[,z...]' */
1307 case 'S': /* Set memory or register */
1308 if (strchr(args,',')) { /* Assume it is properly formatted */
1309 write(adapt_desc,args,strlen(args));
1310 write(adapt_desc,"\r",1);
1317 /* Define the target subroutine names */
1319 struct 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,
1325 adapt_prepare_to_store,
1326 adapt_xfer_inferior_memory,
1328 adapt_insert_breakpoint, adapt_remove_breakpoint, /* Breakpoints */
1329 0, 0, 0, 0, 0, /* Terminal handling */
1330 adapt_kill, /* FIXME, kill */
1332 0, /* lookup_symbol */
1333 adapt_create_inferior, /* create_inferior */
1334 adapt_mourn, /* mourn_inferior FIXME */
1336 0, /* notice_signals */
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 */
1344 _initialize_remote_adapt ()
1346 add_target (&adapt_ops);
1347 add_com ("adapt <command>", class_obscure, adapt_com,
1348 "Send a command to the AMD Adapt remote monitor.");