diff options
Diffstat (limited to 'gdb/remote-e7000.c')
-rw-r--r-- | gdb/remote-e7000.c | 1109 |
1 files changed, 656 insertions, 453 deletions
diff --git a/gdb/remote-e7000.c b/gdb/remote-e7000.c index 644650e..b4aaaed 100644 --- a/gdb/remote-e7000.c +++ b/gdb/remote-e7000.c @@ -1,5 +1,5 @@ /* Remote debugging interface for Hitachi E7000 ICE, for GDB - Copyright 1993 Free Software Foundation, Inc. + Copyright 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Steve Chamberlain for Cygnus Support. @@ -20,87 +20,117 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* The E7000 is an in-circuit emulator for the Hitachi H8/300-H and + Hitachi-SH processor. It has serial port and a lan port. + + The monitor command set makes it difficult to load large ammounts of + data over the lan without using ftp - so try not to issue load + commands when communicating over ethernet; use the ftpload command. + + The monitor pauses for a second when dumping srecords to the serial + line too, so we use a slower per byte mechanism but without the + startup overhead. Even so, it's pretty slow... */ #include "defs.h" #include "gdbcore.h" +#include "inferior.h" #include "target.h" #include "wait.h" -#include <varargs.h> +#include "value.h" +#include "command.h" #include <signal.h> -#include <string.h> +#include "gdb_string.h" #include <sys/types.h> #include "serial.h" +#include "remote-utils.h" +#if 0 +#define HARD_BREAKPOINTS +#define BC_BREAKPOINTS 0 +#endif -/* The E7000 is an in-circuit emulator for the Hitachi H8/300-H and -Hitachi-SH processor. It has serial port and a lan port. - -The monitor command set makes it difficult to load large ammounts of -data over the lan without using ftp - so try not to issue load -commands when communicating over ethernet; use the ftpload command. - -The monitor pauses for a second when dumping srecords to the serial -line too, so we use a slower per byte mechanism but without the -startup overhead. Even so, it's pretty slow... */ - -int using_tcp; /* nonzero if using the tcp serial driver */ - -extern struct target_ops e7000_ops; /* Forward declaration */ #define CTRLC 0x03 #define ENQ 0x05 #define ACK 0x06 #define CTRLZ 0x1a -char *ENQSTRING = "\005"; +extern void notice_quit PARAMS ((void)); -int echo; -int ctrl_c; -static void e7000_close (); -static void e7000_fetch_register (); -static void e7000_store_register (); +/* Local function declarations. */ -static int timeout = 5; +static void e7000_close PARAMS ((int)); + +static void e7000_fetch_register PARAMS ((int)); + +static void e7000_store_register PARAMS ((int)); + +static void e7000_command PARAMS ((char *, int)); + +static void e7000_login_command PARAMS ((char *, int)); + +static void e7000_ftp_command PARAMS ((char *, int)); + +static void e7000_drain_command PARAMS ((char *, int)); static void expect PARAMS ((char *)); -static void expect_full_prompt PARAMS (()); -static void expect_prompt PARAMS (()); + +static void expect_full_prompt PARAMS ((void)); + +static void expect_prompt PARAMS ((void)); + +/* Variables. */ + static serial_t e7000_desc; +/* Nonzero if using the tcp serial driver. */ -/* Send data to e7000debug. Works just like printf. */ -#if 0 -static void -printf_e7000debug (va_alist) - va_dcl -{ - va_list args; - char *pattern; - char buf[200]; +static int using_tcp; - va_start (args); +/* Nonzero if using the pc isa card. */ - pattern = va_arg (args, char *); +static int using_pc; - vsprintf (buf, pattern, args); -#else +extern struct target_ops e7000_ops; /* Forward declaration */ + +char *ENQSTRING = "\005"; + +/* Nonzero if some routine (as opposed to the user) wants echoing. + FIXME: Do this reentrantly with an extra parameter. */ + +static int echo; + +static int ctrl_c; + +static int timeout = 5; + +/* Send data to e7000debug. */ static void -printf_e7000debug(a,b,c,d,e) - { - char buf[200]; - sprintf(buf, a,b,c,d,e); -#endif +puts_e7000debug (buf) + char *buf; +{ + if (!e7000_desc) + error ("Use \"target e7000 ...\" first."); + + if (remote_debug) + printf("Sending %s\n", buf); + if (SERIAL_WRITE (e7000_desc, buf, strlen (buf))) fprintf (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno)); - /* And expect to see it echoed */ - expect (buf); + /* And expect to see it echoed, unless using the pc interface */ +#if 0 + if (!using_pc) +#endif + expect (buf); } static void putchar_e7000 (x) + int x; { char b[1]; + b[0] = x; SERIAL_WRITE (e7000_desc, b, 1); } @@ -112,6 +142,15 @@ write_e7000 (s) SERIAL_WRITE (e7000_desc, s, strlen (s)); } +static int +normal (x) + int x; +{ + if (x == '\n') + return '\r'; + return x; +} + /* Read a character from the remote system, doing all the fancy timeout stuff. */ @@ -120,47 +159,78 @@ readchar (timeout) int timeout; { int c; + do { c = SERIAL_READCHAR (e7000_desc, timeout); } while (c > 127); + if (c == SERIAL_TIMEOUT) { if (timeout == 0) - return c; /* Polls shouldn't generate timeout errors */ - + return -1; + echo = 0; error ("Timeout reading from remote system."); } - return c; + if (remote_debug) + { + putchar (c); + fflush (stdout); + } + + return normal (c); } +#if 0 +char * +tl (x) +{ + static char b[8][10]; + static int p; + + p++; + p &= 7; + if (x >= ' ') + { + b[p][0] = x; + b[p][1] = 0; + } + else + { + sprintf(b[p], "<%d>", x); + } + + return b[p]; +} +#endif + +/* Scan input from the remote system, until STRING is found. If + DISCARD is non-zero, then discard non-matching input, else print it + out. Let the user break out immediately. */ -/* Scan input from the remote system, until STRING is found. If DISCARD is - non-zero, then discard non-matching input, else print it out. - Let the user break out immediately. */ static void expect (string) char *string; { char *p = string; int c; + int nl = 0; while (1) - { c = readchar (timeout); - notice_quit (); if (quit_flag == 1) { - if (ctrl_c) { - putchar_e7000(CTRLC); - ctrl_c -- ; - } + if (ctrl_c) + { + putchar_e7000(CTRLC); + --ctrl_c; + } else { - quit(); + quit (); } } @@ -168,22 +238,32 @@ expect (string) { error ("Serial communication error"); } - if (echo) + if (echo || remote_debug) { - if (c != '\r') - putchar (c); + if (c == '\r' || c == '\n') + { + if (!nl) + putchar ('\n'); + nl = 1; + } + else + { + nl = 0; + putchar (c); + } fflush (stdout); } - if (c == *p++) + if (normal (c) == normal (*p++)) { if (*p == '\0') - { - return; - } + return; } else { p = string; + + if (normal (c) == normal (string[0])) + p++; } } } @@ -194,27 +274,29 @@ expect (string) o give your command o *then* wait for the prompt. - Thus the last thing that a procedure does with the serial line - will be an expect_prompt(). Exception: e7000_resume does not - wait for the prompt, because the terminal is being handed over - to the inferior. However, the next thing which happens after that - is a e7000_wait which does wait for the prompt. - Note that this includes abnormal exit, e.g. error(). This is - necessary to prevent getting into states from which we can't - recover. */ + Thus the last thing that a procedure does with the serial line will + be an expect_prompt(). Exception: e7000_resume does not wait for + the prompt, because the terminal is being handed over to the + inferior. However, the next thing which happens after that is a + e7000_wait which does wait for the prompt. Note that this includes + abnormal exit, e.g. error(). This is necessary to prevent getting + into states from which we can't recover. */ + static void expect_prompt () { expect (":"); } + static void expect_full_prompt () { - expect ("\n:"); + expect ("\r:"); } static int -get_hex_digit (ch) +convert_hex_digit (ch) + int ch; { if (ch >= '0' && ch <= '9') return ch - '0'; @@ -223,20 +305,17 @@ get_hex_digit (ch) else if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; return -1; - } - - static int get_hex (start) int *start; { - int value = get_hex_digit (*start); + int value = convert_hex_digit (*start); int try; *start = readchar (timeout); - while ((try = get_hex_digit (*start)) >= 0) + while ((try = convert_hex_digit (*start)) >= 0) { value <<= 4; value += try; @@ -245,8 +324,9 @@ get_hex (start) return value; } -/* Get N 32-bit words from remote, each preceded by a space, - and put them in registers starting at REGNO. */ +#if 0 +/* Get N 32-bit words from remote, each preceded by a space, and put + them in registers starting at REGNO. */ static void get_hex_regs (n, regno) @@ -266,9 +346,11 @@ get_hex_regs (n, regno) supply_register (regno++, (char *) &val); } } +#endif /* This is called not only when we first attach, but also when the user types "run" after having attached. */ + static void e7000_create_inferior (execfile, args, env) char *execfile; @@ -308,8 +390,8 @@ e7000_create_inferior (execfile, args, env) proceed ((CORE_ADDR) entry_pt, -1, 0); /* Let 'er rip... */ } -/* Open a connection to a remote debugger. - NAME is the filename used for communication. */ +/* Open a connection to a remote debugger. NAME is the filename used + for communication. */ static int baudrate = 9600; static char dev_name[100]; @@ -320,6 +402,7 @@ static char *passwd = ""; static char *dir = ""; /* Grab the next token and buy some space for it */ + static char * next (ptr) char **ptr; @@ -328,10 +411,9 @@ next (ptr) char *s; char *r; int l = 0; + while (*p && *p == ' ') - { - p++; - } + p++; s = p; while (*p && (*p != ' ' && *p != '\t')) { @@ -345,8 +427,8 @@ next (ptr) return r; } -static -e7000_login (args, from_tty) +static void +e7000_login_command (args, from_tty) char *args; int from_tty; { @@ -369,26 +451,34 @@ e7000_login (args, from_tty) /* Start an ftp transfer from the E7000 to a host */ -static -e7000_ftp (args, from_tty) +static void +e7000_ftp_command (args, from_tty) char *args; int from_tty; { + /* FIXME: arbitrary limit on machine names and such. */ + char buf[200]; + int oldtimeout = timeout; timeout = 10; - printf_e7000debug ("ftp %s\r", machine); + + sprintf (buf, "ftp %s\r", machine); + puts_e7000debug (buf); expect (" Username : "); - printf_e7000debug ("%s\r", user); + sprintf (buf, "%s\r", user); + puts_e7000debug (buf); expect (" Password : "); write_e7000 (passwd); write_e7000 ("\r"); expect ("success\r"); expect ("FTP>"); - printf_e7000debug ("cd %s\r", dir); + sprintf (buf, "cd %s\r", dir); + puts_e7000debug (buf); expect ("FTP>"); - printf_e7000debug ("ll 0;s:%s\r", args); + sprintf (buf, "ll 0;s:%s\r", args); + puts_e7000debug (buf); expect ("FTP>"); - printf_e7000debug ("bye\r"); + puts_e7000debug ("bye\r"); expect (":"); timeout = oldtimeout; } @@ -399,46 +489,65 @@ e7000_open (args, from_tty) int from_tty; { int n; + int loop; char junk[100]; int sync; target_preopen (from_tty); - if (args) - n = sscanf (args, " %s %d %s", dev_name, &baudrate, junk); - else - n = 0; - if (n != 1 && n != 2) - error ("Bad arguments. Usage:\ttarget e7000 <device> <speed>\n\ -or \t\ttarget e7000 <host>[:<port>]\n"); - - if (n == 1 && strchr (dev_name, ':') == 0) + n = 0; + if (args && strcasecmp (args, "pc") == 0) + { + strcpy (dev_name, args); + } + else { - /* Default to normal telnet port */ - strcat (dev_name, ":23"); + if (args) + { + n = sscanf (args, " %s %d %s", dev_name, &baudrate, junk); + } + + if (n != 1 && n != 2) + { + error ("Bad arguments. Usage:\ttarget e7000 <device> <speed>\n\ +or \t\ttarget e7000 <host>[:<port>]\n\ +or \t\ttarget e7000 pc\n"); + } + +#ifndef __GO32__ + if (n == 1 && strchr (dev_name, ':') == 0) + { + /* Default to normal telnet port */ + strcat (dev_name, ":23"); + } +#endif } push_target (&e7000_ops); - e7000_desc = SERIAL_OPEN (dev_name); + e7000_desc = SERIAL_OPEN (dev_name); if (!e7000_desc) perror_with_name (dev_name); using_tcp = strcmp (e7000_desc->ops->name, "tcp") == 0; + using_pc = strcmp (e7000_desc->ops->name, "pc") == 0; SERIAL_SETBAUDRATE (e7000_desc, baudrate); SERIAL_RAW (e7000_desc); /* Hello? Are you there? */ sync = 0; + loop = 0; putchar_e7000 (CTRLC); while (!sync) { int c; + if (from_tty) printf_unfiltered ("[waiting for e7000...]\n"); - write_e7000 ("\r\n"); - c = SERIAL_READCHAR (e7000_desc, 3); + + write_e7000 ("\r"); + c = SERIAL_READCHAR (e7000_desc, 1); while (c != SERIAL_TIMEOUT) { /* Dont echo cr's */ @@ -448,18 +557,27 @@ or \t\ttarget e7000 <host>[:<port>]\n"); fflush (stdout); } if (c == ':') + sync = 1; + + if (loop++ == 20) { - sync = 1; + putchar_e7000 (CTRLC); + loop = 0; } - c = SERIAL_READCHAR (e7000_desc, 3); + + QUIT ; + + if (quit_flag) { putchar_e7000 (CTRLC); quit_flag = 0; } + c = SERIAL_READCHAR (e7000_desc, 1); } } - printf_e7000debug ("\r\n"); + puts_e7000debug ("\r"); + expect_prompt (); if (from_tty) @@ -484,9 +602,9 @@ e7000_close (quitting) } } -/* Terminate the open connection to the remote debugger. - Use this when you want to detach and do something else - with your gdb. */ +/* Terminate the open connection to the remote debugger. Use this + when you want to detach and do something else with your gdb. */ + static void e7000_detach (from_tty) int from_tty; @@ -503,31 +621,26 @@ e7000_resume (pid, step, sig) int pid, step, sig; { if (step) - { - printf_e7000debug ("S\r"); - } + puts_e7000debug ("S\r"); else - { - printf_e7000debug ("G\r"); - } + puts_e7000debug ("G\r"); } /* Read the remote registers into the block REGS. For the H8/300 a register dump looks like: - - PC=00021A CCR=80:I******* - ER0 - ER3 0000000A 0000002E 0000002E 00000000 - ER4 - ER7 00000000 00000000 00000000 00FFEFF6 - 000218 MOV.B R1L,R2L - STEP NORMAL END or - BREAK POINT - */ + PC=00021A CCR=80:I******* + ER0 - ER3 0000000A 0000002E 0000002E 00000000 + ER4 - ER7 00000000 00000000 00000000 00FFEFF6 + 000218 MOV.B R1L,R2L + STEP NORMAL END or + BREAK POINT + */ #ifdef GDB_TARGET_IS_H8300 -char *want = "\n\ - PC=%p CCR=%c\n\ + +char *want = "PC=%p CCR=%c\n\ ER0 - ER3 %0 %1 %2 %3\n\ ER4 - ER7 %4 %5 %6 %7\n"; @@ -535,14 +648,15 @@ char *want_nopc = "%p CCR=%c\n\ ER0 - ER3 %0 %1 %2 %3\n\ ER4 - ER7 %4 %5 %6 %7"; - #endif + #ifdef GDB_TARGET_IS_SH -char *want = "\n PC=%16 SR=%22\n\ - PR=%17 GBR=%18 VBR=%19\n\ - MACH=%20 MACL=%21\n\ - R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\ - R8-15 %8 %9 %10 %11 %12 %13 %14 %15\n"; + +char *want = "PC=%16 SR=%22\n\ +PR=%17 GBR=%18 VBR=%19\n\ +MACH=%20 MACL=%21\n\ +R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\ +R8-15 %8 %9 %10 %11 %12 %13 %14 %15\n"; char *want_nopc = "%16 SR=%22\n\ PR=%17 GBR=%18 VBR=%19\n\ @@ -550,31 +664,29 @@ char *want_nopc = "%16 SR=%22\n\ R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\ R8-15 %8 %9 %10 %11 %12 %13 %14 %15"; - #endif -static -int +static int gch () { int c = readchar (timeout); - if (echo) + + if (remote_debug) { if (c >= ' ') printf ("%c", c); else if (c == '\n') - printf ("\n", c); + printf ("\n"); } return c; } - -static -unsigned int +static unsigned int gbyte () { - int high = get_hex_digit (gch ()); - int low = get_hex_digit (gch ()); + int high = convert_hex_digit (gch ()); + int low = convert_hex_digit (gch ()); + return (high << 4) + low; } @@ -586,24 +698,27 @@ fetch_regs_from_dump (nextchar, want) int regno; char buf[MAX_REGISTER_RAW_SIZE]; - int thischar = nextchar(); - + int thischar = nextchar (); + while (*want) { switch (*want) { case '\n': - while (thischar != '\n') - thischar = nextchar(); - thischar = nextchar(); - while (thischar == '\r') - thischar = nextchar(); + /* Skip to end of line and then eat all new line type stuff */ + while (thischar != '\n' && thischar != '\r') + thischar = nextchar (); + while (thischar == '\n' || thischar == '\r') + thischar = nextchar (); want++; break; case ' ': - while (thischar == ' ' || thischar == '\t' || thischar == '\r' || thischar == '\n') - thischar = nextchar(); + while (thischar == ' ' + || thischar == '\t' + || thischar == '\r' + || thischar == '\n') + thischar = nextchar (); want++; break; @@ -612,15 +727,16 @@ fetch_regs_from_dump (nextchar, want) { want++; if (*want) - thischar = nextchar(); + thischar = nextchar (); } - else if (thischar == ' ') + else if (thischar == ' ' || thischar == '\n' || thischar == '\r') { - thischar = nextchar(); + thischar = nextchar (); } else { - error("out of sync in fetch registers"); + error ("out of sync in fetch registers wanted <%s>, got <%c 0x%x>", + want, thischar, thischar); } break; @@ -654,14 +770,13 @@ fetch_regs_from_dump (nextchar, want) break; #endif - default: - if (isdigit(want[0])) + if (isdigit (want[0])) { - if (isdigit(want[1])) + if (isdigit (want[1])) { regno = (want[0] - '0') * 10 + want[1] - '0'; - want+=2; + want += 2; } else { @@ -671,11 +786,11 @@ fetch_regs_from_dump (nextchar, want) } else - abort(); + abort (); } store_signed_integer (buf, REGISTER_RAW_SIZE(regno), - (LONGEST)get_hex(&thischar, nextchar)); + (LONGEST) get_hex (&thischar, nextchar)); supply_register (regno, buf); break; } @@ -687,22 +802,22 @@ e7000_fetch_registers () { int regno; - printf_e7000debug ("R\r"); + puts_e7000debug ("R\r"); fetch_regs_from_dump (gch, want); /* And supply the extra ones the simulator uses */ for (regno = NUM_REALREGS; regno < NUM_REGS; regno++) { int buf = 0; + supply_register (regno, (char *) (&buf)); } } -/* Fetch register REGNO, or all registers if REGNO is -1. - Returns errno value. */ +/* Fetch register REGNO, or all registers if REGNO is -1. Returns + errno value. */ -static -void +static void e7000_fetch_register (regno) int regno; { @@ -722,80 +837,84 @@ e7000_store_registers () registers_changed (); } -/* Store register REGNO, or all if REGNO == 0. - Return errno value. */ +/* Store register REGNO, or all if REGNO == 0. Return errno value. */ + static void e7000_store_register (regno) int regno; { + char buf[200]; + if (regno == -1) { e7000_store_registers (); return; } + #ifdef GDB_TARGET_IS_H8300 if (regno <= 7) { - printf_e7000debug (".ER%d %x\r", regno, - read_register (regno)); - + sprintf (buf, ".ER%d %x\r", regno, read_register (regno)); + puts_e7000debug (buf); } else if (regno == PC_REGNUM) { - printf_e7000debug (".PC %x\r", - read_register (regno)); + sprintf (buf, ".PC %x\r", read_register (regno)); + puts_e7000debug (buf); } else if (regno == CCR_REGNUM) { - printf_e7000debug (".CCR %x\r", - read_register (regno)); + sprintf (buf, ".CCR %x\r", read_register (regno)); + puts_e7000debug (buf); } -#endif +#endif /* GDB_TARGET_IS_H8300 */ #ifdef GDB_TARGET_IS_SH switch (regno) { default: - printf_e7000debug (".R%d %x\r", regno, - read_register (regno)); - + sprintf (buf, ".R%d %x\r", regno, read_register (regno)); + puts_e7000debug (buf); break; + case PC_REGNUM: - printf_e7000debug (".PC %x\r", - read_register (regno)); + sprintf (buf, ".PC %x\r", read_register (regno)); + puts_e7000debug (buf); break; + case SR_REGNUM: - printf_e7000debug (".SR %x\r", - read_register (regno)); + sprintf (buf, ".SR %x\r", read_register (regno)); + puts_e7000debug (buf); break; case PR_REGNUM: - printf_e7000debug (".PR %x\r", - read_register (regno)); + sprintf (buf, ".PR %x\r", read_register (regno)); + puts_e7000debug (buf); break; case GBR_REGNUM: - printf_e7000debug (".GBR %x\r", - read_register (regno)); + sprintf (buf, ".GBR %x\r", read_register (regno)); + puts_e7000debug (buf); break; case VBR_REGNUM: - printf_e7000debug (".VBR %x\r", - read_register (regno)); + sprintf (buf, ".VBR %x\r", read_register (regno)); + puts_e7000debug (buf); break; case MACH_REGNUM: - printf_e7000debug (".MACH %x\r", - read_register (regno)); + sprintf (buf, ".MACH %x\r", read_register (regno)); + puts_e7000debug (buf); break; case MACL_REGNUM: - printf_e7000debug (".MACL %x\r", - read_register (regno)); + sprintf (buf, ".MACL %x\r", read_register (regno)); + puts_e7000debug (buf); break; } -#endif +#endif /* GDB_TARGET_IS_SH */ + expect_prompt (); } @@ -814,23 +933,24 @@ e7000_prepare_to_store () static void e7000_files_info () { - printf ("\tAttached to %s at %d baud.\n", - dev_name, baudrate); + printf ("\tAttached to %s at %d baud.\n", dev_name, baudrate); } -static -int +static int stickbyte (where, what) char *where; unsigned int what; { static CONST char digs[] = "0123456789ABCDEF"; + where[0] = digs[(what >> 4) & 0xf]; where[1] = digs[(what & 0xf) & 0xf]; + return what; } -/* Write a small ammount of memory */ +/* Write a small ammount of memory. */ + static int write_small (memaddr, myaddr, len) CORE_ADDR memaddr; @@ -838,30 +958,34 @@ write_small (memaddr, myaddr, len) int len; { int i; + char buf[200]; + for (i = 0; i < len; i++) { - if (((memaddr + i) & 3) == 0 - && (i + 3 < len)) + if (((memaddr + i) & 3) == 0 && (i + 3 < len)) { /* Can be done with a long word */ - printf_e7000debug ("m %x %x%02x%02x%02x;l\r", - memaddr + i, - myaddr[i], - myaddr[i + 1], - myaddr[i + 2], - myaddr[i + 3]); + sprintf (buf, "m %x %x%02x%02x%02x;l\r", + memaddr + i, + myaddr[i], myaddr[i + 1], myaddr[i + 2], myaddr[i + 3]); + puts_e7000debug (buf); i += 3; } else { - printf_e7000debug ("m %x %x\r", memaddr + i, myaddr[i]); + sprintf (buf, "m %x %x\r", memaddr + i, myaddr[i]); + puts_e7000debug (buf); } } + expect_prompt (); + return len; } -/* Write a large ammount of memory, this only works with the serial mode enabled. - Command is sent as + +/* Write a large ammount of memory, this only works with the serial + mode enabled. Command is sent as + il ;s:s\r -> <- il ;s:s\r <- ENQ @@ -872,7 +996,7 @@ write_small (memaddr, myaddr, len) <- ENQ ACK -> <- : - */ + */ static int write_large (memaddr, myaddr, len) @@ -881,14 +1005,14 @@ write_large (memaddr, myaddr, len) int len; { int i; - int c; #define maxstride 128 int stride; - printf_e7000debug ("IL ;S:FK\r"); + puts_e7000debug ("IL ;S:FK\r"); expect (ENQSTRING); putchar_e7000 (ACK); expect ("LO FK\r"); + for (i = 0; i < len; i += stride) { char compose[maxstride * 2 + 50]; @@ -897,6 +1021,7 @@ write_large (memaddr, myaddr, len) int check_sum; int where = 0; int alen; + stride = len - i; if (stride > maxstride) stride = maxstride; @@ -904,17 +1029,15 @@ write_large (memaddr, myaddr, len) compose[where++] = 'S'; check_sum = 0; if (address >= 0xffffff) - { - alen = 4; - } + alen = 4; else if (address >= 0xffff) - { - alen = 3; - } + alen = 3; else alen = 2; - compose[where++] = alen - 1 + '0'; /* insert type */ - check_sum += stickbyte (compose + where, alen + stride + 1); /* Insert length */ + /* Insert type. */ + compose[where++] = alen - 1 + '0'; + /* Insert length. */ + check_sum += stickbyte (compose + where, alen + stride + 1); where += 2; while (alen > 0) { @@ -928,81 +1051,69 @@ write_large (memaddr, myaddr, len) check_sum += stickbyte (compose + where, myaddr[i + j]); where += 2; } - stickbyte (compose + where, ~check_sum); - where += 2; compose[where++] = '\r'; compose[where++] = '\n'; compose[where++] = 0; - { - char *z; - for (z = compose; *z; z++) ; + + SERIAL_WRITE (e7000_desc, compose, where); + j = SERIAL_READCHAR (e7000_desc, 0); + if (j == SERIAL_TIMEOUT) { - SERIAL_WRITE (e7000_desc, compose, where); - j = SERIAL_READCHAR (e7000_desc, 0); - if (j == SERIAL_TIMEOUT) - { - /* This is ok - nothing there */ - } - else if (j == ENQ) - { - /* Hmm, it's trying to tell us something */ - expect (":"); - error ("Error writing memory"); - } - else + /* This is ok - nothing there */ + } + else if (j == ENQ) + { + /* Hmm, it's trying to tell us something */ + expect (":"); + error ("Error writing memory"); + } + else + { + printf ("@%d}@", j); + while ((j = SERIAL_READCHAR(e7000_desc,0)) > 0) { - printf ("@%d}@", j); - while ((j = SERIAL_READCHAR(e7000_desc,0)) > 0) - { - printf ("@{%d}@",j); - } + printf ("@{%d}@",j); } } - } } + /* Send the trailer record */ write_e7000 ("S70500000000FA\r"); putchar_e7000 (CTRLZ); expect (ENQSTRING); putchar_e7000 (ACK); expect (":"); + return len; } -/* Copy LEN bytes of data from debugger memory at MYADDR - to inferior's memory at MEMADDR. Returns length moved. +/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's + memory at MEMADDR. Returns length moved. + + Can't use the Srecord load over ethernet, so don't use fast method + then. */ - Can't use the Srecord load over ethernet, so dont use - fast method then. - */ static int e7000_write_inferior_memory (memaddr, myaddr, len) CORE_ADDR memaddr; unsigned char *myaddr; int len; { - if (len < 16 || using_tcp) - { - return write_small (memaddr, myaddr, len); - } + if (len < 16 || using_tcp || using_pc) + return write_small (memaddr, myaddr, len); else - { - return write_large (memaddr, myaddr, len); - } + return write_large (memaddr, myaddr, len); } - /* Read LEN bytes from inferior memory at MEMADDR. Put the result at debugger address MYADDR. Returns length moved. - Small transactions we send m <addr>;l and receive 00000000 12345678 ? - */ static int @@ -1014,30 +1125,33 @@ e7000_read_inferior_memory (memaddr, myaddr, len) int count; int c; int i; + char buf[200]; /* Starting address of this pass. */ +/* printf("READ INF %x %x %d\n", memaddr, myaddr, len);*/ if (((memaddr - 1) + len) < memaddr) { errno = EIO; return 0; } - printf_e7000debug ("m %x;l\r", memaddr); + sprintf (buf, "m %x;l\r", memaddr); + puts_e7000debug (buf); for (count = 0; count < len; count += 4) { /* Suck away the address */ - c = gch(); + c = gch (); while (c != ' ') - c = gch(); - c = gch(); + c = gch (); + c = gch (); if (c == '*') { /* Some kind of error */ expect_prompt(); return -1; } while (c != ' ') - c = gch(); + c = gch (); /* Now read in the data */ for (i = 0; i < 4; i++) @@ -1049,14 +1163,16 @@ e7000_read_inferior_memory (memaddr, myaddr, len) } /* Skip the trailing ? and send a . to end and a cr for more */ - gch(); - gch(); + gch (); + gch (); if (count + 4 >= len) - printf_e7000debug(".\r"); + puts_e7000debug(".\r"); else - printf_e7000debug("\r"); + puts_e7000debug("\r"); + } expect_prompt(); + return len; } @@ -1075,7 +1191,6 @@ e7000_read_inferior_memory (memaddr, myaddr, len) A cost in chars for each transaction of 80 + 5*n-bytes. - Large transactions could be done with the srecord load code, but there is a pause for a second before dumping starts, which slows the average rate down! @@ -1089,6 +1204,7 @@ e7000_read_inferior_memory (memaddr, myaddr, len) { int count; int c; + char buf[200]; /* Starting address of this pass. */ @@ -1098,7 +1214,8 @@ e7000_read_inferior_memory (memaddr, myaddr, len) return 0; } - printf_e7000debug ("d %x %x\r", memaddr, memaddr + len - 1); + sprintf (buf, "d %x %x\r", memaddr, memaddr + len - 1); + puts_e7000debug (buf); count = 0; c = gch (); @@ -1156,6 +1273,7 @@ fast_but_for_the_pause_e7000_read_inferior_memory (memaddr, myaddr, len) { int loop; int c; + char buf[200]; if (((memaddr - 1) + len) < memaddr) { @@ -1163,7 +1281,8 @@ fast_but_for_the_pause_e7000_read_inferior_memory (memaddr, myaddr, len) return 0; } - printf_e7000debug ("is %x@%x:s\r", memaddr, len); + sprintf (buf, "is %x@%x:s\r", memaddr, len); + puts_e7000debug (buf); gch (); c = gch (); if (c != ENQ) @@ -1180,6 +1299,7 @@ fast_but_for_the_pause_e7000_read_inferior_memory (memaddr, myaddr, len) int length; int addr; int i; + c = gch (); switch (c) { @@ -1207,6 +1327,7 @@ fast_but_for_the_pause_e7000_read_inferior_memory (memaddr, myaddr, len) case '3': { int alen; + alen = type - '0' + 1; addr = 0; while (alen--) @@ -1216,14 +1337,14 @@ fast_but_for_the_pause_e7000_read_inferior_memory (memaddr, myaddr, len) } for (i = 0; i < length - 1; i++) - { - myaddr[i + addr - memaddr] = gbyte (); - } + myaddr[i + addr - memaddr] = gbyte (); + gbyte (); /* Ignore checksum */ } } } } + putchar_e7000 (ACK); expect ("TOP ADDRESS ="); expect ("END ADDRESS ="); @@ -1243,13 +1364,9 @@ e7000_xfer_inferior_memory (memaddr, myaddr, len, write, target) struct target_ops *target; /* ignored */ { if (write) - { - return e7000_write_inferior_memory( memaddr, myaddr, len); - } + return e7000_write_inferior_memory( memaddr, myaddr, len); else - { - return e7000_read_inferior_memory( memaddr, myaddr, len); - } + return e7000_read_inferior_memory( memaddr, myaddr, len); } static void @@ -1257,7 +1374,6 @@ e7000_kill (args, from_tty) char *args; int from_tty; { - } /* Clean up when a program exits. @@ -1274,11 +1390,15 @@ e7000_mourn_inferior () generic_mourn_inferior (); /* Do all the proper things now */ } +#ifdef HARD_BREAKPOINTS +#define MAX_E7000DEBUG_BREAKPOINTS (BC_BREAKPOINTS ? 5 : 200) +#else #define MAX_E7000DEBUG_BREAKPOINTS 200 +#endif extern int memory_breakpoint_size; -static CORE_ADDR breakaddr[MAX_E7000DEBUG_BREAKPOINTS] = -{0}; + +static CORE_ADDR breakaddr[MAX_E7000DEBUG_BREAKPOINTS] = {0}; static int e7000_insert_breakpoint (addr, shadow) @@ -1286,6 +1406,7 @@ e7000_insert_breakpoint (addr, shadow) unsigned char *shadow; { int i; + char buf[200]; static char nop[2] = NOP; for (i = 0; i <= MAX_E7000DEBUG_BREAKPOINTS; i++) @@ -1293,14 +1414,30 @@ e7000_insert_breakpoint (addr, shadow) { breakaddr[i] = addr; /* Save old contents, and insert a nop in the space */ +#ifdef HARD_BREAKPOINTS + if (BC_BREAKPOINTS) + { + sprintf (buf, "BC%d A=%x\r", i+1, addr); + puts_e7000debug (buf); + } + else + { + sprintf (buf, "B %x\r", addr); + puts_e7000debug (buf); + } +#else e7000_read_inferior_memory (addr, shadow, 2); e7000_write_inferior_memory (addr, nop, 2); - printf_e7000debug ("B %x\r", addr); + + sprintf (buf, "B %x\r", addr); + puts_e7000debug (buf); +#endif expect_prompt (); return 0; } - error("Too many breakpoints ( > %d) for the E7000\n", MAX_E7000DEBUG_BREAKPOINTS); + error ("Too many breakpoints ( > %d) for the E7000\n", + MAX_E7000DEBUG_BREAKPOINTS); return 1; } @@ -1310,48 +1447,74 @@ e7000_remove_breakpoint (addr, shadow) unsigned char *shadow; { int i; + char buf[200]; for (i = 0; i < MAX_E7000DEBUG_BREAKPOINTS; i++) if (breakaddr[i] == addr) { breakaddr[i] = 0; - printf_e7000debug ("B - %x\r", addr); +#ifdef HARD_BREAKPOINTS + if (BC_BREAKPOINTS) + { + sprintf (buf, "BC%d - \r", i+1); + puts_e7000debug (buf); + } + else + { + sprintf (buf, "B - %x\r", addr); + puts_e7000debug (buf); + } expect_prompt (); +#else + sprintf (buf, "B - %x\r", addr); + puts_e7000debug (buf); + expect_prompt (); + /* Replace the insn under the break */ e7000_write_inferior_memory (addr, shadow, 2); +#endif + return 0; } - fprintf (stderr, "Can't find breakpoint associated with 0x%x\n", addr); + warning ("Can't find breakpoint associated with 0x%x\n", addr); return 1; } - -/* Put a command string, in args, out to STDBUG. Output from STDBUG is placed - on the users terminal until the prompt is seen. */ +/* Put a command string, in args, out to STDBUG. Output from STDBUG + is placed on the users terminal until the prompt is seen. */ static void e7000_command (args, fromtty) char *args; int fromtty; { + /* FIXME: arbitrary limit on length of args. */ + char buf[200]; + + echo = 0; if (!e7000_desc) error ("e7000 target not open."); if (!args) { - printf_e7000debug ("\r"); + puts_e7000debug ("\r"); } else { - printf_e7000debug ("%s\r", args); + sprintf (buf, "%s\r", args); + puts_e7000debug (buf); } + echo++; ctrl_c = 2; expect_full_prompt (); echo--; ctrl_c = 0; printf_unfiltered ("\n"); + + /* Who knows what the command did... */ + registers_changed (); } static void @@ -1363,17 +1526,19 @@ e7000_load (args, fromtty) } static void -e7000_drain (args, fromtty) +e7000_drain_command (args, fromtty) char *args; int fromtty; { int c; - printf_e7000debug("end\r"); + + puts_e7000debug("end\r"); putchar_e7000 (CTRLC); + while ((c = SERIAL_READCHAR (e7000_desc, 1) != SERIAL_TIMEOUT)) { - if(quit_flag) + if (quit_flag) { putchar_e7000(CTRLC); quit_flag = 0; @@ -1385,36 +1550,30 @@ e7000_drain (args, fromtty) } } -e7000_noecho () -{ - echo = !echo; - if (echo) - printf_filtered ("Snoop enabled\n"); - else - printf_filtered ("Snoop disabled\n"); +#define NITEMS 7 -} - -#define NITEMS 3 static int why_stop () { - static char *strings[NITEMS] = - { - "STEP NORMAL", - "BREAK POINT", - "BREAK KEY", - }; + static char *strings[NITEMS] = { + "STEP NORMAL", + "BREAK POINT", + "BREAK KEY", + "BREAK CONDI", + "CYCLE ACCESS", + "ILLEGAL INSTRUCTION", + "WRITE PROTECT", + }; char *p[NITEMS]; int c; - p[0] = strings[0]; - p[1] = strings[1]; - p[2] = strings[2]; + int i; + + for (i = 0; i < NITEMS; ++i) + p[i] = strings[i]; - c = gch(); + c = gch (); while (1) { - int i; for (i = 0; i < NITEMS; i++) { if (c == *(p[i])) @@ -1426,18 +1585,19 @@ why_stop () return i; } } - else { + else p[i] = strings[i]; - } } - c = gch(); + c = gch (); } } + /* Suck characters, if a string match, then return the strings index - otherwise echo them */ + otherwise echo them. */ + int -expect_n ( strings) +expect_n (strings) char **strings; { char *(ptr[10]); @@ -1447,120 +1607,132 @@ char **strings; char *buffer = saveaway; /* Count number of expect strings */ - for (n =0; strings[n]; n++) + for (n = 0; strings[n]; n++) { ptr[n] = strings[n]; } - while (1) { - int i; - int gotone = 0; + while (1) + { + int i; + int gotone = 0; - c = SERIAL_READCHAR (e7000_desc, 1); - if (c == SERIAL_TIMEOUT) { - printf_unfiltered ("[waiting for e7000...]\n"); - } + c = SERIAL_READCHAR (e7000_desc, 1); + if (c == SERIAL_TIMEOUT) + { + printf_unfiltered ("[waiting for e7000...]\n"); + } #ifdef __GO32__ - if (kbhit()) - { - int k = getkey(); - if (k == 1) - quit_flag = 1; - } -#endif - - if (quit_flag) - { - putchar_e7000 (CTRLC); /* interrupt the running program */ - quit_flag = 0; - } + if (kbhit ()) + { + int k = getkey(); - for (i = 0; i < n; i++) - { - if (c == ptr[i][0]) - { - ptr[i]++; - if (ptr[i][0] == 0) - { - /* Gone all the way */ - return i; - } - gotone = 1; - } - else - { - ptr[i] = strings[i]; - } - } + if (k == 1) + quit_flag = 1; + } +#endif + if (quit_flag) + { + putchar_e7000 (CTRLC); /* interrupt the running program */ + quit_flag = 0; + } + for (i = 0; i < n; i++) + { + if (c == ptr[i][0]) + { + ptr[i]++; + if (ptr[i][0] == 0) + { + /* Gone all the way */ + return i; + } + gotone = 1; + } + else + { + ptr[i] = strings[i]; + } + } - if (gotone) - { - /* Save it up incase we find that there was no match */ - *buffer ++ = c; - } - else - { - if (buffer != saveaway) - { - *buffer++ = 0; - printf(buffer); - buffer = saveaway; - } - if (c != SERIAL_TIMEOUT) { - putchar (c); - fflush(stdout); + if (gotone) + { + /* Save it up incase we find that there was no match */ + *buffer ++ = c; } - } - } + else + { + if (buffer != saveaway) + { + *buffer++ = 0; + printf ("%s", buffer); + buffer = saveaway; + } + if (c != SERIAL_TIMEOUT) + { + putchar (c); + fflush (stdout); + } + } + } } -/* We subtract two from the pc here rather than use DECR_PC_AFTER_BREAK - since the e7000 doesn't always add two to the pc, and the simulators never do. */ +/* We subtract two from the pc here rather than use + DECR_PC_AFTER_BREAK since the e7000 doesn't always add two to the + pc, and the simulators never do. */ static void -sub2_from_pc() +sub2_from_pc () { char buf[4]; + char buf2[200]; + store_signed_integer (buf, REGISTER_RAW_SIZE(PC_REGNUM), read_register (PC_REGNUM) -2); supply_register (PC_REGNUM, buf); - printf_e7000debug (".PC %x\r", read_register (PC_REGNUM)); + sprintf (buf2, ".PC %x\r", read_register (PC_REGNUM)); + puts_e7000debug (buf2); } + #define WAS_SLEEP 0 #define WAS_INT 1 #define WAS_RUNNING 2 #define WAS_OTHER 3 -static char *estrings[] = { "** SLEEP", "BREAK !", "** PC", "PC", 0}; -/* Wait until the remote machine stops, then return, - storing status in STATUS just as `wait' would. */ +static char *estrings[] = { + "** SLEEP", + "BREAK !", + "** PC", + "PC", + NULL +}; + +/* Wait until the remote machine stops, then return, storing status in + STATUS just as `wait' would. */ static int e7000_wait (pid, status) int pid; - WAITTYPE *status; + struct target_waitstatus *status; { - int c; - int reset_pc; + int stop_reason; int regno; int running_count = 0; int had_sleep = 0; int loop = 1; - char *reg; - int time = 0; - WSETSTOP ((*status), 0); + /* Then echo chars until PC= string seen */ gch (); /* Drop cr */ gch (); /* and space */ + while (loop) { - switch (expect_n(estrings)) + switch (expect_n (estrings)) { case WAS_OTHER: /* how did this happen ? */ - loop =0; + loop = 0; break; case WAS_SLEEP: had_sleep = 1; @@ -1578,10 +1750,14 @@ e7000_wait (pid, status) running_count = 0; } break; + default: + /* error? */ + break; } } - /* Skip till the PC=*/ - expect("="); + + /* Skip till the PC= */ + expect ("="); fetch_regs_from_dump (gch, want_nopc); /* And supply the extra ones the simulator uses */ @@ -1591,36 +1767,56 @@ e7000_wait (pid, status) supply_register (regno, (char *) &buf); } - reset_pc = why_stop (); + stop_reason = why_stop (); expect_full_prompt (); - switch (reset_pc) + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TRAP; + + switch (stop_reason) { case 1: /* Breakpoint */ - - WSETSTOP ((*status), SIGTRAP); + status->value.sig = TARGET_SIGNAL_TRAP; break; - case 0: - /* Single step */ - WSETSTOP ((*status), SIGTRAP); + case 0: /* Single step */ + status->value.sig = TARGET_SIGNAL_TRAP; break; - case 2: - /* Interrupt */ + case 2: /* Interrupt */ if (had_sleep) { - sub2_from_pc(); - WSETSTOP ((*status), SIGTRAP); + status->value.sig = TARGET_SIGNAL_TRAP; + sub2_from_pc (); } else { - WSETSTOP ((*status), SIGINT); + status->value.sig = TARGET_SIGNAL_INT; } break; + case 3: + break; + case 4: + printf_unfiltered ("a cycle address error?\n"); + status->value.sig = TARGET_SIGNAL_UNKNOWN; + break; + case 5: + status->value.sig = TARGET_SIGNAL_ILL; + break; + case 6: + status->value.sig = TARGET_SIGNAL_SEGV; + break; + case 7: /* Anything else (NITEMS + 1) */ + printf_unfiltered ("a write protect error?\n"); + status->value.sig = TARGET_SIGNAL_UNKNOWN; + break; + default: + /* Get the user's attention - this should never happen. */ + abort (); } + return 0; } -/* Define the target subroutine names */ +/* Define the target subroutine names. */ struct target_ops e7000_ops = { @@ -1633,40 +1829,47 @@ the speed to connect at in bits per second.\n\ eg\n\ target e7000 /dev/ttya 9600\n\ target e7000 foobar", - e7000_open, - e7000_close, - 0, - e7000_detach, - e7000_resume, - e7000_wait, - e7000_fetch_register, - e7000_store_register, - e7000_prepare_to_store, - e7000_xfer_inferior_memory, - e7000_files_info, -0,0,/* e7000_insert_breakpoint, - e7000_remove_breakpoint, /* Breakpoints */ - 0, - 0, - 0, - 0, - 0, /* Terminal handling */ - e7000_kill, - e7000_load, /* load */ - 0, /* lookup_symbol */ - e7000_create_inferior, - e7000_mourn_inferior, - 0, /* can_run */ - 0, /* notice_signals */ - process_stratum, - 0, /* next */ - 1, - 1, - 1, - 1, - 1, /* all mem, mem, stack, regs, exec */ - 0, - 0, /* Section pointers */ + e7000_open, /* to_open */ + e7000_close, /* to_close */ + 0, /* to_attach */ + e7000_detach, /* to_detach */ + e7000_resume, /* to_resume */ + e7000_wait, /* to_wait */ + e7000_fetch_register, /* to_fetch_registers */ + e7000_store_register, /* to_store_registers */ + e7000_prepare_to_store, /* to_prepare_to_store */ + e7000_xfer_inferior_memory, /* to_xfer_memory */ + e7000_files_info, /* to_files_info */ +#ifdef HARD_BREAKPOINTS + e7000_insert_breakpoint, /* to_insert_breakpoint */ + e7000_remove_breakpoint, /* to_remove_breakpoint */ +#else + memory_insert_breakpoint, /* to_insert_breakpoint */ + memory_remove_breakpoint, /* to_remove_breakpoint */ +#endif + 0, /* to_terminal_init */ + 0, /* to_terminal_inferior */ + 0, /* to_terminal_ours_for_output */ + 0, /* to_terminal_ours */ + 0, /* to_terminal_info */ + e7000_kill, /* to_kill */ + e7000_load, /* to_load */ + 0, /* to_lookup_symbol */ + e7000_create_inferior, /* to_create_inferior */ + e7000_mourn_inferior, /* to_mourn_inferior */ + 0, /* to_can_run */ + 0, /* to_notice_signals */ + 0, /* to_thread_alive */ + 0, /* to_stop */ + process_stratum, /* to_stratum */ + 0, /* next (unused) */ + 1, /* to_has_all_memory */ + 1, /* to_has_memory */ + 1, /* to_has_stack */ + 1, /* to_has_registers */ + 1, /* to_has_execution */ + 0, /* to_sections */ + 0, /* to_sections_end */ OPS_MAGIC, /* Always the last thing */ }; @@ -1674,16 +1877,16 @@ void _initialize_remote_e7000 () { add_target (&e7000_ops); + add_com ("e7000 <command>", class_obscure, e7000_command, "Send a command to the e7000 monitor."); - add_com ("ftplogin <machine> <name> <passwd> <dir>", class_obscure, e7000_login, + add_com ("ftplogin <machine> <name> <passwd> <dir>", class_obscure, e7000_login_command, "Login to machine and change to directory."); - add_com ("ftpload <file>", class_obscure, e7000_ftp, + add_com ("ftpload <file>", class_obscure, e7000_ftp_command, "Fetch and load a file from previously described place."); - add_com ("drain", class_obscure, e7000_drain, + add_com ("drain", class_obscure, e7000_drain_command, "Drain pending e7000 text buffers."); - add_com ("snoop", class_obscure, e7000_noecho, "Toggle monitor echo."); } |