* 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.
+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.
#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", "" \
+ }
#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", "" \
+ }
# 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
# 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
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
};
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);
/* 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. */
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)
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);
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. */
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);
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" };
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
/* 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);
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. */
--- /dev/null
+/* 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);
+}
/* 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.
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;
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.
vsprintf (sndbuf, pattern, args);
if (remote_debug > 0)
- monitor_debug ("sent -->", sndbuf, "<--");
+ puts_debug ("sent -->", sndbuf, "<--");
len = strlen (sndbuf);
vsprintf (sndbuf, pattern, args);
if (remote_debug > 0)
- monitor_debug ("sent -->", sndbuf, "<--");
+ puts_debug ("sent -->", sndbuf, "<--");
len = strlen (sndbuf);
char buf[2];
buf[0] = c;
buf[1] = '\0';
- monitor_debug ("read -->", buf, "<--");
+ puts_debug ("read -->", buf, "<--");
}
}
/* 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 ()
{
return val;
}
+#endif
static void
compile_pattern (pattern, compiled_pattern, fastmap)
int from_tty;
{
char *name;
- int i;
char **p;
if (mon_ops->magic != MONITOR_OPS_MAGIC)
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;
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)
/* Read the remote registers into the block regs. */
-static void monitor_dump_regs ()
+static void
+monitor_dump_regs ()
{
char buf[1024];
int resp_len;
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. */
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)
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);
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)
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;
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);
#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 */
{
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++;
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;
{
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);
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. */
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);
/* Convert hex digit A to a number. */
+#if 0
static int
from_hex (a)
int 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 =
{
#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,
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. */
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));
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;
#ifdef ANSI_PROTOTYPES
error (const char *string, ...)
#else
-void
error (va_alist)
va_dcl
#endif
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
}
+/* 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,
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;