mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-20 06:53:59 +08:00
* 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:
parent
76ef416550
commit
7e9576e098
@ -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.
|
||||
|
@ -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", "" \
|
||||
}
|
||||
|
@ -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", "" \
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
31
gdb/dsrec.c
31
gdb/dsrec.c
@ -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
466
gdb/dve3900-rom.c
Normal 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);
|
||||
}
|
247
gdb/monitor.c
247
gdb/monitor.c
@ -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 =
|
||||
{
|
||||
|
@ -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,
|
||||
|
99
gdb/utils.c
99
gdb/utils.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user