* 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.
This commit is contained in:
Mark Alexander 1997-12-29 21:50:10 +00:00
parent 76ef416550
commit 7e9576e098
11 changed files with 792 additions and 120 deletions

View 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.

View 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", "" \
}

View 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", "" \
}

View 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

View 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

View 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. */

View 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. */

466
gdb/dve3900-rom.c Normal file
View File

@ -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);
}

View 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 =
{

View 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,

View 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;