From 2a8b1fab7c1802f6297c22dd95e79ba8ea0eb6c7 Mon Sep 17 00:00:00 2001 From: John Metzler Date: Wed, 29 Apr 1998 17:33:57 +0000 Subject: [PATCH] Wed Apr 29 10:20:40 1998 John Metzler * 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 --- gdb/ChangeLog | 44 +++++ gdb/monitor.c | 531 ++++++++++++++++++++++++++++++++++++++++++++------ gdb/monitor.h | 27 ++- 3 files changed, 542 insertions(+), 60 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b12a3e19bf9..4ce8279b882 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,47 @@ +Wed Apr 29 10:20:40 1998 John Metzler + + * 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 * Makefile.in (GDBTKLIBS): New macro. diff --git a/gdb/monitor.c b/gdb/monitor.c index 03bfa598dc6..bd07a2af4d2 100644 --- a/gdb/monitor.c +++ b/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); - } + if (current_monitor->getreg.term_cmd) + { RDEBUG(("EMIT getreg.term.cmd\n")) + monitor_printf (current_monitor->getreg.term_cmd); } - else + 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) diff --git a/gdb/monitor.h b/gdb/monitor.h index 48e83ba82e2..6864165ffb3 100644 --- a/gdb/monitor.h +++ b/gdb/monitor.h @@ -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)) ; -- 2.30.2