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:
John Metzler 1998-04-29 17:33:57 +00:00
parent 2325ac592f
commit 2a8b1fab7c
3 changed files with 543 additions and 61 deletions

View File

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

View File

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

View File

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