Wed Apr 29 10:20:40 1998 John Metzler <jmetzler@cygnus.com>
* nec4102rom.c : New file implements rom monitor adapter for nec-vr4102 board. This board hosts the vr4111 chip. This file required extenstions to the monitor_ops structure, hooks for wiat filter, new flags. This version does not support more than one breakpoint and resuming after a breakpoint in 16 bit mode is completely disfunctional. * monitor.h : Defined additional hooks for dmpregs, confinuer_hooks and wait_filter. These additions require that all rom monitor interfaces be recoded to to initializa monitor ops using assignments rather than static structure initialization. Added new bits to flags MO_EXACT_DUMPADDR, MO_HAS_BLOCKWRITES * monitor.c (RDEBUG): Conditional tracing throughout the file. (fromhex): Now recognized upper cse hex digits (monitor_printf_noecho): (monitor_readchar): Tracing interferes with input timing. (monitor_open): Register different memory write functions with dcache_init if MO_HAS_BLOCKWRITES. (flush_monior_dcache): Added as an additional utilty. (monitor-resume): Call continue hook if one has been supplied. (monitor_wait_filter): New function Factored out of monitor wait and used if alternate wait-filter has not been provided. (monitor_wait): call alternate wait filter if provided. Call monitor_dump_regs, a new function factored out from inline code. (monitor_dump_block): A new function used as a utility when monitors must dump several blocks of registers using different commands. (monitor_dump_regs): Call alternate function if provided. Uses new hook in monitor.h. (monitor_write_memory): Engage previouly added hook MO_FILL_USES_ADDR. (monitor_write_even_block): new function supports writing long blocks of 4byte words. (longlongendswap): new internal function (monitor_write_memory_longlongs): new function writes large blocks using command to enter a long long. (monitor_write-memory_block): new Function figures out which block mod to use. (monitor_read_memory): Can now handle dump formats in which the bytes preceeding the requested data is not printed. * monitor.h: Added new fields to the structure
This commit is contained in:
parent
2325ac592f
commit
2a8b1fab7c
|
@ -1,3 +1,47 @@
|
|||
Wed Apr 29 10:20:40 1998 John Metzler <jmetzler@cygnus.com>
|
||||
|
||||
* nec4102rom.c : New file implements rom monitor adapter for
|
||||
nec-vr4102 board. This board hosts the vr4111 chip. This file
|
||||
required extenstions to the monitor_ops structure, hooks for wiat
|
||||
filter, new flags. This version does not support more than one
|
||||
breakpoint and resuming after a breakpoint in 16 bit mode is
|
||||
completely disfunctional. * monitor.h : Defined additional hooks
|
||||
for dmpregs, confinuer_hooks and wait_filter. These additions
|
||||
require that all rom monitor interfaces be recoded to to
|
||||
initializa monitor ops using assignments rather than static
|
||||
structure initialization. Added new bits to flags
|
||||
MO_EXACT_DUMPADDR, MO_HAS_BLOCKWRITES
|
||||
* monitor.c (RDEBUG): Conditional tracing throughout the file.
|
||||
(fromhex): Now recognized upper cse hex digits
|
||||
(monitor_printf_noecho):
|
||||
(monitor_readchar): Tracing interferes with input timing.
|
||||
(monitor_open): Register different memory write functions with
|
||||
dcache_init if MO_HAS_BLOCKWRITES.
|
||||
(flush_monior_dcache): Added as an additional utilty.
|
||||
(monitor-resume): Call continue hook if one has been supplied.
|
||||
(monitor_wait_filter): New function Factored out of monitor wait
|
||||
and used if alternate wait-filter has not been provided.
|
||||
(monitor_wait): call alternate wait filter if provided. Call
|
||||
monitor_dump_regs, a new function factored out from inline code.
|
||||
(monitor_dump_block): A new function used as a utility when
|
||||
monitors must dump several blocks of registers using different
|
||||
commands.
|
||||
(monitor_dump_regs): Call alternate function if provided. Uses new
|
||||
hook in monitor.h.
|
||||
(monitor_write_memory): Engage previouly added hook
|
||||
MO_FILL_USES_ADDR.
|
||||
(monitor_write_even_block): new function supports writing long
|
||||
blocks of 4byte words.
|
||||
(longlongendswap): new internal function
|
||||
(monitor_write_memory_longlongs): new function writes large blocks
|
||||
using command to enter a long long.
|
||||
(monitor_write-memory_block): new Function figures out which block
|
||||
mod to use.
|
||||
(monitor_read_memory): Can now handle dump formats in which the bytes
|
||||
preceeding the requested data is not printed.
|
||||
* monitor.h: Added new fields to the structure
|
||||
|
||||
|
||||
Tue Apr 28 19:41:33 1998 Tom Tromey <tromey@cygnus.com>
|
||||
|
||||
* Makefile.in (GDBTKLIBS): New macro.
|
||||
|
|
533
gdb/monitor.c
533
gdb/monitor.c
|
@ -62,6 +62,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
static char *dev_name;
|
||||
static struct target_ops *targ_ops;
|
||||
|
||||
static void monitor_vsprintf PARAMS ((char *sndbuf, char *pattern, va_list args));
|
||||
|
||||
static int readchar PARAMS ((int timeout));
|
||||
|
||||
static void monitor_command PARAMS ((char *args, int fromtty));
|
||||
|
@ -91,9 +93,15 @@ static void monitor_stop PARAMS ((void));
|
|||
|
||||
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_write_memory_bytes PARAMS ((CORE_ADDR addr,
|
||||
char *myaddr,int len));
|
||||
static int monitor_write_memory_block PARAMS((
|
||||
CORE_ADDR memaddr ,
|
||||
char * myaddr ,
|
||||
int len)) ;
|
||||
static int monitor_expect_regexp PARAMS ((struct re_pattern_buffer *pat,
|
||||
char *buf, int buflen));
|
||||
static void monitor_dump_regs PARAMS((void)) ;
|
||||
#if 0
|
||||
static int from_hex PARAMS ((int a));
|
||||
static unsigned long get_hex_word PARAMS ((void));
|
||||
|
@ -110,6 +118,16 @@ static int in_monitor_wait = 0; /* Non-zero means we are in monitor_wait() */
|
|||
|
||||
static void (*ofunc)(); /* Old SIGINT signal handler */
|
||||
|
||||
/* Extra remote debugging for developing a new rom monitor variation */
|
||||
#if ! defined(EXTRA_RDEBUG)
|
||||
#define EXTRA_RDEBUG 1
|
||||
#endif
|
||||
#if EXTRA_RDEBUG
|
||||
#define RDEBUG(stuff) { if (remote_debug) printf stuff ; }
|
||||
#else
|
||||
#define RDEBUG(stuff) {}
|
||||
#endif
|
||||
|
||||
/* Descriptor for I/O to remote machine. Initialize it to NULL so
|
||||
that monitor_open knows that we don't have a file open when the
|
||||
program starts. */
|
||||
|
@ -141,10 +159,75 @@ fromhex (a)
|
|||
return a - '0';
|
||||
else if (a >= 'a' && a <= 'f')
|
||||
return a - 'a' + 10;
|
||||
else
|
||||
error ("Invalid hex digit %d", a);
|
||||
else
|
||||
if (a >= 'A' && a <= 'F')
|
||||
return a - 'A' + 10 ;
|
||||
else error ("Invalid hex digit %d", a);
|
||||
}
|
||||
|
||||
/* monitor_vsprintf - similar to vsprintf but handles 64-bit addresses
|
||||
|
||||
This function exists to get around the problem that many host platforms
|
||||
don't have a printf that can print 64-bit addresses. The %A format
|
||||
specification is recognized as a special case, and causes the argument
|
||||
to be printed as a 64-bit hexadecimal address.
|
||||
|
||||
Only format specifiers of the form "[0-9]*[a-z]" are recognized.
|
||||
If it is a '%s' format, the argument is a string; otherwise the
|
||||
argument is assumed to be a long integer.
|
||||
*/
|
||||
|
||||
static void
|
||||
monitor_vsprintf (sndbuf, pattern, args)
|
||||
char *sndbuf;
|
||||
char *pattern;
|
||||
va_list args;
|
||||
{
|
||||
char format[10];
|
||||
char fmt;
|
||||
char *p;
|
||||
int i;
|
||||
long arg_int;
|
||||
CORE_ADDR arg_addr;
|
||||
char *arg_string;
|
||||
|
||||
for (p = pattern; *p; p++)
|
||||
{
|
||||
if (*p == '%')
|
||||
{
|
||||
/* Copy the format specifier to a separate buffer. */
|
||||
format[0] = *p++;
|
||||
for (i = 1; *p >= '0' && *p <= '9' && i < (int) sizeof (format) - 2;
|
||||
i++, p++)
|
||||
format[i] = *p;
|
||||
format[i] = fmt = *p;
|
||||
format[i+1] = '\0';
|
||||
|
||||
/* Fetch the next argument and print it. */
|
||||
switch (fmt)
|
||||
{
|
||||
case 'A':
|
||||
arg_addr = va_arg (args, CORE_ADDR);
|
||||
strcpy (sndbuf, paddr_nz (arg_addr));
|
||||
break;
|
||||
case 's':
|
||||
arg_string = va_arg (args, char *);
|
||||
sprintf (sndbuf, format, arg_string);
|
||||
break;
|
||||
default:
|
||||
arg_int = va_arg (args, long);
|
||||
sprintf (sndbuf, format, arg_int);
|
||||
break;
|
||||
}
|
||||
sndbuf += strlen (sndbuf);
|
||||
}
|
||||
else
|
||||
*sndbuf++ = *p;
|
||||
}
|
||||
*sndbuf = '\0';
|
||||
}
|
||||
|
||||
|
||||
/* monitor_printf_noecho -- Send data to monitor, but don't expect an echo.
|
||||
Works just like printf. */
|
||||
|
||||
|
@ -168,11 +251,14 @@ monitor_printf_noecho (va_alist)
|
|||
pattern = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
vsprintf (sndbuf, pattern, args);
|
||||
monitor_vsprintf (sndbuf, pattern, args);
|
||||
|
||||
#if 0
|
||||
if (remote_debug > 0)
|
||||
puts_debug ("sent -->", sndbuf, "<--");
|
||||
|
||||
#endif
|
||||
RDEBUG(("sent[%s]\n",sndbuf)) ;
|
||||
|
||||
len = strlen (sndbuf);
|
||||
|
||||
if (len + 1 > sizeof sndbuf)
|
||||
|
@ -204,13 +290,14 @@ monitor_printf (va_alist)
|
|||
pattern = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
vsprintf (sndbuf, pattern, args);
|
||||
monitor_vsprintf (sndbuf, pattern, args);
|
||||
|
||||
#if 0
|
||||
if (remote_debug > 0)
|
||||
puts_debug ("sent -->", sndbuf, "<--");
|
||||
|
||||
#endif
|
||||
RDEBUG(("sent[%s]\n",sndbuf))
|
||||
len = strlen (sndbuf);
|
||||
|
||||
if (len + 1 > sizeof sndbuf)
|
||||
abort ();
|
||||
|
||||
|
@ -220,6 +307,7 @@ monitor_printf (va_alist)
|
|||
just output, but sometimes some extra junk appeared before the characters
|
||||
we expected, like an extra prompt, or a portmaster sending telnet negotiations.
|
||||
So, just start searching for what we sent, and skip anything unknown. */
|
||||
RDEBUG(("ExpectEcho\n"))
|
||||
monitor_expect (sndbuf, (char *)0, 0);
|
||||
}
|
||||
|
||||
|
@ -285,6 +373,9 @@ readchar (timeout)
|
|||
if (c >= 0)
|
||||
{
|
||||
c &= 0x7f;
|
||||
#if 0
|
||||
/* This seems to interfere with proper function of the
|
||||
input stream */
|
||||
if (remote_debug > 0)
|
||||
{
|
||||
char buf[2];
|
||||
|
@ -292,6 +383,8 @@ readchar (timeout)
|
|||
buf[1] = '\0';
|
||||
puts_debug ("read -->", buf, "<--");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Canonicialize \n\r combinations into one \r */
|
||||
|
@ -320,11 +413,12 @@ readchar (timeout)
|
|||
return c;
|
||||
|
||||
if (c == SERIAL_TIMEOUT)
|
||||
#ifdef MAINTENANCE_CMDS
|
||||
#if 0 /* MAINTENANCE_CMDS */
|
||||
/* I fail to see how detaching here can be useful
|
||||
if (in_monitor_wait) /* Watchdog went off */
|
||||
{
|
||||
target_mourn_inferior ();
|
||||
error ("Watchdog has expired. Target detached.\n");
|
||||
error ("GDB serial timeout has expired. Target detached.\n");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -350,6 +444,7 @@ monitor_expect (string, buf, buflen)
|
|||
int obuflen = buflen;
|
||||
int c;
|
||||
extern struct target_ops *targ_ops;
|
||||
RDEBUG(("MON Expecting '%s'\n",string)) ;
|
||||
|
||||
immediate_quit = 1;
|
||||
while (1)
|
||||
|
@ -414,7 +509,7 @@ monitor_expect_regexp (pat, buf, buflen)
|
|||
{
|
||||
char *mybuf;
|
||||
char *p;
|
||||
|
||||
RDEBUG(("MON Expecting regexp\n")) ;
|
||||
if (buf)
|
||||
mybuf = buf;
|
||||
else
|
||||
|
@ -465,6 +560,7 @@ monitor_expect_prompt (buf, buflen)
|
|||
char *buf;
|
||||
int buflen;
|
||||
{
|
||||
RDEBUG(("MON Expecting prompt\n"))
|
||||
return monitor_expect (current_monitor->prompt, buf, buflen);
|
||||
}
|
||||
|
||||
|
@ -593,7 +689,8 @@ monitor_open (args, mon_ops, from_tty)
|
|||
monitor_stop ();
|
||||
if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
|
||||
{
|
||||
monitor_expect_prompt (NULL, 0);
|
||||
RDEBUG(("EXP Open echo\n")) ;
|
||||
monitor_expect_prompt (NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -631,8 +728,10 @@ monitor_open (args, mon_ops, from_tty)
|
|||
|
||||
monitor_printf (current_monitor->line_term);
|
||||
|
||||
remote_dcache = dcache_init (monitor_read_memory, monitor_write_memory);
|
||||
|
||||
if (current_monitor->flags & MO_HAS_BLOCKWRITES)
|
||||
remote_dcache = dcache_init (monitor_read_memory, monitor_write_memory_block);
|
||||
else
|
||||
remote_dcache = dcache_init (monitor_read_memory, monitor_write_memory);
|
||||
start_remote ();
|
||||
}
|
||||
|
||||
|
@ -673,6 +772,7 @@ monitor_supply_register (regno, valstr)
|
|||
char *p;
|
||||
|
||||
val = strtoul (valstr, &p, 16);
|
||||
RDEBUG(("Supplying Register %d %s\n",regno,valstr)) ;
|
||||
|
||||
if (val == 0 && valstr == p)
|
||||
error ("monitor_supply_register (%d): bad value from monitor: %s.",
|
||||
|
@ -689,12 +789,15 @@ monitor_supply_register (regno, valstr)
|
|||
|
||||
/* Tell the remote machine to resume. */
|
||||
|
||||
int flush_monitor_dcache(void) { dcache_flush (remote_dcache); }
|
||||
|
||||
static void
|
||||
monitor_resume (pid, step, sig)
|
||||
int pid, step;
|
||||
enum target_signal sig;
|
||||
{
|
||||
/* Some monitors require a different command when starting a program */
|
||||
RDEBUG(("MON resume\n")) ;
|
||||
if (current_monitor->flags & MO_RUN_FIRST_TIME && first_time == 1)
|
||||
{
|
||||
first_time = 0;
|
||||
|
@ -708,7 +811,9 @@ monitor_resume (pid, step, sig)
|
|||
monitor_printf (current_monitor->step);
|
||||
else
|
||||
{
|
||||
monitor_printf (current_monitor->cont);
|
||||
if (current_monitor->continue_hook)
|
||||
(*current_monitor->continue_hook)() ;
|
||||
else monitor_printf (current_monitor->cont);
|
||||
if (current_monitor->flags & MO_NEED_REGDUMP_AFTER_CONT)
|
||||
dump_reg_flag = 1;
|
||||
}
|
||||
|
@ -724,6 +829,7 @@ parse_register_dump (buf, len)
|
|||
char *buf;
|
||||
int len;
|
||||
{
|
||||
RDEBUG(("MON Parsing register dump\n"))
|
||||
while (1)
|
||||
{
|
||||
int regnamelen, vallen;
|
||||
|
@ -803,6 +909,40 @@ monitor_wait_cleanup (old_timeout)
|
|||
in_monitor_wait = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void monitor_wait_filter(char * buf,
|
||||
int bufmax,
|
||||
int * ext_resp_len,
|
||||
struct target_waitstatus * status
|
||||
)
|
||||
{
|
||||
int resp_len ;
|
||||
do
|
||||
{
|
||||
resp_len = monitor_expect_prompt (buf, bufmax);
|
||||
* ext_resp_len =resp_len ;
|
||||
|
||||
if (resp_len <= 0)
|
||||
fprintf_unfiltered (gdb_stderr, "monitor_wait: excessive response from monitor: %s.", buf);
|
||||
}
|
||||
while (resp_len < 0);
|
||||
|
||||
/* Print any output characters that were preceded by ^O. */
|
||||
/* FIXME - This would be great as a user settabgle flag */
|
||||
if (remote_debug ||
|
||||
current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < resp_len - 1; i++)
|
||||
if (buf[i] == 0x0f)
|
||||
putchar_unfiltered (buf[++i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Wait until the remote machine stops, then return, storing status in
|
||||
status just as `wait' would. */
|
||||
|
||||
|
@ -820,8 +960,10 @@ monitor_wait (pid, status)
|
|||
status->value.integer = 0;
|
||||
|
||||
old_chain = make_cleanup (monitor_wait_cleanup, old_timeout);
|
||||
RDEBUG(("MON wait\n"))
|
||||
|
||||
#ifdef MAINTENANCE_CMDS
|
||||
#if 0 /* MAINTENANCE_CMDS */
|
||||
/* This is somthing other than a maintenance command */
|
||||
in_monitor_wait = 1;
|
||||
timeout = watchdog > 0 ? watchdog : -1;
|
||||
#else
|
||||
|
@ -830,6 +972,11 @@ monitor_wait (pid, status)
|
|||
|
||||
ofunc = (void (*)()) signal (SIGINT, monitor_interrupt);
|
||||
|
||||
if (current_monitor->wait_filter)
|
||||
(*current_monitor->wait_filter)(buf,sizeof (buf),&resp_len,status) ;
|
||||
else monitor_wait_filter(buf,sizeof (buf),&resp_len,status) ;
|
||||
|
||||
#if 0 /* Transferred to monitor wait filter */
|
||||
do
|
||||
{
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
|
@ -840,7 +987,9 @@ monitor_wait (pid, status)
|
|||
while (resp_len < 0);
|
||||
|
||||
/* Print any output characters that were preceded by ^O. */
|
||||
if (current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
|
||||
/* FIXME - This would be great as a user settabgle flag */
|
||||
if (remote_debug ||
|
||||
current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -848,21 +997,25 @@ monitor_wait (pid, status)
|
|||
if (buf[i] == 0x0f)
|
||||
putchar_unfiltered (buf[++i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
signal (SIGINT, ofunc);
|
||||
|
||||
timeout = old_timeout;
|
||||
|
||||
#if 0
|
||||
if (dump_reg_flag && current_monitor->dump_registers)
|
||||
{
|
||||
dump_reg_flag = 0;
|
||||
|
||||
monitor_printf (current_monitor->dump_registers);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
}
|
||||
|
||||
if (current_monitor->register_pattern)
|
||||
parse_register_dump (buf, resp_len);
|
||||
#else
|
||||
RDEBUG(("Wait fetching registers after stop\n")) ;
|
||||
monitor_dump_regs() ;
|
||||
#endif
|
||||
|
||||
status->kind = TARGET_WAITKIND_STOPPED;
|
||||
status->value.sig = TARGET_SIGNAL_TRAP;
|
||||
|
@ -887,9 +1040,10 @@ monitor_fetch_register (regno)
|
|||
int i;
|
||||
|
||||
name = current_monitor->regnames[regno];
|
||||
RDEBUG(("MON fetchreg %d '%s'\n",regno,name))
|
||||
|
||||
if (!name)
|
||||
{
|
||||
if (!name || (*name == '\0'))
|
||||
{ RDEBUG(("No register known for %d\n",regno))
|
||||
supply_register (regno, zerobuf);
|
||||
return;
|
||||
}
|
||||
|
@ -904,11 +1058,14 @@ monitor_fetch_register (regno)
|
|||
|
||||
if (current_monitor->getreg.resp_delim)
|
||||
{
|
||||
RDEBUG(("EXP getreg.resp_delim\n"))
|
||||
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);
|
||||
{ RDEBUG(("EXP getreg.resp_delim\n")) ;
|
||||
monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */
|
||||
|
@ -943,6 +1100,7 @@ monitor_fetch_register (regno)
|
|||
}
|
||||
|
||||
regbuf[i] = '\000'; /* terminate the number */
|
||||
RDEBUG(("REGVAL '%s'\n",regbuf)) ;
|
||||
|
||||
/* If TERM is present, we wait for that to show up. Also, (if TERM
|
||||
is present), we will send TERM_CMD if that is present. In any
|
||||
|
@ -951,31 +1109,49 @@ monitor_fetch_register (regno)
|
|||
|
||||
if (current_monitor->getreg.term)
|
||||
{
|
||||
RDEBUG(("EXP getreg.term\n"))
|
||||
monitor_expect (current_monitor->getreg.term, NULL, 0); /* get response */
|
||||
|
||||
if (current_monitor->getreg.term_cmd)
|
||||
{
|
||||
monitor_printf (current_monitor->getreg.term_cmd);
|
||||
monitor_expect_prompt (NULL, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (current_monitor->getreg.term_cmd)
|
||||
{ RDEBUG(("EMIT getreg.term.cmd\n"))
|
||||
monitor_printf (current_monitor->getreg.term_cmd);
|
||||
}
|
||||
if (! current_monitor->getreg.term || /* Already expected or */
|
||||
current_monitor->getreg.term_cmd) /* ack expected */
|
||||
monitor_expect_prompt (NULL, 0); /* get response */
|
||||
|
||||
monitor_supply_register (regno, regbuf);
|
||||
}
|
||||
|
||||
/* Sometimes, it takes several commands to dump the registers */
|
||||
/* This is a primitive for use by variations of monitor interfaces in
|
||||
case they need to compose the operation.
|
||||
*/
|
||||
int monitor_dump_reg_block(char * block_cmd)
|
||||
{
|
||||
char buf[1024];
|
||||
int resp_len;
|
||||
monitor_printf (block_cmd);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
parse_register_dump (buf, resp_len);
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
|
||||
/* Read the remote registers into the block regs. */
|
||||
/* Call the specific function if it has been provided */
|
||||
|
||||
static void
|
||||
monitor_dump_regs ()
|
||||
{
|
||||
char buf[1024];
|
||||
int resp_len;
|
||||
|
||||
if (current_monitor->dump_registers)
|
||||
{
|
||||
monitor_printf (current_monitor->dump_registers);
|
||||
if (current_monitor->dumpregs)
|
||||
(*(current_monitor->dumpregs))() ; /* call supplied function */
|
||||
else
|
||||
if (current_monitor->dump_registers) /* default version */
|
||||
{ monitor_printf (current_monitor->dump_registers);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
parse_register_dump (buf, resp_len);
|
||||
}
|
||||
|
@ -987,6 +1163,7 @@ static void
|
|||
monitor_fetch_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
RDEBUG(("MON fetchregs\n")) ;
|
||||
if (current_monitor->getreg.cmd)
|
||||
{
|
||||
if (regno >= 0)
|
||||
|
@ -1013,10 +1190,13 @@ monitor_store_register (regno)
|
|||
unsigned int val;
|
||||
|
||||
name = current_monitor->regnames[regno];
|
||||
if (!name)
|
||||
return;
|
||||
if (!name || (*name == '\0'))
|
||||
{ RDEBUG(("MON Cannot store unknown register\n"))
|
||||
return;
|
||||
}
|
||||
|
||||
val = read_register (regno);
|
||||
RDEBUG(("MON storeg %d %08x\n",regno,(unsigned int)val))
|
||||
|
||||
/* send the register deposit command */
|
||||
|
||||
|
@ -1028,17 +1208,20 @@ monitor_store_register (regno)
|
|||
monitor_printf (current_monitor->setreg.cmd, name, val);
|
||||
|
||||
if (current_monitor->setreg.term)
|
||||
{
|
||||
{ RDEBUG(("EXP setreg.term\n"))
|
||||
monitor_expect (current_monitor->setreg.term, 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);
|
||||
}
|
||||
if (current_monitor->setreg.term_cmd) /* Mode exit required */
|
||||
{ RDEBUG(("EXP setreg_termcmd\n")) ;
|
||||
monitor_printf("%s",current_monitor->setreg.term_cmd) ;
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
}
|
||||
} /* monitor_store_register */
|
||||
|
||||
/* Store the remote registers. */
|
||||
|
||||
|
@ -1081,10 +1264,12 @@ monitor_write_memory (memaddr, myaddr, len)
|
|||
char *myaddr;
|
||||
int len;
|
||||
{
|
||||
unsigned int val;
|
||||
unsigned int val, hostval ;
|
||||
char *cmd;
|
||||
int i;
|
||||
|
||||
RDEBUG(("MON write %d %08x\n",len,(unsigned long)memaddr))
|
||||
|
||||
if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
|
||||
memaddr = ADDR_BITS_REMOVE (memaddr);
|
||||
|
||||
|
@ -1098,10 +1283,11 @@ monitor_write_memory (memaddr, myaddr, len)
|
|||
|
||||
if (i > 4) /* More than 4 zeros is worth doing */
|
||||
{
|
||||
if (current_monitor->flags & MO_FILL_USES_ADDR)
|
||||
monitor_printf (current_monitor->fill, memaddr, memaddr + i, 0);
|
||||
else
|
||||
monitor_printf (current_monitor->fill, memaddr, i, 0);
|
||||
RDEBUG(("MON FILL %d\n",i))
|
||||
if (current_monitor->flags & MO_FILL_USES_ADDR)
|
||||
monitor_printf (current_monitor->fill, memaddr, (memaddr + i)-1, 0);
|
||||
else
|
||||
monitor_printf (current_monitor->fill, memaddr, i, 0);
|
||||
|
||||
monitor_expect_prompt (NULL, 0);
|
||||
|
||||
|
@ -1135,6 +1321,12 @@ monitor_write_memory (memaddr, myaddr, len)
|
|||
}
|
||||
|
||||
val = extract_unsigned_integer (myaddr, len);
|
||||
|
||||
if (len == 4)
|
||||
{ hostval = * (unsigned int *) myaddr ;
|
||||
RDEBUG(("Hostval(%08x) val(%08x)\n",hostval,val)) ;
|
||||
}
|
||||
|
||||
|
||||
if (current_monitor->flags & MO_NO_ECHO_ON_SETMEM)
|
||||
monitor_printf_noecho (cmd, memaddr, val);
|
||||
|
@ -1144,11 +1336,14 @@ monitor_write_memory (memaddr, myaddr, len)
|
|||
monitor_printf_noecho (cmd, memaddr);
|
||||
|
||||
if (current_monitor->setmem.term)
|
||||
{
|
||||
{ RDEBUG(("EXP setmem.term")) ;
|
||||
monitor_expect (current_monitor->setmem.term, NULL, 0);
|
||||
|
||||
monitor_printf ("%x\r", val);
|
||||
|
||||
}
|
||||
if (current_monitor->setmem.term_cmd)
|
||||
{ /* Emit this to get out of the memory editing state */
|
||||
monitor_printf("%s",current_monitor->setmem.term_cmd) ;
|
||||
/* Drop through to expecting a prompt */
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1159,6 +1354,191 @@ monitor_write_memory (memaddr, myaddr, len)
|
|||
return len;
|
||||
}
|
||||
|
||||
|
||||
static monitor_write_even_block(memaddr,myaddr,len)
|
||||
CORE_ADDR memaddr ;
|
||||
char * myaddr ;
|
||||
int len ;
|
||||
{
|
||||
unsigned int val ;
|
||||
int written = 0 ;;
|
||||
/* Enter the sub mode */
|
||||
monitor_printf(current_monitor->setmem.cmdl,memaddr) ;
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
|
||||
while (len)
|
||||
{
|
||||
val = extract_unsigned_integer(myaddr,4) ; /* REALLY */
|
||||
monitor_printf("%x\r",val) ;
|
||||
myaddr += 4 ;
|
||||
memaddr += 4 ;
|
||||
written += 4 ;
|
||||
RDEBUG((" @ %08x\n",memaddr))
|
||||
/* If we wanted to, here we could validate the address */
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
}
|
||||
/* Now exit the sub mode */
|
||||
monitor_printf (current_monitor->getreg.term_cmd);
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
return written ;
|
||||
}
|
||||
|
||||
|
||||
static int monitor_write_memory_bytes(memaddr,myaddr,len)
|
||||
CORE_ADDR memaddr ;
|
||||
char * myaddr ;
|
||||
int len ;
|
||||
{
|
||||
unsigned char val ;
|
||||
int written = 0 ;
|
||||
if (len == 0) return 0 ;
|
||||
/* Enter the sub mode */
|
||||
monitor_printf(current_monitor->setmem.cmdb,memaddr) ;
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
while (len)
|
||||
{
|
||||
val = *myaddr ;
|
||||
monitor_printf("%x\r",val) ;
|
||||
myaddr++ ;
|
||||
memaddr++ ;
|
||||
written++ ;
|
||||
/* If we wanted to, here we could validate the address */
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
len-- ;
|
||||
}
|
||||
/* Now exit the sub mode */
|
||||
monitor_printf (current_monitor->getreg.term_cmd);
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
return written ;
|
||||
}
|
||||
|
||||
|
||||
static longlongendswap(unsigned char * a)
|
||||
{
|
||||
int i,j ;
|
||||
unsigned char x ;
|
||||
i = 0 ; j = 7 ;
|
||||
while (i < 4)
|
||||
{ x = *(a+i) ;
|
||||
*(a+i) = *(a+j) ;
|
||||
*(a+j) = x ;
|
||||
i++ , j-- ;
|
||||
}
|
||||
}
|
||||
/* Format 32 chars of long long value, advance the pointer */
|
||||
static char * hexlate = "0123456789abcdef" ;
|
||||
static char * longlong_hexchars(unsigned long long value,
|
||||
char * outbuff )
|
||||
{
|
||||
if (value == 0) { *outbuff++ = '0' ; return outbuff ; }
|
||||
else
|
||||
{ static unsigned char disbuf[8] ; /* disassembly buffer */
|
||||
unsigned char * scan , * limit ; /* loop controls */
|
||||
unsigned char c , nib ;
|
||||
int leadzero = 1 ;
|
||||
scan = disbuf ; limit = scan + 8 ;
|
||||
{ unsigned long long * dp ;
|
||||
dp = (unsigned long long *) scan ;
|
||||
*dp = value ;
|
||||
}
|
||||
longlongendswap(disbuf) ; /* FIXME: ONly on big endian hosts */
|
||||
while (scan < limit)
|
||||
{ c = *scan++ ; /* a byte of our long long value */
|
||||
if (leadzero)
|
||||
if (c == 0) continue ;
|
||||
else leadzero = 0 ; /* henceforth we print even zeroes */
|
||||
nib = c >> 4 ; /* high nibble bits */
|
||||
*outbuff++ = hexlate[nib] ;
|
||||
nib = c & 0x0f ; /* low nibble bits */
|
||||
*outbuff++ = hexlate[nib] ;
|
||||
}
|
||||
return outbuff ;
|
||||
}
|
||||
} /* longlong_hexchars */
|
||||
|
||||
|
||||
|
||||
/* I am only going to call this when writing virtual byte streams.
|
||||
Which possably entails endian conversions
|
||||
*/
|
||||
static int monitor_write_memory_longlongs(memaddr,myaddr,len)
|
||||
CORE_ADDR memaddr ;
|
||||
char * myaddr ;
|
||||
int len ;
|
||||
{
|
||||
static char hexstage[20] ; /* At least 16 digits required, plus null */
|
||||
char * endstring ;
|
||||
long long * llptr ;
|
||||
long long value ;
|
||||
int written = 0 ;
|
||||
llptr = (unsigned long long *) myaddr ;
|
||||
if (len == 0 ) return 0 ;
|
||||
monitor_printf(current_monitor->setmem.cmdll,memaddr) ;
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
while (len >= 8 )
|
||||
{
|
||||
value = *llptr ;
|
||||
endstring = longlong_hexchars(*llptr,hexstage) ;
|
||||
*endstring = '\0' ; /* NUll terminate for printf */
|
||||
monitor_printf("%s\r",hexstage) ;
|
||||
llptr++ ;
|
||||
memaddr += 8 ;
|
||||
written += 8 ;
|
||||
/* If we wanted to, here we could validate the address */
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
len -= 8 ;
|
||||
}
|
||||
/* Now exit the sub mode */
|
||||
monitor_printf (current_monitor->getreg.term_cmd);
|
||||
monitor_expect_prompt(NULL,0) ;
|
||||
return written ;
|
||||
} /* */
|
||||
|
||||
|
||||
|
||||
/* ----- MONITOR_WRITE_MEMORY_BLOCK ---------------------------- */
|
||||
/* This is for the large blocks of memory which may occur in downloading.
|
||||
And for monitors which use interactive entry,
|
||||
And for monitors which do not have other downloading methods.
|
||||
Without this, we will end up calling monitor_write_memory many times
|
||||
and do the entry and exit of the sub mode many times
|
||||
This currently assumes...
|
||||
MO_SETMEM_INTERACTIVE
|
||||
! MO_NO_ECHO_ON_SETMEM
|
||||
To use this, the you have to patch the monitor_cmds block with
|
||||
this function. Otherwise, its not tuned up for use by all
|
||||
monitor variations.
|
||||
*/
|
||||
|
||||
static int monitor_write_memory_block(memaddr,myaddr,len)
|
||||
CORE_ADDR memaddr ;
|
||||
char * myaddr ;
|
||||
int len ;
|
||||
{
|
||||
int written ;
|
||||
written = 0 ;
|
||||
/* FIXME: This would be a good place to put the zero test */
|
||||
#if 1
|
||||
if ((len > 8) && (((len & 0x07)) == 0) && current_monitor->setmem.cmdll)
|
||||
{
|
||||
return monitor_write_memory_longlongs(memaddr,myaddr,len) ;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if (len > 4)
|
||||
{
|
||||
int sublen ;
|
||||
written = monitor_write_even_block(memaddr,myaddr,len) ;
|
||||
/* Adjust calling parameters by written amount */
|
||||
memaddr += written ;
|
||||
myaddr += written ;
|
||||
len -= written ;
|
||||
}
|
||||
#endif
|
||||
written = monitor_write_memory_bytes(memaddr,myaddr,len) ;
|
||||
return written ;
|
||||
}
|
||||
|
||||
/* This is an alternate form of monitor_read_memory which is used for monitors
|
||||
which can only read a single byte/word/etc. at a time. */
|
||||
|
||||
|
@ -1174,6 +1554,7 @@ monitor_read_memory_single (memaddr, myaddr, len)
|
|||
char *cmd;
|
||||
int i;
|
||||
|
||||
RDEBUG(("MON read single\n")) ;
|
||||
#if 0
|
||||
/* Can't actually use long longs (nice idea, though). In fact, the
|
||||
call to strtoul below will fail if it tries to convert a value
|
||||
|
@ -1210,7 +1591,9 @@ monitor_read_memory_single (memaddr, myaddr, len)
|
|||
searching from the start of the buf. */
|
||||
|
||||
if (current_monitor->getmem.resp_delim)
|
||||
monitor_expect_regexp (&getmem_resp_delim_pattern, NULL, 0);
|
||||
{ RDEBUG(("EXP getmem.resp_delim\n")) ;
|
||||
monitor_expect_regexp (&getmem_resp_delim_pattern, NULL, 0);
|
||||
}
|
||||
|
||||
/* Now, read the appropriate number of hex digits for this loc,
|
||||
skipping spaces. */
|
||||
|
@ -1298,6 +1681,9 @@ monitor_read_memory (memaddr, myaddr, len)
|
|||
int i;
|
||||
CORE_ADDR dumpaddr;
|
||||
|
||||
if (remote_debug) printf("MON read block ta(%08x) ha(%08x) %d\n",
|
||||
(unsigned long) memaddr , (unsigned long)myaddr, len);
|
||||
|
||||
if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
|
||||
memaddr = ADDR_BITS_REMOVE (memaddr);
|
||||
|
||||
|
@ -1306,7 +1692,13 @@ monitor_read_memory (memaddr, myaddr, len)
|
|||
|
||||
len = min (len, 16);
|
||||
|
||||
dumpaddr = memaddr & ~0xf;
|
||||
/* Some dumpers align the first data with the preceeding 16
|
||||
byte boundary. Some print blanks and start at the
|
||||
requested boundary. EXACT_DUMPADDR
|
||||
*/
|
||||
|
||||
dumpaddr = (current_monitor->flags & MO_EXACT_DUMPADDR)
|
||||
? memaddr : memaddr & ~ 0x0f ;
|
||||
|
||||
/* See if xfer would cross a 16 byte boundary. If so, clip it. */
|
||||
if (((memaddr ^ (memaddr + len - 1)) & ~0xf) != 0)
|
||||
|
@ -1354,6 +1746,7 @@ monitor_read_memory (memaddr, myaddr, len)
|
|||
{
|
||||
int retval, tmp;
|
||||
struct re_registers resp_strings;
|
||||
RDEBUG(("MON getmem.resp_delim %s\n",current_monitor->getmem.resp_delim)) ;
|
||||
|
||||
tmp = strlen (p);
|
||||
retval = re_search (&getmem_resp_delim_pattern, p, tmp, 0, tmp,
|
||||
|
@ -1372,27 +1765,35 @@ monitor_read_memory (memaddr, myaddr, len)
|
|||
p += strlen (current_monitor->getmem.resp_delim);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (remote_debug) printf("MON scanning %d ,%08x '%s'\n",len,p,p) ;
|
||||
if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
|
||||
{
|
||||
char c ;
|
||||
int fetched = 0 ;
|
||||
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));
|
||||
c = *p ;
|
||||
|
||||
|
||||
while (!(c == '\000' || c == '\n' || c == '\r') && i > 0)
|
||||
{ if (isxdigit (c))
|
||||
{ if ((dumpaddr >= memaddr) && (i > 0))
|
||||
{ val = fromhex (c) * 16 + fromhex (*(p+1));
|
||||
*myaddr++ = val;
|
||||
if (remote_debug) printf("[%02x]",val) ;
|
||||
--i;
|
||||
fetched++ ;
|
||||
}
|
||||
++dumpaddr;
|
||||
++p;
|
||||
}
|
||||
++p;
|
||||
++p; /* skip a blank or other non hex char */
|
||||
c = *p ;
|
||||
}
|
||||
return len;
|
||||
if (fetched == 0) error("Failed to read via monitor") ;
|
||||
if (remote_debug) printf("\n") ;
|
||||
return fetched ; /* Return the number of bytes actually read */
|
||||
}
|
||||
RDEBUG(("MON scanning bytes\n")) ;
|
||||
|
||||
for (i = len; i > 0; i--)
|
||||
{
|
||||
|
@ -1425,6 +1826,16 @@ monitor_read_memory (memaddr, myaddr, len)
|
|||
return len;
|
||||
}
|
||||
|
||||
/* This version supports very large reads by looping on multiline
|
||||
dump bytes outputs. Beware of buffering limits.
|
||||
*/
|
||||
static int monotor_read_memory_block(memaddr,myaddr,len)
|
||||
CORE_ADDR memaddr ;
|
||||
char * myaddr ;
|
||||
int len ;
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
monitor_xfer_memory (memaddr, myaddr, len, write, target)
|
||||
CORE_ADDR memaddr;
|
||||
|
@ -1486,6 +1897,7 @@ monitor_insert_breakpoint (addr, shadow)
|
|||
unsigned char *bp;
|
||||
int bplen;
|
||||
|
||||
RDEBUG(("MON inst bkpt %08x\n",addr))
|
||||
if (current_monitor->set_break == NULL)
|
||||
error ("No set_break defined for this monitor");
|
||||
|
||||
|
@ -1519,6 +1931,7 @@ monitor_remove_breakpoint (addr, shadow)
|
|||
{
|
||||
int i;
|
||||
|
||||
RDEBUG(("MON rmbkpt %08x\n",addr))
|
||||
if (current_monitor->clr_break == NULL)
|
||||
error ("No clr_break defined for this monitor");
|
||||
|
||||
|
@ -1580,6 +1993,7 @@ monitor_load (file, from_tty)
|
|||
int from_tty;
|
||||
{
|
||||
dcache_flush (remote_dcache);
|
||||
RDEBUG(("MON load\n"))
|
||||
|
||||
if (current_monitor->load_routine)
|
||||
current_monitor->load_routine (monitor_desc, file, hashmark);
|
||||
|
@ -1627,6 +2041,7 @@ monitor_load (file, from_tty)
|
|||
static void
|
||||
monitor_stop ()
|
||||
{
|
||||
RDEBUG(("MON stop\n")) ;
|
||||
if ((current_monitor->flags & MO_SEND_BREAK_ON_STOP) != 0)
|
||||
SERIAL_SEND_BREAK (monitor_desc);
|
||||
if (current_monitor->stop)
|
||||
|
|
|
@ -93,8 +93,16 @@ struct monitor_ops
|
|||
GDB with the value of a register. */
|
||||
char *dump_registers; /* Command to dump all regs at once */
|
||||
char *register_pattern; /* Pattern that picks out register from reg dump */
|
||||
void (*supply_register) PARAMS ((char *name, int namelen, char *val, int vallen));
|
||||
void (*load_routine) PARAMS ((serial_t desc, char *file, int hashmark)); /* Download routine */
|
||||
void (*supply_register) PARAMS ((char *name, int namelen,
|
||||
char *val, int vallen));
|
||||
void (*load_routine) PARAMS ((serial_t desc, char *file,
|
||||
int hashmark)); /* Download routine */
|
||||
int (*dumpregs) PARAMS((void)) ; /* routine to dump all registers */
|
||||
int (*continue_hook) PARAMS((void)) ; /* Emit the continue command */
|
||||
int (*wait_filter) PARAMS((char * buf, /* Maybe contains registers */
|
||||
int bufmax ,
|
||||
int * response_length,
|
||||
struct target_waitstatus * status)) ;
|
||||
char *load; /* load command */
|
||||
char *loadresp; /* Response to load command */
|
||||
char *prompt; /* monitor command prompt */
|
||||
|
@ -205,6 +213,20 @@ struct monitor_ops
|
|||
|
||||
#define MO_PRINT_PROGRAM_OUTPUT 0x200000
|
||||
|
||||
/* Some dump bytes commands align the first data with the preceeding
|
||||
16 byte boundary. Some print blanks and start at the exactly the
|
||||
requested boundary. */
|
||||
|
||||
#define MO_EXACT_DUMPADDR 0x400000
|
||||
|
||||
/* Rather entering and exiting the write memory dialog for each word byte,
|
||||
we can save time by transferring the whole block without exiting
|
||||
the memory editing mode. You only need to worry about this
|
||||
if you are doing memory downloading.
|
||||
This engages a new write function registered with dcache.
|
||||
*/
|
||||
#define MO_HAS_BLOCKWRITES 0x800000
|
||||
|
||||
#define SREC_SIZE 160
|
||||
|
||||
extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops,
|
||||
|
@ -221,3 +243,4 @@ extern void monitor_write PARAMS ((char *buf, int buflen));
|
|||
extern int monitor_readchar PARAMS ((void));
|
||||
extern char *monitor_get_dev_name PARAMS ((void));
|
||||
extern void init_monitor_ops PARAMS ((struct target_ops *));
|
||||
extern int monitor_dump_reg_block PARAMS((char * dump_cmd)) ;
|
||||
|
|
Loading…
Reference in New Issue