* dve3900-rom.c: New file to support Densan DVE-R3900/20 board.
authorMark Alexander <marka@cygnus>
Mon, 29 Dec 1997 21:50:10 +0000 (21:50 +0000)
committerMark Alexander <marka@cygnus>
Mon, 29 Dec 1997 21:50:10 +0000 (21:50 +0000)
* monitor.c (monitor_debug): Move to utils.c, rename to puts_debug.
(monitor_write_memory, monitor_read_memory, monitor_insert_breakpoint,
monitor_remove_breakpoint): Remove useless address bits if current
monitor has MO_ADDR_BITS_REMOVE flag.
* monitor.h (MO_ADDR_BITS_REMOVE): Define.
* utils.c (puts_debug): Formerly monitor_debug from monitor.c;
move here and make public.  Add better support for carriage returns.
* defs.h (puts_debug): Declare.
* dsrec.c (load_srec): Use puts_debug to print remotedebug information.
Output header record correctly.
(make_srec): Output a header record instead of a termination record
if sect is non-NULL (value is ignored), but abfd is NULL.
* config/mips/tm-tx39.h (DEFAULT_MIPS_TYPE): Remove definition.
(REGISTER_NAMES): Define to add R3900-specific registers.
* config/mips/tm-tx39l.h: Ditto.
* config/mips/tx39.mt (TDEPFILES): Add dve3900-rom.o and support files.
* config/mips/tx39l.mt: Ditto.

gdb/ChangeLog
gdb/config/mips/tm-tx39.h
gdb/config/mips/tm-tx39l.h
gdb/config/mips/tx39.mt
gdb/config/mips/tx39l.mt
gdb/defs.h
gdb/dsrec.c
gdb/dve3900-rom.c [new file with mode: 0644]
gdb/monitor.c
gdb/monitor.h
gdb/utils.c

index a72276fcf6ac968a5097f12a394834e3120fce05..b15f4eb9c33f9c75553dc2b12af2cadc718ae64b 100644 (file)
@@ -1,3 +1,24 @@
+Mon Dec 29 21:25:34 1997  Mark Alexander  <marka@cygnus.com>
+
+       * dve3900-rom.c: New file to support Densan DVE-R3900/20 board.
+       * monitor.c (monitor_debug): Move to utils.c, rename to puts_debug.
+       (monitor_write_memory, monitor_read_memory, monitor_insert_breakpoint,
+       monitor_remove_breakpoint): Remove useless address bits if current
+       monitor has MO_ADDR_BITS_REMOVE flag.
+       * monitor.h (MO_ADDR_BITS_REMOVE): Define.
+       * utils.c (puts_debug): Formerly monitor_debug from monitor.c;
+       move here and make public.  Add better support for carriage returns.
+       * defs.h (puts_debug): Declare.
+       * dsrec.c (load_srec): Use puts_debug to print remotedebug information.
+       Output header record correctly.
+       (make_srec): Output a header record instead of a termination record
+       if sect is non-NULL (value is ignored), but abfd is NULL.
+       * config/mips/tm-tx39.h (DEFAULT_MIPS_TYPE): Remove definition.
+       (REGISTER_NAMES): Define to add R3900-specific registers.
+       * config/mips/tm-tx39l.h: Ditto.
+       * config/mips/tx39.mt (TDEPFILES): Add dve3900-rom.o and support files.
+       * config/mips/tx39l.mt: Ditto.
+
 Wed Dec 24 12:48:48 1997  Stan Shebs  <shebs@andros.cygnus.com>
 
        * dsrec.c: Cosmetic improvements.
index f46ee21bb6f1b4797d82b890e102de80511c03a6..7db466a934a7849f240779debcccf01663fbed2c 100644 (file)
@@ -21,5 +21,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "mips/tm-bigmips.h"
 
-#undef DEFAULT_MIPS_TYPE
-#define DEFAULT_MIPS_TYPE "r3900"
+#undef  REGISTER_NAMES
+#define REGISTER_NAMES         \
+    {  "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3", \
+       "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7", \
+       "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7", \
+       "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra", \
+       "sr",   "lo",   "hi",   "bad",  "cause","pc", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "", "config", "cache", "debug", "depc", "epc",  "" \
+    }
index 7da13207099e767b366d24eb6e22ffeaf7e15da5..53be627612b4efac8530ee6c216e1aba6df71c5f 100644 (file)
@@ -21,5 +21,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "mips/tm-mips.h"
 
-#undef DEFAULT_MIPS_TYPE
-#define DEFAULT_MIPS_TYPE "r3900"
+#undef  REGISTER_NAMES
+#define REGISTER_NAMES         \
+    {  "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3", \
+       "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7", \
+       "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7", \
+       "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra", \
+       "sr",   "lo",   "hi",   "bad",  "cause","pc", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "",     "",     "", \
+       "",     "",     "",     "",     "",     "",     "",     "", \
+       "",     "", "config", "cache", "debug", "depc", "epc",  "" \
+    }
index 6ae1dad204697c88181824864e744a6980d95b63..8b4c1a92c2445bfd399e62cb8edb9e9635277d01 100644 (file)
@@ -1,5 +1,5 @@
 # Target: Big-endian mips board, typically an IDT.
-TDEPFILES= mips-tdep.o remote-mips.o remote-array.o
+TDEPFILES= mips-tdep.o remote-mips.o dve3900-rom.o monitor.o dsrec.o
 TM_FILE= tm-tx39.h
 SIM_OBS = remote-sim.o
 SIM = ../sim/mips/libsim.a
index fe339d633ddc2c63be9d3d00440e7475d9c78d55..35083293d458a631ce5aae96ffe960a17840d8dd 100644 (file)
@@ -1,5 +1,5 @@
 # Target: Big-endian mips board, typically an IDT.
-TDEPFILES= mips-tdep.o remote-mips.o remote-array.o
+TDEPFILES= mips-tdep.o remote-mips.o dve3900-rom.o monitor.o dsrec.o
 TM_FILE= tm-tx39l.h
 SIM_OBS = remote-sim.o
 SIM = ../sim/mips/libsim.a
index 75325480808073bed10d94f289da5d0ea3584025..aa5dd5f1484e2561877ecd083cf06affaf066e96 100644 (file)
@@ -118,7 +118,7 @@ enum command_class
   all_classes = -2, all_commands = -1,
   /* Classes of commands */
   no_class = -1, class_run = 0, class_vars, class_stack,
-  class_files, class_support, class_info, class_breakpoint,
+  class_files, class_support, class_info, class_breakpoint, class_trace,
   class_alias, class_obscure, class_user, class_maintenance,
   class_pseudo
 };
@@ -309,6 +309,8 @@ extern void puts_filtered PARAMS ((const char *));
 
 extern void puts_unfiltered PARAMS ((const char *));
 
+extern void puts_debug PARAMS ((char *prefix, char *string, char *suffix));
+
 extern void vprintf_filtered PARAMS ((const char *, va_list))
      ATTR_FORMAT(printf, 1, 0);
 
@@ -771,7 +773,7 @@ extern void set_architecture_from_file PARAMS ((bfd *));
 /* Notify target of a change to the selected architecture. Zero return
    status indicates that the target did not like the change. */
 extern int (*target_architecture_hook) PARAMS ((const bfd_arch_info_type *ap)); 
-extern void set_architecture PARAMS ((char *arg, int from_tty));
+extern void set_architecture_from_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long mach));
 
 /* Number of bits in a char or unsigned char for the target machine.
    Just like CHAR_BIT in <limits.h> but describes the target machine.  */
index 03b5517d8d45498462377fdb7b6cdc20a18e0265..6a40e7eae7a371d5fe7e76efa83422e2f20b2ae8 100644 (file)
@@ -82,9 +82,12 @@ load_srec (desc, file, load_offset, maxrecsize, flags, hashmark, waitack)
      is no data, so len is 0.  */
 
   reclen = maxrecsize;
-  make_srec (srec, 0, NULL, NULL, 0, &reclen, flags);
+  make_srec (srec, 0, NULL, (asection *)1, 0, &reclen, flags);
   if (remote_debug)
-    fprintf_unfiltered (gdb_stderr, "%.*s\\r\n", reclen-1, srec);
+    {
+      srec[reclen] = '\0';
+      puts_debug ("sent -->", srec, "<--");
+    }
   SERIAL_WRITE (desc, srec, reclen);
 
   for (s = abfd->sections; s; s = s->next)
@@ -93,8 +96,7 @@ load_srec (desc, file, load_offset, maxrecsize, flags, hashmark, waitack)
        int numbytes;
        bfd_vma addr = bfd_get_section_vma (abfd, s) + load_offset;
        bfd_size_type size = bfd_get_section_size_before_reloc (s);
-       char * section_name = bfd_get_section_name (abfd, s);
-
+       char * section_name = (char *)bfd_get_section_name (abfd, s);
        printf_filtered ("%s\t: 0x%08x .. 0x%08x  ",
                         section_name, (int) addr, (int) addr + size);
        gdb_flush (gdb_stdout);
@@ -108,7 +110,10 @@ load_srec (desc, file, load_offset, maxrecsize, flags, hashmark, waitack)
                                  i, &reclen, flags);
 
            if (remote_debug)
-             fprintf_unfiltered (gdb_stderr, "%.*s\\r\n", reclen-1, srec);
+             {
+               srec[reclen] = '\0';
+               puts_debug ("sent -->", srec, "<--");
+             }
 
            /* Repeatedly send the S-record until a good
               acknowledgement is sent back.  */
@@ -145,11 +150,16 @@ load_srec (desc, file, load_offset, maxrecsize, flags, hashmark, waitack)
   make_srec (srec, abfd->start_address, NULL, NULL, 0, &reclen, flags);
 
   if (remote_debug)
-    fprintf_unfiltered (gdb_stderr, "%.*s\\r\n", reclen-1, srec);
+    {
+      srec[reclen] = '\0';
+      puts_debug ("sent -->", srec, "<--");
+    }
+
   SERIAL_WRITE (desc, srec, reclen);
 
   /* Some monitors need these to wake up properly.  (Which ones? -sts)  */
   SERIAL_WRITE (desc, "\r\r", 2);
+  puts_debug ("sent -->", "\r\r", "<---");
 
   SERIAL_FLUSH_INPUT (desc);
 
@@ -215,6 +225,7 @@ make_srec (srec, targ_addr, abfd, sect, sectoff, maxrecsize, flags)
   const static char hextab[] = "0123456789ABCDEF";
   const static char data_code_table[] = "123";
   const static char term_code_table[] = "987";
+  const static char header_code_table[] = "000";
   const static char *formats[] = { "S%c%02X%04X",
                                   "S%c%02X%06X",
                                   "S%c%02X%08X" };
@@ -226,8 +237,8 @@ make_srec (srec, targ_addr, abfd, sect, sectoff, maxrecsize, flags)
 
   if (sect)
     {
-      tmp = flags;             /* Data record */
-      code_table = data_code_table;
+      tmp = flags;             /* Data or header record */
+      code_table = abfd ? data_code_table : header_code_table;
       binbuf = alloca (*maxrecsize/2);
     }
   else
@@ -249,7 +260,7 @@ make_srec (srec, targ_addr, abfd, sect, sectoff, maxrecsize, flags)
   /* Now that we know the address size, we can figure out how much
      data this record can hold.  */
 
-  if (sect)
+  if (sect && abfd)
     {
       payload_size = (*maxrecsize - (1 + 1 + 2 + addr_size * 2 + 2)) / 2;
       payload_size = min (payload_size, sect->_raw_size - sectoff);
@@ -257,7 +268,7 @@ make_srec (srec, targ_addr, abfd, sect, sectoff, maxrecsize, flags)
       bfd_get_section_contents (abfd, sect, binbuf, sectoff, payload_size);
     }
   else
-    payload_size = 0;          /* Term packets have no payload */
+    payload_size = 0;          /* Term or header packets have no payload */
 
   /* Output the header.  */
 
diff --git a/gdb/dve3900-rom.c b/gdb/dve3900-rom.c
new file mode 100644 (file)
index 0000000..511b4fe
--- /dev/null
@@ -0,0 +1,466 @@
+/* Remote debugging interface for Densan DVE-R3900 ROM monitor for
+   GDB, the GNU debugger.
+   Copyright 1997 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void r3900_open PARAMS ((char *args, int from_tty));
+
+/* Pointers to static functions in monitor.c for fetching and storing
+   registers.  We can't use these function in certain cases where the Densan
+   monitor acts perversely: for registers that it displays in bit-map
+   format, and those that can't be modified at all.  In those cases
+   we have to use our own functions to fetch and store their values.  */
+
+static void (*orig_monitor_fetch_registers) PARAMS ((int regno));
+static void (*orig_monitor_store_registers) PARAMS ((int regno));
+
+
+/* This array of registers needs to match the indexes used by GDB. The
+   whole reason this exists is because the various ROM monitors use
+   different names than GDB does, and don't support all the registers
+   either.  */
+
+static char *r3900_regnames[NUM_REGS] =
+{
+  "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",
+  "r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15",
+  "r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23",
+  "r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31",
+
+  "S",                 /* PS_REGNUM */
+  "l",         /* LO_REGNUM */
+  "h",         /* HI_REGNUM */
+  "B",         /* BADVADDR_REGNUM */
+  "Pcause",    /* CAUSE_REGNUM */
+  "p"          /* PC_REGNUM */
+};
+
+
+/* Table of register names produced by monitor's register dump command.  */
+
+static struct reg_entry
+{
+  char *name;
+  int regno;
+} reg_table[] =
+{
+  { "r0_zero", 0 },  { "r1_at",   1 },  { "r2_v0",   2 },  { "r3_v1",   3 },
+  { "r4_a0",   4 },  { "r5_a1",   5 },  { "r6_a2",   6 },  { "r7_a3",   7 },
+  { "r8_t0",   8 },  { "r9_t1",   9 },  { "r10_t2", 10 },  { "r11_t3", 11 },
+  { "r12_t4", 12 },  { "r13_t5", 13 },  { "r14_t6", 14 },  { "r15_t7", 15 },
+  { "r16_s0", 16 },  { "r17_s1", 17 },  { "r18_s2", 18 },  { "r19_s3", 19 },
+  { "r20_s4", 20 },  { "r21_s5", 21 },  { "r22_s6", 22 },  { "r23_s7", 23 },
+  { "r24_t8", 24 },  { "r25_t9", 25 },  { "r26_k0", 26 },  { "r27_k1", 27 },
+  { "r28_gp", 28 },  { "r29_sp", 29 },  { "r30_fp", 30 },  { "r31_ra", 31 },
+  { "HI",     HI_REGNUM },
+  { "LO",     LO_REGNUM },
+  { "PC",     PC_REGNUM },
+  { "BadV",   BADVADDR_REGNUM },
+  { NULL,     0 }
+};
+
+
+/* The monitor prints register values in the form
+
+       regname = xxxx xxxx
+
+   We look up the register name in a table, and remove the embedded space in
+   the hex value before passing it to monitor_supply_register.  */
+
+static void
+r3900_supply_register (regname, regnamelen, val, vallen)
+     char *regname;
+     int regnamelen;
+     char *val;
+     int vallen;
+{
+  int regno = -1;
+  int i;
+  char valbuf[10];
+  char *p;
+
+  /* Perform some sanity checks on the register name and value.  */
+  if (regnamelen < 2 || regnamelen > 7 || vallen != 9)
+    return;
+
+  /* Look up the register name.  */
+  for (i = 0; reg_table[i].name != NULL; i++)
+    {
+      int rlen = strlen (reg_table[i].name);
+      if (rlen == regnamelen && strncmp (regname, reg_table[i].name, rlen) == 0)
+       {
+         regno = reg_table[i].regno;
+         break;
+       }
+    }
+  if (regno == -1)
+    return;
+
+  /* Copy the hex value to a buffer and eliminate the embedded space. */
+  for (i = 0, p = valbuf; i < vallen; i++)
+    if (val[i] != ' ')
+      *p++ = val[i];
+  *p = '\0';
+
+  monitor_supply_register (regno, valbuf);
+}
+
+/* Fetch the BadVaddr register.  Unlike the other registers, this
+   one can't be modified, and the monitor won't even prompt to let
+   you modify it.  */
+
+static void
+r3900_fetch_badvaddr()
+{
+  char buf[20];
+  int c;
+
+  monitor_printf ("xB\r");
+  monitor_expect ("BadV=", NULL, 0);
+  monitor_expect_prompt (buf, sizeof(buf));
+  monitor_supply_register (BADVADDR_REGNUM, buf);
+}
+
+    
+/* Certain registers are "bitmapped", in that the monitor can only display
+   them or let the user modify them as a series of named bitfields.
+   This structure describes a field in a bitmapped register.  */
+
+struct bit_field
+{
+  char *prefix;                /* string appearing before the value */
+  char *suffix;                /* string appearing after the value */
+  char *user_name;     /* name used by human when entering field value */
+  int  length;         /* number of bits in the field */
+  int  start;          /* starting (least significant) bit number of field */
+};
+        
+/* The monitor displays the cache register along with the status register,
+   as if they were a single register.  So when we want to fetch the
+   status register, parse but otherwise ignore the fields of the
+   cache register that the monitor displays.  Register fields that should
+   be ignored have a length of zero in the tables below.  */
+
+static struct bit_field status_fields [] =
+{
+  /* Status register portion */
+  { "SR[<CU=", " ",    "cu",   4, 28 },
+  { "RE=",     " ",    "re",   1, 25 },
+  { "BEV=",    " ",    "bev",  1, 22 },
+  { "TS=",     " ",    "ts",   1, 21 },
+  { "Nmi=",    " ",    "nmi",  1, 20 },
+  { "INT=",    " ",    "int",  6, 10 },
+  { "SW=",     ">]",   "sw",   2,  8 },
+  { "[<KUO=",  " ",    "kuo",  1,  5 },
+  { "IEO=",    " ",    "ieo",  1,  4 },
+  { "KUP=",    " ",    "kup",  1,  3 },
+  { "IEP=",    " ",    "iep",  1,  2 },
+  { "KUC=",    " ",    "kuc",  1,  1 },
+  { "IEC=",    ">]",   "iec",  1,  0 },
+
+  /* Cache register portion (dummy for parsing only) */
+  { "CR[<IalO="," ",   "ialo", 0, 13 },
+  { "DalO=",   " ",    "dalo", 0, 12 },
+  { "IalP=",   " ",    "ialp", 0, 11 },
+  { "DalP=",   " ",    "dalp", 0, 10 },
+  { "IalC=",   " ",    "ialc", 0,  9 },
+  { "DalC=",   ">] ",  "dalc", 0,  8 },
+
+  { NULL,      NULL,   0,  0 }         /* end of table marker */
+};
+
+
+static struct bit_field cache_fields [] =
+{
+  /* Status register portion (dummy for parsing only) */
+  { "SR[<CU=", " ",    "cu",   0, 28 },
+  { "RE=",     " ",    "re",   0, 25 },
+  { "BEV=",    " ",    "bev",  0, 22 },
+  { "TS=",     " ",    "ts",   0, 21 },
+  { "Nmi=",    " ",    "nmi",  0, 20 },
+  { "INT=",    " ",    "int",  0, 10 },
+  { "SW=",     ">]",   "sw",   0,  8 },
+  { "[<KUO=",  " ",    "kuo",  0,  5 },
+  { "IEO=",    " ",    "ieo",  0,  4 },
+  { "KUP=",    " ",    "kup",  0,  3 },
+  { "IEP=",    " ",    "iep",  0,  2 },
+  { "KUC=",    " ",    "kuc",  0,  1 },
+  { "IEC=",    ">]",   "iec",  0,  0 },
+
+  /* Cache register portion  */
+  { "CR[<IalO="," ",   "ialo", 1, 13 },
+  { "DalO=",   " ",    "dalo", 1, 12 },
+  { "IalP=",   " ",    "ialp", 1, 11 },
+  { "DalP=",   " ",    "dalp", 1, 10 },
+  { "IalC=",   " ",    "ialc", 1,  9 },
+  { "DalC=",   ">] ",  "dalc", 1,  8 },
+
+  { NULL,      NULL,   NULL,   0,  0 }         /* end of table marker */
+};
+
+static struct bit_field cause_fields[] = 
+{
+  { "<BD=",    " ",    "bd",   1, 31 },
+  { "CE=",     " ",    "ce",   2, 28 },
+  { "IP=",     " ",    "ip",   6, 10 },
+  { "SW=",     " ",    "sw",   2,  8 },
+  { "EC=",     ">]" ,  "ec",   5,  2 },
+
+  { NULL,      NULL,   NULL,   0,  0 }         /* end of table marker */
+};
+
+
+/* Read a series of bit fields from the monitor, and return their
+   combined binary value.  */
+
+static unsigned long
+r3900_fetch_fields (bf)
+     struct bit_field *bf;
+{
+  char buf[20];
+  int c;
+  unsigned long val = 0;
+  unsigned long bits;
+
+  for ( ; bf->prefix != NULL; bf++)
+    {
+      monitor_expect (bf->prefix, NULL, 0);            /* get prefix */
+      monitor_expect (bf->suffix, buf, sizeof (buf));  /* hex value, suffix */
+      if (bf->length != 0)
+        {
+         bits = strtoul (buf, NULL, 16);       /* get field value */
+         bits &= ((1 << bf->length) - 1);      /* mask out useless bits */
+         val |= bits << bf->start;             /* insert into register */
+       }
+         
+    }
+
+  return val;
+}
+
+static void
+r3900_fetch_bitmapped_register (regno, bf)
+     int regno;
+     struct bit_field *bf;
+{
+  char buf[20];
+  int c;
+  unsigned long val;
+  unsigned long bits;
+  unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
+
+  monitor_printf ("x%s\r", r3900_regnames[regno]);
+  val = r3900_fetch_fields (bf);
+  monitor_printf (".\r");
+  monitor_expect_prompt (NULL, 0);
+
+  /* supply register stores in target byte order, so swap here */
+
+  store_unsigned_integer (regbuf, REGISTER_RAW_SIZE (regno), val);
+  supply_register (regno, regbuf);
+
+}
+
+/* Fetch all registers (if regno is -1), or one register from the
+   monitor.  For most registers, we can use the generic monitor_
+   monitor_fetch_registers function.  But others are displayed in
+   very unusual fashion and must be handled specially.  */
+
+static void
+r3900_fetch_registers (regno)
+     int regno;
+{
+  switch (regno)
+    {
+    case BADVADDR_REGNUM:
+      r3900_fetch_badvaddr ();
+      return;
+    case PS_REGNUM:
+      r3900_fetch_bitmapped_register (PS_REGNUM, status_fields);
+      return;
+    case CAUSE_REGNUM:
+      r3900_fetch_bitmapped_register (CAUSE_REGNUM, cause_fields);
+      return;
+    default:
+      orig_monitor_fetch_registers (regno);
+    }
+}
+
+
+/* Write the new value of the bitmapped register to the monitor.  */
+
+static void
+r3900_store_bitmapped_register (regno, bf)
+     int regno;
+     struct bit_field *bf;
+{
+  unsigned long oldval, newval;
+
+  /* Fetch the current value of the register.  */
+  monitor_printf ("x%s\r", r3900_regnames[regno]);
+  oldval = r3900_fetch_fields (bf);
+  newval = read_register (regno);
+
+  /* To save time, write just the fields that have changed.  */
+  for ( ; bf->prefix != NULL; bf++)
+    {
+      if (bf->length != 0)
+        {
+         unsigned long oldbits, newbits, mask;
+
+         mask = (1 << bf->length) - 1;
+         oldbits = (oldval >> bf->start) & mask;
+         newbits = (newval >> bf->start) & mask;
+         if (oldbits != newbits)
+           monitor_printf ("%s %x ", bf->user_name, newbits);
+       }
+    }
+
+  monitor_printf (".\r");
+  monitor_expect_prompt (NULL, 0);
+}
+
+static void
+r3900_store_registers (regno)
+     int regno;
+{
+  switch (regno)
+    {
+    case PS_REGNUM:
+      r3900_store_bitmapped_register (PS_REGNUM, status_fields);
+      return;
+    case CAUSE_REGNUM:
+      r3900_store_bitmapped_register (CAUSE_REGNUM, cause_fields);
+      return;
+    default:
+      orig_monitor_store_registers (regno);
+    }
+}
+
+static void
+r3900_load (monops, filename, from_tty)
+     struct monitor_ops *monops;
+     char *filename;
+     int from_tty;
+{
+  extern int inferior_pid;
+
+  generic_load (filename, from_tty);
+
+  /* Finally, make the PC point at the start address */
+  if (exec_bfd)
+    write_pc (bfd_get_start_address (exec_bfd));
+
+  inferior_pid = 0;             /* No process now */
+}
+
+
+static struct target_ops r3900_ops;
+
+/* Commands to send to the monitor when first connecting:
+    * The bare carriage return forces a prompt from the monitor
+      (monitor doesn't prompt after a reset).
+    * The "Xtr" command causes subsequent "t" (trace) commands to display
+      the general registers only.
+    * The "Xxr" command does the same thing for the "x" (examine
+      registers) command.
+    * The "bx" command clears all breakpoints.
+*/
+
+static char *r3900_inits[] = {"\r", "Xtr\r", "Xxr\r", "bx\r", NULL};
+
+static struct monitor_ops r3900_cmds;
+
+static void
+r3900_open (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  monitor_open (args, &r3900_cmds, from_tty);
+}
+
+void
+_initialize_r3900_rom ()
+{
+  r3900_cmds.flags = MO_HANDLE_NL |
+                    MO_NO_ECHO_ON_OPEN |
+                    MO_ADDR_BITS_REMOVE |
+                    MO_CLR_BREAK_USES_ADDR;
+
+  r3900_cmds.init = r3900_inits;
+  r3900_cmds.cont = "g\r";
+  r3900_cmds.step = "t\r";
+  r3900_cmds.set_break = "b %Lx\r";            /* COREADDR */
+  r3900_cmds.clr_break = "b %Lx,0\r";          /* COREADDR */
+  r3900_cmds.fill = "fx %Lx s %x %x\r";                /* COREADDR, len, val */
+
+  r3900_cmds.setmem.cmdb = "sx %Lx %x\r";      /* COREADDR, val */
+  r3900_cmds.setmem.cmdw = "sh %Lx %x\r";      /* COREADDR, val */
+  r3900_cmds.setmem.cmdl = "sw %Lx %x\r";      /* COREADDR, val */
+
+  r3900_cmds.getmem.cmdb = "dx %Lx s %x\r";    /* COREADDR, len */
+  r3900_cmds.getmem.resp_delim = " : ";
+
+  r3900_cmds.setreg.cmd = "x%s %x\r";          /* regname, val */
+
+  r3900_cmds.getreg.cmd = "x%s\r";             /* regname */
+  r3900_cmds.getreg.resp_delim = "=";
+  r3900_cmds.getreg.term = " ";
+  r3900_cmds.getreg.term_cmd = ".\r";
+
+  r3900_cmds.dump_registers = "x\r";
+  r3900_cmds.register_pattern =
+       "\\([a-zA-Z0-9_]+\\) *=\\([0-9a-f]+ [0-9a-f]+\\b\\)";
+  r3900_cmds.supply_register = r3900_supply_register;
+  /* S-record download, via "keyboard port".  */
+  r3900_cmds.load = "r0\r";
+#if 0 /* FIXME - figure out how to get fast load to work */
+  r3900_cmds.load_routine = r3900_load;
+#endif
+  r3900_cmds.prompt = "#";
+  r3900_cmds.line_term = "\r";
+  r3900_cmds.target = &r3900_ops;
+  r3900_cmds.stopbits = SERIAL_1_STOPBITS;
+  r3900_cmds.regnames = r3900_regnames;
+  r3900_cmds.magic = MONITOR_OPS_MAGIC;
+
+  init_monitor_ops (&r3900_ops);
+
+  r3900_ops.to_shortname = "r3900";
+  r3900_ops.to_longname = "R3900 monitor";
+  r3900_ops.to_doc = "Debug using the DVE R3900 monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+  r3900_ops.to_open = r3900_open;
+
+  /* Override the functions to fetch and store registers.  But save the
+     addresses of the default functions, because we will use those functions
+     for "normal" registers.  */
+
+  orig_monitor_fetch_registers = r3900_ops.to_fetch_registers;
+  orig_monitor_store_registers = r3900_ops.to_store_registers;
+  r3900_ops.to_fetch_registers = r3900_fetch_registers;
+  r3900_ops.to_store_registers = r3900_store_registers;
+
+  add_target (&r3900_ops);
+}
index b7a56aa57d33c65b3205b240a0576f58ac2b2dba..97f5a504b4f44fbdf844b642a9776d2ca94d9789 100644 (file)
@@ -1,5 +1,5 @@
 /* Remote debugging interface for boot monitors, for GDB.
-   Copyright 1990, 1991, 1992, 1993, 1995, 1996
+   Copyright 1990, 1991, 1992, 1993, 1995, 1996, 1997
    Free Software Foundation, Inc.
    Contributed by Cygnus Support.  Written by Rob Savoye for Cygnus.
    Resurrected from the ashes by Stu Grossman.
@@ -88,15 +88,17 @@ static void monitor_kill PARAMS ((void));
 static void monitor_load PARAMS ((char *file, int from_tty));
 static void monitor_mourn_inferior PARAMS ((void));
 static void monitor_stop PARAMS ((void));
-static void monitor_debug PARAMS ((char *prefix, char *string, char *suffix));
 
 static int monitor_read_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
 static int monitor_write_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
 
 static int monitor_expect_regexp PARAMS ((struct re_pattern_buffer *pat,
                                          char *buf, int buflen));
+#if 0
 static int from_hex PARAMS ((int a));
 static unsigned long get_hex_word PARAMS ((void));
+#endif
+static void parse_register_dump PARAMS ((char *, int));
 
 static struct monitor_ops *current_monitor;
 
@@ -129,68 +131,18 @@ static DCACHE *remote_dcache;
 static int first_time=0;       /* is this the first time we're executing after 
                                        gaving created the child proccess? */
 
-/* monitor_debug is like fputs_unfiltered, except it prints special
-   characters in printable fashion.  */
+/* Convert hex digit A to a number.  */
 
-static void
-monitor_debug (prefix, string, suffix)
-     char *prefix;
-     char *string;
-     char *suffix;
+static int
+fromhex (a)
+     int a;
 {
-  int ch;
-
-  /* print prefix and suffix after each line */
-  static int new_line=1;
-  static char *prev_prefix = "";
-  static char *prev_suffix = "";
-
-  /* if the prefix is changing, print the previous suffix, a new line,
-     and the new prefix */
-  if (strcmp(prev_prefix, prefix) != 0 && !new_line)
-    {
-      fputs_unfiltered (prev_suffix, gdb_stderr);
-      fputs_unfiltered ("\n", gdb_stderr);
-      fputs_unfiltered (prefix, gdb_stderr);
-    }
-  prev_prefix = prefix;
-  prev_suffix = suffix;
-
-  /* print prefix if last char was a newline*/
-
-  if (new_line == 1) {
-    fputs_unfiltered (prefix, gdb_stderr);
-    new_line=0;
-  }
-  if (strchr(string,'\n'))     /* save state for next call */
-    new_line=1;
-
-  while ((ch = *string++) != '\0')
-    {
-      switch (ch) {
-      default:
-       if (isprint (ch))
-         fputc_unfiltered (ch, gdb_stderr);
-
-       else
-         fprintf_unfiltered (gdb_stderr, "\\%03o", ch);
-
-       break;
-
-      case '\\': fputs_unfiltered ("\\\\",  gdb_stderr);       break;  
-      case '\b': fputs_unfiltered ("\\b",   gdb_stderr);       break;  
-      case '\f': fputs_unfiltered ("\\f",   gdb_stderr);       break;  
-      case '\n': fputs_unfiltered ("\\n",   gdb_stderr);       break;  
-      case '\r': fputs_unfiltered ("\\r",   gdb_stderr);       break;  
-      case '\t': fputs_unfiltered ("\\t",   gdb_stderr);       break;  
-      case '\v': fputs_unfiltered ("\\v",   gdb_stderr);       break;  
-      }
-    }
-
-  if (new_line==1) {   /* print suffix if last char was a newline */
-    fputs_unfiltered (suffix, gdb_stderr);
-    fputs_unfiltered ("\n", gdb_stderr);
-  }
+  if (a >= '0' && a <= '9')
+    return a - '0';
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else 
+    error ("Invalid hex digit %d", a);
 }
 
 /* monitor_printf_noecho -- Send data to monitor, but don't expect an echo.
@@ -219,7 +171,7 @@ monitor_printf_noecho (va_alist)
   vsprintf (sndbuf, pattern, args);
 
   if (remote_debug > 0)
-    monitor_debug ("sent -->", sndbuf, "<--");
+    puts_debug ("sent -->", sndbuf, "<--");
 
   len = strlen (sndbuf);
 
@@ -256,7 +208,7 @@ monitor_printf (va_alist)
   vsprintf (sndbuf, pattern, args);
 
   if (remote_debug > 0)
-    monitor_debug ("sent -->", sndbuf, "<--");
+    puts_debug ("sent -->", sndbuf, "<--");
 
   len = strlen (sndbuf);
 
@@ -297,7 +249,7 @@ readchar (timeout)
              char buf[2];
              buf[0] = c;
              buf[1] = '\0';
-             monitor_debug ("read -->", buf, "<--");
+             puts_debug ("read -->", buf, "<--");
            }
        }
 
@@ -478,6 +430,7 @@ monitor_expect_prompt (buf, buflen)
 /* Get N 32-bit words from remote, each preceded by a space, and put
    them in registers starting at REGNO.  */
 
+#if 0
 static unsigned long
 get_hex_word ()
 {
@@ -501,6 +454,7 @@ get_hex_word ()
 
   return val;
 }
+#endif
 
 static void
 compile_pattern (pattern, compiled_pattern, fastmap)
@@ -536,7 +490,6 @@ monitor_open (args, mon_ops, from_tty)
      int from_tty;
 {
   char *name;
-  int i;
   char **p;
 
   if (mon_ops->magic != MONITOR_OPS_MAGIC)
@@ -725,7 +678,7 @@ monitor_resume (pid, step, sig)
    form REG=VAL.  Each description is split up into a name and a value
    string which are passed down to monitor specific code.  */
 
-static char *
+static void
 parse_register_dump (buf, len)
      char *buf;
      int len;
@@ -899,7 +852,13 @@ monitor_fetch_register (regno)
      searching from the start of the buf.  */
 
   if (current_monitor->getreg.resp_delim)
-    monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+    {
+      monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+      /* Handle case of first 32 registers listed in pairs.  */
+      if (current_monitor->flags & MO_32_REGS_PAIRED
+         && regno & 1 == 1 && regno < 32)
+       monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+    }
 
   /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */
   if (current_monitor->flags & MO_HEX_PREFIX) 
@@ -957,7 +916,8 @@ monitor_fetch_register (regno)
 
 /* Read the remote registers into the block regs.  */
 
-static void monitor_dump_regs ()
+static void
+monitor_dump_regs ()
 {
   char buf[1024];
   int resp_len;
@@ -1007,19 +967,26 @@ monitor_store_register (regno)
 
   val = read_register (regno);
 
- /* send the register deposit command */
 /* send the register deposit command */
 
   if (current_monitor->flags & MO_REGISTER_VALUE_FIRST)
     monitor_printf (current_monitor->setreg.cmd, val, name);
+  else if (current_monitor->flags & MO_SETREG_INTERACTIVE)
+    monitor_printf (current_monitor->setreg.cmd, name);
   else
     monitor_printf (current_monitor->setreg.cmd, name, val);
 
-/* It's possible that there are actually some monitors out there that
-   will prompt you when you set a register.  In that case, you may
-   need to add some code here to deal with TERM and TERM_CMD (see
-   monitor_fetch_register to get an idea of what's needed...) */
+  if (current_monitor->setreg.term)
+    {
+      monitor_expect (current_monitor->setreg.term, NULL, 0);
 
-  monitor_expect_prompt (NULL, 0);
+      if (current_monitor->flags & MO_SETREG_INTERACTIVE)
+       monitor_printf ("%x\r", val);
+
+      monitor_expect_prompt (NULL, 0);
+    }
+  else
+    monitor_expect_prompt (NULL, 0);
 }
 
 /* Store the remote registers.  */
@@ -1067,6 +1034,9 @@ monitor_write_memory (memaddr, myaddr, len)
   char *cmd;
   int i;
 
+  if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+    memaddr = ADDR_BITS_REMOVE (memaddr);
+
   /* Use memory fill command for leading 0 bytes.  */
 
   if (current_monitor->fill)
@@ -1117,6 +1087,19 @@ monitor_write_memory (memaddr, myaddr, len)
 
   if (current_monitor->flags & MO_NO_ECHO_ON_SETMEM)
     monitor_printf_noecho (cmd, memaddr, val);
+  else if (current_monitor->flags & MO_SETMEM_INTERACTIVE)
+    {
+
+      monitor_printf_noecho (cmd, memaddr);
+
+      if (current_monitor->setmem.term)
+       {
+         monitor_expect (current_monitor->setmem.term, NULL, 0);
+
+         monitor_printf ("%x\r", val);
+
+       }
+    }
   else
     monitor_printf (cmd, memaddr, val);
 
@@ -1247,9 +1230,9 @@ monitor_read_memory_single (memaddr, myaddr, len)
   return len;
 }
 
-/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's memory
-   at MEMADDR.  Returns length moved.  Currently, we only do one byte at a
-   time.  */
+/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's
+   memory at MEMADDR.  Returns length moved.  Currently, we do no more
+   than 16 bytes at a time.  */
 
 static int
 monitor_read_memory (memaddr, myaddr, len)
@@ -1258,18 +1241,22 @@ monitor_read_memory (memaddr, myaddr, len)
      int len;
 {
   unsigned int val;
-  unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
   char buf[512];
   char *p, *p1;
-  char *name;
   int resp_len;
   int i;
+  CORE_ADDR dumpaddr;
+
+  if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+    memaddr = ADDR_BITS_REMOVE (memaddr);
 
   if (current_monitor->flags & MO_GETMEM_READ_SINGLE)
     return monitor_read_memory_single (memaddr, myaddr, len);
 
   len = min (len, 16);
 
+  dumpaddr = memaddr & ~0xf;
+
   /* See if xfer would cross a 16 byte boundary.  If so, clip it.  */
   if (((memaddr ^ (memaddr + len - 1)) & ~0xf) != 0)
     len = ((memaddr + len) & ~0xf) - memaddr;
@@ -1278,6 +1265,8 @@ monitor_read_memory (memaddr, myaddr, len)
 
   if (current_monitor->flags & MO_GETMEM_NEEDS_RANGE)
     monitor_printf (current_monitor->getmem.cmdb, memaddr, memaddr + len - 1);
+  else if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
+    monitor_printf (current_monitor->getmem.cmdb, dumpaddr);
   else
     monitor_printf (current_monitor->getmem.cmdb, memaddr, len);
 
@@ -1333,6 +1322,27 @@ monitor_read_memory (memaddr, myaddr, len)
 #endif
     }
 
+  if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
+    {
+      i = len;
+      while (!(*p == '\000' || *p == '\n' || *p == '\r') && i > 0)
+       {
+         if (isxdigit (*p))
+           {
+             if (dumpaddr >= memaddr && i > 0)
+               {
+                 val = fromhex (*p) * 16 + fromhex (*(p+1));
+                 *myaddr++ = val;
+                 --i;
+               }
+             ++dumpaddr;
+             ++p;
+           }
+         ++p;
+       }
+      return len;
+    }
+
   for (i = len; i > 0; i--)
     {
       /* Skip non-hex chars, but bomb on end of string and newlines */
@@ -1341,6 +1351,7 @@ monitor_read_memory (memaddr, myaddr, len)
        {
          if (isxdigit (*p))
            break;
+
          if (*p == '\000' || *p == '\n' || *p == '\r')
            error ("monitor_read_memory (0x%x):  badly terminated response from monitor: %.*s", memaddr, resp_len, buf);
          p++;
@@ -1421,20 +1432,24 @@ monitor_insert_breakpoint (addr, shadow)
      char *shadow;
 {
   int i;
-  /* This is only used to compute the size of a breakpoint.  */
-#ifdef BREAKPOINT
-  static unsigned char break_insn[] = BREAKPOINT;
-#else
-  /* In the bi-endian case we assume breakpoints are the same size.  */
-  static unsigned char break_insn[] = BIG_BREAKPOINT;
-#endif
+  unsigned char *bp;
+  int bplen;
+
+  if (current_monitor->set_break == NULL)
+    error ("No set_break defined for this monitor");
+
+  if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+    addr = ADDR_BITS_REMOVE (addr);
+
+  /* Determine appropriate breakpoint size for this address.  */
+  bp = memory_breakpoint_from_pc (&addr, &bplen);
 
   for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
     {
       if (breakaddr[i] == 0)
        {
          breakaddr[i] = addr;
-         monitor_read_memory (addr, shadow, sizeof (break_insn));
+         monitor_read_memory (addr, shadow, bplen);
          monitor_printf (current_monitor->set_break, addr);
          monitor_expect_prompt (NULL, 0);
          return 0;
@@ -1453,14 +1468,22 @@ monitor_remove_breakpoint (addr, shadow)
 {
   int i;
 
+  if (current_monitor->clr_break == NULL)
+    error ("No clr_break defined for this monitor");
+
+  if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+    addr = ADDR_BITS_REMOVE (addr);
+
   for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
     {
       if (breakaddr[i] == addr)
        {
          breakaddr[i] = 0;
          /* some monitors remove breakpoints based on the address */
-         if (current_monitor->flags & MO_CLR_BREAK_USES_ADDR)   
+         if (current_monitor->flags & MO_CLR_BREAK_USES_ADDR)
            monitor_printf (current_monitor->clr_break, addr);
+         else if (current_monitor->flags & MO_CLR_BREAK_1_BASED)
+           monitor_printf (current_monitor->clr_break, i + 1);
          else
            monitor_printf (current_monitor->clr_break, i);
          monitor_expect_prompt (NULL, 0);
@@ -1477,10 +1500,25 @@ monitor_remove_breakpoint (addr, shadow)
 static int
 monitor_wait_srec_ack ()
 {
-  /* FIXME: eventually we'll want to be able to handle acknowledgements
-     of something other than a '+' character.  Right now this is only
-     going to work for EST visionICE.  */
-  return readchar (timeout) == '+';
+  int i, ch;
+
+  if (current_monitor->flags & MO_SREC_ACK_PLUS)
+    {
+      return (readchar (timeout) == '+');
+    }
+  else if (current_monitor->flags & MO_SREC_ACK_ROTATE)
+    {
+      /* Eat two backspaces, a "rotating" char (|/-\), and a space.  */
+      if ((ch = readchar (1)) < 0)
+       return 0;
+      if ((ch = readchar (1)) < 0)
+       return 0;
+      if ((ch = readchar (1)) < 0)
+       return 0;
+      if ((ch = readchar (1)) < 0)
+       return 0;
+    }
+  return 1;
 }
 
 /* monitor_load -- download a file. */
@@ -1496,12 +1534,23 @@ monitor_load (file, from_tty)
     current_monitor->load_routine (monitor_desc, file, hashmark);
   else
     {                          /* The default is ascii S-records */
+      int n;
+      unsigned long load_offset;
+      char buf[128];
+
+      /* enable user to specify address for downloading as 2nd arg to load */
+      n = sscanf (file, "%s 0x%lx", buf, &load_offset);
+      if (n > 1)
+       file = buf;
+      else
+       load_offset = 0;
+
       monitor_printf (current_monitor->load);
       if (current_monitor->loadresp)
        monitor_expect (current_monitor->loadresp, NULL, 0);
 
-/* FIXME Should add arg here for load_offset (already done for generic_load) */
-      load_srec (monitor_desc, file, 32, SREC_ALL, hashmark,
+      load_srec (monitor_desc, file, (bfd_vma) load_offset,
+                32, SREC_ALL, hashmark,
                 current_monitor->flags & MO_SREC_ACK ?
                   monitor_wait_srec_ack : NULL);
 
@@ -1563,6 +1612,7 @@ monitor_command (args, from_tty)
 
 /* Convert hex digit A to a number.  */
 
+#if 0
 static int
 from_hex (a)
      int a;
@@ -1576,6 +1626,13 @@ from_hex (a)
 
   error ("Reply contains invalid hex digit 0x%x", a);
 }
+#endif
+
+char *
+monitor_get_dev_name ()
+{
+  return dev_name;
+}
 
 static struct target_ops monitor_ops =
 {
index cf1e0cef8f092ec753029689eaba273671a373df..f6c22c67cdd85a083e75a0f8b2d172e8e20363e9 100644 (file)
@@ -197,6 +197,10 @@ struct monitor_ops
 
 #define MO_SREC_ACK_ROTATE 0x80000
 
+/* If set, then remove useless address bits from memory addresses.  */
+
+#define MO_ADDR_BITS_REMOVE 0x100000
+
 #define SREC_SIZE 160
 
 extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops,
index a2699d6f9f471b96d65fc71d42c18acd84ab023f..182ed34ba4710d24de732a368bf7c56c397adecd 100644 (file)
@@ -74,6 +74,7 @@ set_width_command PARAMS ((char *, int, struct cmd_list_element *));
 
 static struct cleanup *cleanup_chain; /* cleaned up after a failed command */
 static struct cleanup *final_cleanup_chain; /* cleaned up when gdb exits */
+static struct cleanup *run_cleanup_chain; /* cleaned up on each 'run' */
 
 /* Nonzero if we have job control. */
 
@@ -146,6 +147,13 @@ make_final_cleanup (function, arg)
     return make_my_cleanup (&final_cleanup_chain, function, arg);
 }
 struct cleanup *
+make_run_cleanup (function, arg)
+     void (*function) PARAMS ((PTR));
+     PTR arg;
+{
+    return make_my_cleanup (&run_cleanup_chain, function, arg);
+}
+struct cleanup *
 make_my_cleanup (pmy_chain, function, arg)
      struct cleanup **pmy_chain;
      void (*function) PARAMS ((PTR));
@@ -180,6 +188,13 @@ do_final_cleanups (old_chain)
     do_my_cleanups (&final_cleanup_chain, old_chain);
 }
 
+void
+do_run_cleanups (old_chain)
+     register struct cleanup *old_chain;
+{
+    do_my_cleanups (&run_cleanup_chain, old_chain);
+}
+
 void
 do_my_cleanups (pmy_chain, old_chain)
      register struct cleanup **pmy_chain;
@@ -378,7 +393,6 @@ NORETURN void
 #ifdef ANSI_PROTOTYPES
 error (const char *string, ...)
 #else
-void
 error (va_alist)
      va_dcl
 #endif
@@ -678,12 +692,6 @@ request_quit (signo)
      about USG defines and stuff like that.  */
   signal (signo, request_quit);
 
-/* start-sanitize-gm */
-#ifdef GENERAL_MAGIC
-  target_kill ();
-#endif /* GENERAL_MAGIC */
-/* end-sanitize-gm */
-
 #ifdef REQUEST_QUIT
   REQUEST_QUIT;
 #else
@@ -1560,6 +1568,80 @@ fputc_unfiltered (c, stream)
 }
 
 
+/* puts_debug is like fputs_unfiltered, except it prints special
+   characters in printable fashion.  */
+
+void
+puts_debug (prefix, string, suffix)
+     char *prefix;
+     char *string;
+     char *suffix;
+{
+  int ch;
+
+  /* Print prefix and suffix after each line.  */
+  static int new_line = 1;
+  static int carriage_return = 0;
+  static char *prev_prefix = "";
+  static char *prev_suffix = "";
+
+  if (*string == '\n')
+    carriage_return = 0;
+
+  /* If the prefix is changing, print the previous suffix, a new line,
+     and the new prefix.  */
+  if ((carriage_return || (strcmp(prev_prefix, prefix) != 0)) && !new_line)
+    {
+      fputs_unfiltered (prev_suffix, gdb_stderr);
+      fputs_unfiltered ("\n", gdb_stderr);
+      fputs_unfiltered (prefix, gdb_stderr);
+    }
+
+  /* Print prefix if we printed a newline during the previous call.  */
+  if (new_line)
+    {
+      new_line = 0;
+      fputs_unfiltered (prefix, gdb_stderr);
+    }
+
+  prev_prefix = prefix;
+  prev_suffix = suffix;
+
+  /* Output characters in a printable format.  */
+  while ((ch = *string++) != '\0')
+    {
+      switch (ch)
+        {
+       default:
+         if (isprint (ch))
+           fputc_unfiltered (ch, gdb_stderr);
+
+         else
+           fprintf_unfiltered (gdb_stderr, "\\%03o", ch);
+         break;
+
+       case '\\': fputs_unfiltered ("\\\\",  gdb_stderr);      break;
+       case '\b': fputs_unfiltered ("\\b",   gdb_stderr);      break;
+       case '\f': fputs_unfiltered ("\\f",   gdb_stderr);      break;
+       case '\n': new_line = 1;
+                  fputs_unfiltered ("\\n",   gdb_stderr);      break;
+       case '\r': fputs_unfiltered ("\\r",   gdb_stderr);      break;
+       case '\t': fputs_unfiltered ("\\t",   gdb_stderr);      break;
+       case '\v': fputs_unfiltered ("\\v",   gdb_stderr);      break;
+        }
+
+      carriage_return = ch == '\r';
+    }
+
+  /* Print suffix if we printed a newline.  */
+  if (new_line)
+    {
+      fputs_unfiltered (suffix, gdb_stderr);
+      fputs_unfiltered ("\n", gdb_stderr);
+    }
+}
+
+
 /* Print a variable number of ARGS using format FORMAT.  If this
    information is going to put the amount written (since the last call
    to REINITIALIZE_MORE_FILTER or the last page break) over the page size,
@@ -1876,6 +1958,9 @@ fprintf_symbol_filtered (stream, name, lang, arg_mode)
            case language_cplus:
              demangled = cplus_demangle (name, arg_mode);
              break;
+           case language_java:
+             demangled = cplus_demangle (name, arg_mode | DMGL_JAVA);
+             break;
            case language_chill:
              demangled = chill_demangle (name);
              break;