-/* Remote debugging interface for Hitachi E7000 ICE, for GDB.
- Copyright 1993 Free Software Foundation, Inc.
- Contributed by Cygnus Support. Written by Steve Chamberlain for Cygnus.
+/* Remote debugging interface for Hitachi E7000 ICE, for GDB
+ Copyright 1993, 1994, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+ Written by Steve Chamberlain for Cygnus Support.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, 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 "gdbarch.h"
+#include "inferior.h"
#include "target.h"
-#include "wait.h"
-#include <varargs.h>
+#include "gdb_wait.h"
+#include "value.h"
+#include "command.h"
#include <signal.h>
-#include <string.h>
+#include "gdb_string.h"
+#include "gdbcmd.h"
#include <sys/types.h>
#include "serial.h"
+#include "remote-utils.h"
+#include "symfile.h"
+#include <time.h>
+#include <ctype.h>
-/* 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 */
+#if 1
+#define HARD_BREAKPOINTS /* Now handled by set option. */
+#define BC_BREAKPOINTS use_hard_breakpoints
+#endif
-extern struct target_ops e7000_ops; /* Forward declaration */
#define CTRLC 0x03
#define ENQ 0x05
#define ACK 0x06
#define CTRLZ 0x1a
-char *ENQSTRING = "\005";
+/* This file is used by 2 different targets, sh-elf and h8300. The
+ h8300 is not multiarched and doesn't use the registers defined in
+ tm-sh.h. To avoid using a macro GDB_TARGET_IS_SH, we do runtime check
+ of the target, which requires that these namse below are always
+ defined also in the h8300 case. */
+
+#if !defined (PR_REGNUM)
+#define PR_REGNUM -1
+#endif
+#if !defined (GBR_REGNUM)
+#define GBR_REGNUM -1
+#endif
+#if !defined (VBR_REGNUM)
+#define VBR_REGNUM -1
+#endif
+#if !defined (MACH_REGNUM)
+#define MACH_REGNUM -1
+#endif
+#if !defined (MACL_REGNUM)
+#define MACL_REGNUM -1
+#endif
+#if !defined (SR_REGNUM)
+#define SR_REGNUM -1
+#endif
+
+extern void notice_quit (void);
+
+extern void report_transfer_performance (unsigned long, time_t, time_t);
+
+extern char *sh_processor_type;
+
+/* Local function declarations. */
+
+static void e7000_close (int);
+
+static void e7000_fetch_register (int);
-int echo;
-static int echo_index;
-static void e7000_close ();
-static void e7000_fetch_register ();
-static void e7000_store_register ();
+static void e7000_store_register (int);
-static int timeout = 5;
+static void e7000_command (char *, int);
+
+static void e7000_login_command (char *, int);
+
+static void e7000_ftp_command (char *, int);
+
+static void e7000_drain_command (char *, int);
+
+static void expect (char *);
+
+static void expect_full_prompt (void);
+
+static void expect_prompt (void);
+
+static int e7000_parse_device (char *args, char *dev_name, int baudrate);
+/* Variables. */
-static void expect PARAMS ((char *));
-static void expect_full_prompt PARAMS (());
-static void expect_prompt PARAMS (());
static serial_t e7000_desc;
+/* Allow user to chose between using hardware breakpoints or memory. */
+static int use_hard_breakpoints = 0; /* use sw breakpoints by default */
+
+/* Nonzero if using the tcp serial driver. */
-/* Send data to e7000debug. Works just like printf. */
+static int using_tcp; /* direct tcp connection to target */
+static int using_tcp_remote; /* indirect connection to target
+ via tcp to controller */
+
+/* Nonzero if using the pc isa card. */
+
+static int using_pc;
+
+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 = 20;
+
+/* Send data to e7000debug. */
static void
-printf_e7000debug (va_alist)
- va_dcl
+puts_e7000debug (char *buf)
{
- va_list args;
- char *pattern;
- char buf[200];
-
- va_start (args);
+ if (!e7000_desc)
+ error ("Use \"target e7000 ...\" first.");
- pattern = va_arg (args, char *);
+ if (remote_debug)
+ printf_unfiltered ("Sending %s\n", buf);
- vsprintf (buf, pattern, args);
if (SERIAL_WRITE (e7000_desc, buf, strlen (buf)))
- fprintf (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
+ fprintf_unfiltered (gdb_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)
+putchar_e7000 (int x)
{
char b[1];
+
b[0] = x;
SERIAL_WRITE (e7000_desc, b, 1);
}
static void
-write_e7000 (s)
- char *s;
+write_e7000 (char *s)
{
SERIAL_WRITE (e7000_desc, s, strlen (s));
}
+static int
+normal (int x)
+{
+ if (x == '\n')
+ return '\r';
+ return x;
+}
+
/* Read a character from the remote system, doing all the fancy timeout
- stuff. */
+ stuff. Handles serial errors and EOF. If TIMEOUT == 0, and no chars,
+ returns -1, else returns next char. Discards chars > 127. */
static int
-readchar (timeout)
- int timeout;
+readchar (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;
+ else if (c < 0)
+ error ("Serial communication error");
+
+ if (remote_debug)
+ {
+ putchar_unfiltered (c);
+ gdb_flush (gdb_stdout);
+ }
+
+ return normal (c);
+}
+
+#if 0
+char *
+tl (int 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;
+expect (char *string)
{
char *p = string;
int c;
+ int nl = 0;
- immediate_quit = 1;
while (1)
-
{
c = readchar (timeout);
- if (c == SERIAL_ERROR)
+#if 0
+ notice_quit ();
+ if (quit_flag == 1)
{
- error ("Serial communication error");
+ if (ctrl_c)
+ {
+ putchar_e7000 (CTRLC);
+ --ctrl_c;
+ }
+ else
+ {
+ quit ();
+ }
}
- if (echo_index)
+#endif
+
+ if (echo)
{
- if (c != '\r')
- putchar (c);
- fflush (stdout);
+ if (c == '\r' || c == '\n')
+ {
+ if (!nl)
+ putchar_unfiltered ('\n');
+ nl = 1;
+ }
+ else
+ {
+ nl = 0;
+ putchar_unfiltered (c);
+ }
+ gdb_flush (gdb_stdout);
}
- if (c == *p++)
+ if (normal (c) == normal (*p++))
{
if (*p == '\0')
- {
- immediate_quit = 0;
- return;
- }
+ return;
}
else
{
p = string;
+
+ if (normal (c) == normal (string[0]))
+ p++;
}
}
}
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_prompt (void)
{
-#if defined (LOG_FILE)
- /* This is a convenient place to do this. The idea is to do it often
- enough that we never lose much data if we terminate abnormally. */
- fflush (log_file);
-#endif
expect (":");
}
+
static void
-expect_full_prompt ()
+expect_full_prompt (void)
{
-#if defined (LOG_FILE)
- /* This is a convenient place to do this. The idea is to do it often
- enough that we never lose much data if we terminate abnormally. */
- fflush (log_file);
-#endif
- expect ("\n:");
+ expect ("\r:");
}
static int
-get_hex_digit (ch)
+convert_hex_digit (int ch)
{
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
return -1;
-
}
-
-
static int
-get_hex (start)
- int *start;
+get_hex (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;
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)
- int n;
- int regno;
+get_hex_regs (int n, int regno)
{
long val;
int i;
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;
- char *args;
- char **env;
+e7000_create_inferior (char *execfile, char *args, char **env)
{
int entry_pt;
error ("Can't pass arguments to remote E7000DEBUG process");
if (execfile == 0 || exec_bfd == 0)
- error ("No exec file specified");
+ error ("No executable file specified");
entry_pt = (int) bfd_get_start_address (exec_bfd);
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];
static char *dir = "";
/* Grab the next token and buy some space for it */
+
static char *
-next (ptr)
- char **ptr;
+next (char **ptr)
{
char *p = *ptr;
char *s;
char *r;
int l = 0;
+
while (*p && *p == ' ')
- {
- p++;
- }
+ p++;
s = p;
while (*p && (*p != ' ' && *p != '\t'))
{
return r;
}
-static
-e7000_login (args, from_tty)
- char *args;
- int from_tty;
+static void
+e7000_login_command (char *args, int from_tty)
{
if (args)
{
dir = next (&args);
if (from_tty)
{
- printf ("Set info to %s %s %s %s\n", machine, user, passwd, dir);
+ printf_unfiltered ("Set info to %s %s %s %s\n", machine, user, passwd, dir);
}
}
else
/* Start an ftp transfer from the E7000 to a host */
-static
-e7000_ftp (args, from_tty)
- char *args;
- int from_tty;
+static void
+e7000_ftp_command (char *args, int from_tty)
{
+ /* FIXME: arbitrary limit on machine names and such. */
+ char buf[200];
+
int oldtimeout = timeout;
- timeout = 10;
- echo_index++;
- printf_e7000debug ("ftp %s\r", machine);
+ timeout = remote_timeout;
+
+ 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 (":");
- echo_index--;
timeout = oldtimeout;
}
-static void
-e7000_open (args, from_tty)
- char *args;
- int from_tty;
+static int
+e7000_parse_device (char *args, char *dev_name, int baudrate)
{
- int n;
- 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)
+ char junk[128];
+ int n = 0;
+ if (args && strcasecmp (args, "pc") == 0)
{
- /* Default to normal telnet port */
- strcat (dev_name, ":23");
+ strcpy (dev_name, args);
+ using_pc = 1;
}
+ else
+ {
+ /* FIXME! temp hack to allow use with port master -
+ target tcp_remote <device> */
+ if (args && strncmp (args, "tcp", 10) == 0)
+ {
+ char com_type[128];
+ n = sscanf (args, " %s %s %d %s", com_type, dev_name, &baudrate, junk);
+ using_tcp_remote = 1;
+ n--;
+ }
+ else if (args)
+ {
+ n = sscanf (args, " %s %d %s", dev_name, &baudrate, junk);
+ }
- push_target (&e7000_ops);
- e7000_desc = SERIAL_OPEN (dev_name);
+ 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 tcp_remote <host>[:<port>]\n\
+or \t\ttarget e7000 pc\n");
+ }
+#if !defined(__GO32__) && !defined(_WIN32)
+ /* FIXME! test for ':' is ambiguous */
+ if (n == 1 && strchr (dev_name, ':') == 0)
+ {
+ /* Default to normal telnet port */
+ /* serial_open will use this to determine tcp communication */
+ strcat (dev_name, ":23");
+ }
+#endif
+ if (!using_tcp_remote && strchr (dev_name, ':'))
+ using_tcp = 1;
+ }
- if (!e7000_desc)
- perror_with_name (dev_name);
+ return n;
+}
- using_tcp = strcmp (e7000_desc->ops->name, "tcp") == 0;
+/* Stub for catch_errors. */
- SERIAL_SETBAUDRATE (e7000_desc, baudrate);
- SERIAL_RAW (e7000_desc);
+static int
+e7000_start_remote (void *dummy)
+{
+ int loop;
+ int sync;
+ int try;
+ int quit_trying;
+
+ immediate_quit++; /* Allow user to interrupt it */
/* Hello? Are you there? */
sync = 0;
- while (!sync)
+ loop = 0;
+ try = 0;
+ quit_trying = 20;
+ putchar_e7000 (CTRLC);
+ while (!sync && ++try <= quit_trying)
{
int c;
- if (from_tty)
- printf_unfiltered ("[waiting for e7000...]\n");
- write_e7000 ("\r\n");
- c = SERIAL_READCHAR (e7000_desc, 3);
- while (c != SERIAL_TIMEOUT)
+
+ printf_unfiltered ("[waiting for e7000...]\n");
+
+ write_e7000 ("\r");
+ c = readchar (1);
+
+ /* FIXME! this didn't seem right-> while (c != SERIAL_TIMEOUT)
+ * we get stuck in this loop ...
+ * We may never timeout, and never sync up :-(
+ */
+ while (!sync && c != -1)
{
/* Dont echo cr's */
- if (from_tty && c != '\r')
+ if (c != '\r')
{
- putchar (c);
- fflush (stdout);
+ putchar_unfiltered (c);
+ gdb_flush (gdb_stdout);
}
+ /* Shouldn't we either break here, or check for sync in inner loop? */
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;
+ /* Was-> quit_flag = 0; */
+ c = -1;
+ quit_trying = try + 1; /* we don't want to try anymore */
+ }
+ else
+ {
+ c = readchar (1);
}
}
}
- printf_e7000debug ("\r\n");
+
+ if (!sync)
+ {
+ fprintf_unfiltered (gdb_stderr, "Giving up after %d tries...\n", try);
+ error ("Unable to synchronize with target.\n");
+ }
+
+ puts_e7000debug ("\r");
+ expect_prompt ();
+ puts_e7000debug ("b -\r"); /* Clear breakpoints */
expect_prompt ();
- if (from_tty)
- printf_filtered ("Remote %s connected to %s\n", target_shortname,
- dev_name);
+ immediate_quit--;
+
+/* This is really the job of start_remote however, that makes an assumption
+ that the target is about to print out a status message of some sort. That
+ doesn't happen here. */
+
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc ();
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, -1, 1);
+
+ return 1;
+}
+
+static void
+e7000_open (char *args, int from_tty)
+{
+ int n;
+
+ target_preopen (from_tty);
+ n = e7000_parse_device (args, dev_name, baudrate);
+
+ push_target (&e7000_ops);
+
+ e7000_desc = SERIAL_OPEN (dev_name);
+
+ if (!e7000_desc)
+ perror_with_name (dev_name);
+
+ SERIAL_SETBAUDRATE (e7000_desc, baudrate);
+ SERIAL_RAW (e7000_desc);
+
+#ifdef GDB_TARGET_IS_H8300
+ h8300hmode = 1;
+#endif
+
+ /* Start the remote connection; if error (0), discard this target.
+ In particular, if the user quits, be sure to discard it
+ (we'd be in an inconsistent state otherwise). */
+ if (!catch_errors (e7000_start_remote, (char *) 0,
+ "Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
+ if (from_tty)
+ printf_filtered ("Remote target %s connected to %s\n", target_shortname,
+ dev_name);
}
/* Close out all files and local state before this target loses control. */
static void
-e7000_close (quitting)
- int quitting;
+e7000_close (int quitting)
{
if (e7000_desc)
{
}
}
-/* 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;
+e7000_detach (char *arg, int from_tty)
{
pop_target (); /* calls e7000_close to do the real work */
if (from_tty)
- printf ("Ending remote %s debugging\n", target_shortname);
+ printf_unfiltered ("Ending remote %s debugging\n", target_shortname);
}
/* Tell the remote machine to resume. */
static void
-e7000_resume (pid, step, sig)
- int pid, step, sig;
+e7000_resume (int pid, int step, enum target_signal sigal)
{
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.
- A reg dump looks like:
+ 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
*/
-#ifdef GDB_TARGET_IS_H8300
-char *want = "\n\
- PC=%p CCR=%c\n\
+char *want_h8300h = "PC=%p CCR=%c\n\
ER0 - ER3 %0 %1 %2 %3\n\
- ER4 - ER7 %4 %5 %6 %7\n\
-:";
+ ER4 - ER7 %4 %5 %6 %7\n";
-#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_nopc_h8300h = "%p CCR=%c\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7";
+
+char *want_h8300s = "PC=%p CCR=%c\n\
+ MACH=\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7\n";
-char *want_nopc = "%16 SR=%22\n\
+char *want_nopc_h8300s = "%p CCR=%c EXR=%9\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7";
+
+char *want_sh = "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_sh = "%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";
+char *want_sh3 = "PC=%16 SR=%22\n\
+PR=%17 GBR=%18 VBR=%19\n\
+MACH=%20 MACL=%21 SSR=%23 SPC=%24\n\
+R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\
+R8-15 %8 %9 %10 %11 %12 %13 %14 %15\n\
+R0_BANK0-R3_BANK0 %25 %26 %27 %28\n\
+R4_BANK0-R7_BANK0 %29 %30 %31 %32\n\
+R0_BANK1-R3_BANK1 %33 %34 %35 %36\n\
+R4_BANK1-R7_BANK1 %37 %38 %39 %40";
+
+char *want_nopc_sh3 = "%16 SR=%22\n\
+ PR=%17 GBR=%18 VBR=%19\n\
+ MACH=%20 MACL=%21 SSR=%22 SPC=%23\n\
+ R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\
+ R8-15 %8 %9 %10 %11 %12 %13 %14 %15\n\
+ R0_BANK0-R3_BANK0 %25 %26 %27 %28\n\
+ R4_BANK0-R7_BANK0 %29 %30 %31 %32\n\
+ R0_BANK1-R3_BANK1 %33 %34 %35 %36\n\
+ R4_BANK1-R7_BANK1 %37 %38 %39 %40";
-#endif
-
-static
-int
-gch ()
+static int
+gch (void)
{
- int c = readchar (timeout);
- if (echo)
- {
- if (c >= ' ')
- printf ("%c", c);
- else if (c == '\n')
- printf ("\n", c);
- }
- return c;
+ return readchar (timeout);
}
-
-static
-unsigned int
-gbyte ()
+static unsigned int
+gbyte (void)
{
- 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;
}
void
-fetch_regs_from_dump (nextchar, want)
- int (*nextchar)();
- char *want;
+fetch_regs_from_dump (int (*nextchar) (), char *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 = nextchar();
+ while (thischar == ' '
+ || thischar == '\t'
+ || thischar == '\r'
+ || thischar == '\n')
+ thischar = nextchar ();
want++;
break;
-
+
default:
if (*want == thischar)
{
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");
- }
-
+ else
+ {
+ error ("out of sync in fetch registers wanted <%s>, got <%c 0x%x>",
+ want, thischar, thischar);
+ }
+
break;
case '%':
/* Got a register command */
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
+ else
{
regno = want[0] - '0';
want++;
}
}
-
+
else
- abort();
+ abort ();
}
store_signed_integer (buf,
- REGISTER_RAW_SIZE(regno),
- (LONGEST)get_hex(&thischar, nextchar));
+ REGISTER_RAW_SIZE (regno),
+ (LONGEST) get_hex (&thischar));
supply_register (regno, buf);
break;
}
}
static void
-e7000_fetch_registers ()
+e7000_fetch_registers (void)
{
int regno;
+ char *wanted;
+
+ puts_e7000debug ("R\r");
+
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_sh)
+ {
+ wanted = want_sh;
+ switch (TARGET_ARCHITECTURE->mach)
+ {
+ case bfd_mach_sh3:
+ case bfd_mach_sh3e:
+ case bfd_mach_sh4:
+ wanted = want_sh3;
+ }
+ }
+#ifdef GDB_TARGET_IS_H8300
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_h8300)
+ {
+ if (h8300smode)
+ wanted = want_h8300s;
+ else
+ wanted = want_h8300h;
+ }
+#endif
- printf_e7000debug ("R\r");
- fetch_regs_from_dump (gch, want);
+ fetch_regs_from_dump (gch, wanted);
/* 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
-e7000_fetch_register (regno)
- int regno;
+static void
+e7000_fetch_register (int regno)
{
e7000_fetch_registers ();
}
/* Store the remote registers from the contents of the block REGS. */
static void
-e7000_store_registers ()
+e7000_store_registers (void)
{
int regno;
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;
+e7000_store_register (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));
- }
- else if (regno == PC_REGNUM)
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_h8300)
{
- printf_e7000debug (".PC %x\r",
- read_register (regno));
+ if (regno <= 7)
+ {
+ sprintf (buf, ".ER%d %lx\r", regno, read_register (regno));
+ puts_e7000debug (buf);
+ }
+ else if (regno == PC_REGNUM)
+ {
+ sprintf (buf, ".PC %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
+#ifdef CCR_REGNUM
+ else if (regno == CCR_REGNUM)
+ {
+ sprintf (buf, ".CCR %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
+#endif
}
- else if (regno == CCR_REGNUM)
- {
- printf_e7000debug (".CCR %x\r",
- read_register (regno));
- }
-#endif
-#ifdef GDB_TARGET_IS_SH
- switch (regno)
+ else if (TARGET_ARCHITECTURE->arch == bfd_arch_sh)
{
- default:
- printf_e7000debug (".R%d %x\r", regno,
- read_register (regno));
+ if (regno == PC_REGNUM)
+ {
+ sprintf (buf, ".PC %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
- break;
- case PC_REGNUM:
- printf_e7000debug (".PC %x\r",
- read_register (regno));
- break;
- case SR_REGNUM:
- printf_e7000debug (".SR %x\r",
- read_register (regno));
- break;
+ else if (regno == SR_REGNUM)
+ {
+ sprintf (buf, ".SR %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
- case PR_REGNUM:
- printf_e7000debug (".PR %x\r",
- read_register (regno));
- break;
+ else if (regno == PR_REGNUM)
+ {
+ sprintf (buf, ".PR %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
- case GBR_REGNUM:
- printf_e7000debug (".GBR %x\r",
- read_register (regno));
- break;
+ else if (regno == GBR_REGNUM)
+ {
+ sprintf (buf, ".GBR %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
- case VBR_REGNUM:
- printf_e7000debug (".VBR %x\r",
- read_register (regno));
- break;
+ else if (regno == VBR_REGNUM)
+ {
+ sprintf (buf, ".VBR %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
- case MACH_REGNUM:
- printf_e7000debug (".MACH %x\r",
- read_register (regno));
- break;
+ else if (regno == MACH_REGNUM)
+ {
+ sprintf (buf, ".MACH %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
- case MACL_REGNUM:
- printf_e7000debug (".MACL %x\r",
- read_register (regno));
- break;
+ else if (regno == MACL_REGNUM)
+ {
+ sprintf (buf, ".MACL %lx\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
+ else
+ {
+ sprintf (buf, ".R%d %lx\r", regno, read_register (regno));
+ puts_e7000debug (buf);
+ }
}
-#endif
expect_prompt ();
}
debugged. */
static void
-e7000_prepare_to_store ()
+e7000_prepare_to_store (void)
{
/* Do nothing, since we can store individual regs */
}
static void
-e7000_files_info ()
+e7000_files_info (struct target_ops *ops)
{
- printf ("\tAttached to %s at %d baud.\n",
- dev_name, baudrate);
+ printf_unfiltered ("\tAttached to %s at %d baud.\n", dev_name, baudrate);
}
-static
-int
-stickbyte (where, what)
- char *where;
- unsigned int what;
+static int
+stickbyte (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;
- unsigned char *myaddr;
- int len;
+write_small (CORE_ADDR memaddr, unsigned char *myaddr, 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 %lx %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 %lx %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
- il ;s:s\r ->
- <- il ;s:s\r
- <- ENQ
- ACK ->
- <- LO s\r
- Srecords...
- ^Z ->
- <- ENQ
- ACK ->
- <- :
+
+/* 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
+ ACK ->
+ <- LO s\r
+ Srecords...
+ ^Z ->
+ <- ENQ
+ ACK ->
+ <- :
*/
static int
-write_large (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- unsigned char *myaddr;
- int len;
+write_large (CORE_ADDR memaddr, unsigned char *myaddr, int len)
{
int i;
#define maxstride 128
int stride;
- printf_e7000debug ("il ;s:s\r");
+ puts_e7000debug ("IL ;S:FK\r");
expect (ENQSTRING);
putchar_e7000 (ACK);
- expect ("LO s\r");
+ expect ("LO FK\r");
for (i = 0; i < len; i += stride)
{
int check_sum;
int where = 0;
int alen;
+
stride = len - i;
if (stride > maxstride)
stride = maxstride;
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)
{
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;
+
SERIAL_WRITE (e7000_desc, compose, where);
- j = SERIAL_READCHAR (e7000_desc, 0);
- if (j == SERIAL_TIMEOUT)
+ j = readchar (0);
+ if (j == -1)
{
/* This is ok - nothing there */
}
}
else
{
- printf ("Whats this %d\n", j);
+ printf_unfiltered ("@%d}@", j);
+ while ((j = readchar (0)) > 0)
+ {
+ printf_unfiltered ("@{%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;
+e7000_write_inferior_memory (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.
- Done by requesting an srecord dump from the E7000.
- */
-
-
-
-/* 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 ?
-
+ Small transactions we send
+ m <addr>;l
+ and receive
+ 00000000 12345678 ?
*/
static int
-e7000_read_inferior_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- unsigned char *myaddr;
- int len;
+e7000_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int 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 %lx;l\r", memaddr);
+ puts_e7000debug (buf);
- for (count = 0; count < len; count += 4)
+ for (count = 0; count < len; count += 4)
{
/* Suck away the address */
- c = gch();
+ c = gch ();
while (c != ' ')
- c = gch();
- c = gch();
- if (c == '*')
+ c = gch ();
+ c = gch ();
+ if (c == '*')
{ /* Some kind of error */
- expect_prompt();
+ puts_e7000debug (".\r"); /* Some errors leave us in memory input mode */
+ expect_full_prompt ();
return -1;
}
while (c != ' ')
- c = gch();
+ c = gch ();
/* Now read in the data */
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
{
- int b = gbyte();
- if (count + i < len) {
- myaddr[count + i] = b;
- }
+ int b = gbyte ();
+ if (count + i < len)
+ {
+ myaddr[count + i] = b;
+ }
}
/* 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();
+ expect_prompt ();
+ return len;
}
-#if 0
-/*
- For large transfers we used to send
+/*
+ For large transfers we used to send
- d <addr> <endaddr>\r
- and receive
- <ADDR> < D A T A > < ASCII CODE >
- 000000 5F FD FD FF DF 7F DF FF 01 00 01 00 02 00 08 04 "_..............."
- 000010 FF D7 FF 7F D7 F1 7F FF 00 05 00 00 08 00 40 00 "..............@."
- 000020 7F FD FF F7 7F FF FF F7 00 00 00 00 00 00 00 00 "................"
+ d <addr> <endaddr>\r
- A cost in chars for each transaction of 80 + 5*n-bytes.
+ and receive
+ <ADDRESS> < D A T A > < ASCII CODE >
+ 00000000 5F FD FD FF DF 7F DF FF 01 00 01 00 02 00 08 04 "_..............."
+ 00000010 FF D7 FF 7F D7 F1 7F FF 00 05 00 00 08 00 40 00 "..............@."
+ 00000020 7F FD FF F7 7F FF FF F7 00 00 00 00 00 00 00 00 "................"
+ 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!
-*/
+ 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!
+ */
static int
-e7000_read_inferior_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- unsigned char *myaddr;
- int len;
+e7000_read_inferior_memory_large (CORE_ADDR memaddr, unsigned char *myaddr,
+ int len)
{
int count;
int c;
+ char buf[200];
/* Starting address of this pass. */
return 0;
}
- printf_e7000debug ("d %x %x\r", memaddr, memaddr + len - 1);
+ sprintf (buf, "d %lx %lx\r", memaddr, memaddr + len - 1);
+ puts_e7000debug (buf);
count = 0;
c = gch ();
- /* First skip the command */
- while (c == '\n')
+ /* skip down to the first ">" */
+ while (c != '>')
c = gch ();
-
- while (c == ' ')
- c = gch ();
- if (c == '*')
- {
- expect ("\r");
- return -1;
- }
-
- /* Skip the title line */
- while (c != '\n')
+ /* now skip to the end of that line */
+ while (c != '\r')
c = gch ();
c = gch ();
+
while (count < len)
{
- /* Skip the address */
+ /* get rid of any white space before the address */
while (c <= ' ')
c = gch ();
+ /* Skip the address */
get_hex (&c);
/* read in the bytes on the line */
myaddr[count++] = get_hex (&c);
}
}
-
- while (c != '\n')
+ /* throw out the rest of the line */
+ while (c != '\r')
c = gch ();
}
+ /* wait for the ":" prompt */
while (c != ':')
c = gch ();
return len;
}
+#if 0
+
static int
-fast_but_for_the_pause_e7000_read_inferior_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
+fast_but_for_the_pause_e7000_read_inferior_memory (CORE_ADDR memaddr,
+ char *myaddr, int len)
{
int loop;
int c;
+ char buf[200];
if (((memaddr - 1) + len) < memaddr)
{
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)
int length;
int addr;
int i;
+
c = gch ();
switch (c)
{
case '3':
{
int alen;
+
alen = type - '0' + 1;
addr = 0;
while (alen--)
}
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 =");
#endif
+/* Transfer LEN bytes between GDB address MYADDR and target address
+ MEMADDR. If WRITE is non-zero, transfer them to the target,
+ otherwise transfer them from the target. TARGET is unused.
+
+ Returns the number of bytes transferred. */
+
static int
-e7000_xfer_inferior_memory (memaddr, myaddr, len, write, target)
- CORE_ADDR memaddr;
- unsigned char *myaddr;
- int len;
- int write;
- struct target_ops *target; /* ignored */
+e7000_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr,
+ int len, int write,
+ struct mem_attrib *attrib ATTRIBUTE_UNUSED,
+ struct target_ops *target ATTRIBUTE_UNUSED)
{
if (write)
- {
- return e7000_write_inferior_memory( memaddr, myaddr, len);
- }
+ return e7000_write_inferior_memory (memaddr, myaddr, len);
+ else if (len < 16)
+ return e7000_read_inferior_memory (memaddr, myaddr, len);
else
- {
- return e7000_read_inferior_memory( memaddr, myaddr, len);
- }
+ return e7000_read_inferior_memory_large (memaddr, myaddr, len);
}
static void
-e7000_kill (args, from_tty)
- char *args;
- int from_tty;
+e7000_kill (void)
{
+}
+
+static void
+e7000_load (char *args, int from_tty)
+{
+ struct cleanup *old_chain;
+ asection *section;
+ bfd *pbfd;
+ bfd_vma entry;
+#define WRITESIZE 0x1000
+ char buf[2 + 4 + 4 + WRITESIZE]; /* `DT' + <addr> + <len> + <data> */
+ char *filename;
+ int quiet;
+ int nostart;
+ time_t start_time, end_time; /* Start and end times of download */
+ unsigned long data_count; /* Number of bytes transferred to memory */
+ int oldtimeout = timeout;
+
+ timeout = remote_timeout;
+
+
+ /* FIXME! change test to test for type of download */
+ if (!using_tcp)
+ {
+ generic_load (args, from_tty);
+ return;
+ }
+
+ /* for direct tcp connections, we can do a fast binary download */
+ buf[0] = 'D';
+ buf[1] = 'T';
+ quiet = 0;
+ nostart = 0;
+ filename = NULL;
+
+ while (*args != '\000')
+ {
+ char *arg;
+
+ while (isspace (*args))
+ args++;
+
+ arg = args;
+
+ while ((*args != '\000') && !isspace (*args))
+ args++;
+
+ if (*args != '\000')
+ *args++ = '\000';
+
+ if (*arg != '-')
+ filename = arg;
+ else if (strncmp (arg, "-quiet", strlen (arg)) == 0)
+ quiet = 1;
+ else if (strncmp (arg, "-nostart", strlen (arg)) == 0)
+ nostart = 1;
+ else
+ error ("unknown option `%s'", arg);
+ }
+
+ if (!filename)
+ filename = get_exec_file (1);
+
+ pbfd = bfd_openr (filename, gnutarget);
+ if (pbfd == NULL)
+ {
+ perror_with_name (filename);
+ return;
+ }
+ old_chain = make_cleanup_bfd_close (pbfd);
+
+ if (!bfd_check_format (pbfd, bfd_object))
+ error ("\"%s\" is not an object file: %s", filename,
+ bfd_errmsg (bfd_get_error ()));
+
+ start_time = time (NULL);
+ data_count = 0;
+
+ puts_e7000debug ("mw\r");
+
+ expect ("\nOK");
+
+ for (section = pbfd->sections; section; section = section->next)
+ {
+ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD)
+ {
+ bfd_vma section_address;
+ bfd_size_type section_size;
+ file_ptr fptr;
+
+ section_address = bfd_get_section_vma (pbfd, section);
+ section_size = bfd_get_section_size_before_reloc (section);
+
+ if (!quiet)
+ printf_filtered ("[Loading section %s at 0x%x (%ud bytes)]\n",
+ bfd_get_section_name (pbfd, section),
+ section_address,
+ section_size);
+
+ fptr = 0;
+
+ data_count += section_size;
+
+ while (section_size > 0)
+ {
+ int count;
+ static char inds[] = "|/-\\";
+ static int k = 0;
+
+ QUIT;
+
+ count = min (section_size, WRITESIZE);
+
+ buf[2] = section_address >> 24;
+ buf[3] = section_address >> 16;
+ buf[4] = section_address >> 8;
+ buf[5] = section_address;
+
+ buf[6] = count >> 24;
+ buf[7] = count >> 16;
+ buf[8] = count >> 8;
+ buf[9] = count;
+
+ bfd_get_section_contents (pbfd, section, buf + 10, fptr, count);
+
+ if (SERIAL_WRITE (e7000_desc, buf, count + 10))
+ fprintf_unfiltered (gdb_stderr,
+ "e7000_load: SERIAL_WRITE failed: %s\n",
+ safe_strerror (errno));
+
+ expect ("OK");
+
+ if (!quiet)
+ {
+ printf_unfiltered ("\r%c", inds[k++ % 4]);
+ gdb_flush (gdb_stdout);
+ }
+
+ section_address += count;
+ fptr += count;
+ section_size -= count;
+ }
+ }
+ }
+
+ write_e7000 ("ED");
+
+ expect_prompt ();
+
+ end_time = time (NULL);
+
+/* Finally, make the PC point at the start address */
+
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+/* This is necessary because many things were based on the PC at the time that
+ we attached to the monitor, which is no longer valid now that we have loaded
+ new code (and just changed the PC). Another way to do this might be to call
+ normal_stop, except that the stack may not be valid, and things would get
+ horribly confused... */
+
+ clear_symtab_users ();
+
+ if (!nostart)
+ {
+ entry = bfd_get_start_address (pbfd);
+
+ if (!quiet)
+ printf_unfiltered ("[Starting %s at 0x%x]\n", filename, entry);
+
+/* start_routine (entry); */
+ }
+
+ report_transfer_performance (data_count, start_time, end_time);
+
+ do_cleanups (old_chain);
+ timeout = oldtimeout;
}
/* Clean up when a program exits.
instructions. */
static void
-e7000_mourn_inferior ()
+e7000_mourn_inferior (void)
{
remove_breakpoints ();
unpush_target (&e7000_ops);
generic_mourn_inferior (); /* Do all the proper things now */
}
-#define MAX_E7000DEBUG_BREAKPOINTS 200
+#define MAX_BREAKPOINTS 200
+#ifdef HARD_BREAKPOINTS
+#define MAX_E7000DEBUG_BREAKPOINTS (BC_BREAKPOINTS ? 5 : MAX_BREAKPOINTS)
+#else
+#define MAX_E7000DEBUG_BREAKPOINTS MAX_BREAKPOINTS
+#endif
-extern int memory_breakpoint_size;
-static CORE_ADDR breakaddr[MAX_E7000DEBUG_BREAKPOINTS] =
+/* Since we can change to soft breakpoints dynamically, we must define
+ more than enough. Was breakaddr[MAX_E7000DEBUG_BREAKPOINTS]. */
+static CORE_ADDR breakaddr[MAX_BREAKPOINTS] =
{0};
static int
-e7000_insert_breakpoint (addr, shadow)
- CORE_ADDR addr;
- unsigned char *shadow;
+e7000_insert_breakpoint (CORE_ADDR addr, char *shadow)
{
int i;
- static char nop[2] =
- {0x20, 0x0b};
+ char buf[200];
+#if 0
+ static char nop[2] = NOP;
+#endif
for (i = 0; i <= MAX_E7000DEBUG_BREAKPOINTS; i++)
if (breakaddr[i] == 0)
{
breakaddr[i] = addr;
/* Save old contents, and insert a nop in the space */
+#ifdef HARD_BREAKPOINTS
+ if (BC_BREAKPOINTS)
+ {
+ sprintf (buf, "BC%d A=%lx\r", i + 1, addr);
+ puts_e7000debug (buf);
+ }
+ else
+ {
+ sprintf (buf, "B %lx\r", addr);
+ puts_e7000debug (buf);
+ }
+#else
+#if 0
e7000_read_inferior_memory (addr, shadow, 2);
e7000_write_inferior_memory (addr, nop, 2);
- printf_e7000debug ("B %x\r", addr);
+#endif
+
+ 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;
}
static int
-e7000_remove_breakpoint (addr, shadow)
- CORE_ADDR addr;
- unsigned char *shadow;
+e7000_remove_breakpoint (CORE_ADDR addr, 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 - %lx\r", addr);
+ puts_e7000debug (buf);
+ }
+ expect_prompt ();
+#else
+ sprintf (buf, "B - %lx\r", addr);
+ puts_e7000debug (buf);
expect_prompt ();
+
+#if 0
/* Replace the insn under the break */
e7000_write_inferior_memory (addr, shadow, 2);
+#endif
+#endif
+
return 0;
}
- fprintf (stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ warning ("Can't find breakpoint associated with 0x%lx\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;
+e7000_command (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_index++;
+
+ echo++;
+ ctrl_c = 2;
expect_full_prompt ();
- echo_index--;
+ echo--;
+ ctrl_c = 0;
printf_unfiltered ("\n");
-}
-static void
-e7000_load (args, fromtty)
- char *args;
- int fromtty;
-{
- load_target_image (args, fromtty);
+ /* Who knows what the command did... */
+ registers_changed ();
}
-static void
-e7000_drain (args, fromtty)
- char *args;
- int fromtty;
+static void
+e7000_drain_command (char *args, int fromtty)
{
int c;
- while ((c = SERIAL_READCHAR (e7000_desc, 2) != SERIAL_TIMEOUT))
+ puts_e7000debug ("end\r");
+ putchar_e7000 (CTRLC);
+
+ while ((c = readchar (1) != -1))
{
+ if (quit_flag)
+ {
+ putchar_e7000 (CTRLC);
+ quit_flag = 0;
+ }
if (c > ' ' && c < 127)
- printf ("%c", c & 0xff);
+ printf_unfiltered ("%c", c & 0xff);
else
- printf ("<%x>", c & 0xff);
+ printf_unfiltered ("<%x>", c & 0xff);
}
}
-e7000_noecho ()
-{
- echo = !echo;
-}
-
-/* Wait until the remote machine stops, then return,
- storing status in STATUS just as `wait' would. */
+#define NITEMS 7
static int
-e7000_wait (pid, status)
- int pid;
- WAITTYPE *status;
+why_stop (void)
{
+ static char *strings[NITEMS] =
+ {
+ "STEP NORMAL",
+ "BREAK POINT",
+ "BREAK KEY",
+ "BREAK CONDI",
+ "CYCLE ACCESS",
+ "ILLEGAL INSTRUCTION",
+ "WRITE PROTECT",
+ };
+ char *p[NITEMS];
int c;
- int regno;
- int loop = 1;
- int time = 0;
- WSETSTOP ((*status), 0);
- /* Then echo chars until PC= string seen */
- gch (); /* Drop cr */
- gch (); /* and space */
- while (loop)
+ int i;
+
+ for (i = 0; i < NITEMS; ++i)
+ p[i] = strings[i];
+
+ c = gch ();
+ while (1)
{
- c = SERIAL_READCHAR (e7000_desc, 1);
- if (c < 0)
+ for (i = 0; i < NITEMS; i++)
{
- time++;
- if (time == 5)
+ if (c == *(p[i]))
{
- printf_unfiltered ("[waiting for e7000..]\n");
- time = 0;
+ p[i]++;
+ if (*(p[i]) == 0)
+ {
+ /* found one of the choices */
+ return i;
+ }
}
+ else
+ p[i] = strings[i];
+ }
+
+ c = gch ();
+ }
+}
+
+/* Suck characters, if a string match, then return the strings index
+ otherwise echo them. */
+
+int
+expect_n (char **strings)
+{
+ char *(ptr[10]);
+ int n;
+ int c;
+ char saveaway[100];
+ char *buffer = saveaway;
+ /* Count number of expect strings */
+
+ for (n = 0; strings[n]; n++)
+ {
+ ptr[n] = strings[n];
+ }
+
+ while (1)
+ {
+ int i;
+ int gotone = 0;
+
+ c = readchar (1);
+ if (c == -1)
+ {
+ 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;
- putchar_e7000 (CTRLC); /* interrupt the running program */
}
- if (c == 'P')
+
+ for (i = 0; i < n; i++)
{
- c = SERIAL_READCHAR (e7000_desc, 1);
- if (c == 'C')
+ if (c == ptr[i][0])
{
- c = SERIAL_READCHAR (e7000_desc, 1);
- if (c == '=')
- {
- /* Got break */
- loop = 0;
- }
- else
+ ptr[i]++;
+ if (ptr[i][0] == 0)
{
- printf ("PC");
+ /* Gone all the way */
+ return i;
}
+ gotone = 1;
}
else
{
- printf ("P");
+ ptr[i] = strings[i];
}
}
+
+ if (gotone)
+ {
+ /* Save it up incase we find that there was no match */
+ *buffer++ = c;
+ }
else
{
- if (c > 0)
+ if (buffer != saveaway)
+ {
+ *buffer++ = 0;
+ printf_unfiltered ("%s", buffer);
+ buffer = saveaway;
+ }
+ if (c != -1)
{
- putchar (c);
- fflush (stdout);
+ putchar_unfiltered (c);
+ gdb_flush (gdb_stdout);
}
}
}
- fetch_regs_from_dump (gch, want_nopc);
+}
+
+/* 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 (void)
+{
+ 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);
+ sprintf (buf2, ".PC %lx\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",
+ NULL
+};
+
+/* Wait until the remote machine stops, then return, storing status in
+ STATUS just as `wait' would. */
+
+static int
+e7000_wait (int pid, struct target_waitstatus *status)
+{
+ int stop_reason;
+ int regno;
+ int running_count = 0;
+ int had_sleep = 0;
+ int loop = 1;
+ char *wanted_nopc;
+
+ /* Then echo chars until PC= string seen */
+ gch (); /* Drop cr */
+ gch (); /* and space */
+
+ while (loop)
+ {
+ switch (expect_n (estrings))
+ {
+ case WAS_OTHER:
+ /* how did this happen ? */
+ loop = 0;
+ break;
+ case WAS_SLEEP:
+ had_sleep = 1;
+ putchar_e7000 (CTRLC);
+ loop = 0;
+ break;
+ case WAS_INT:
+ loop = 0;
+ break;
+ case WAS_RUNNING:
+ running_count++;
+ if (running_count == 20)
+ {
+ printf_unfiltered ("[running...]\n");
+ running_count = 0;
+ }
+ break;
+ default:
+ /* error? */
+ break;
+ }
+ }
+
+ /* Skip till the PC= */
+ expect ("=");
+
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_sh)
+ {
+ wanted_nopc = want_nopc_sh;
+ switch (TARGET_ARCHITECTURE->mach)
+ {
+ case bfd_mach_sh3:
+ case bfd_mach_sh3e:
+ case bfd_mach_sh4:
+ wanted_nopc = want_nopc_sh3;
+ }
+ }
+#ifdef GDB_TARGET_IS_H8300
+ if (TARGET_ARCHITECTURE->arch == bfd_arch_h8300)
+ {
+ if (h8300smode)
+ wanted_nopc = want_nopc_h8300s;
+ else
+ wanted_nopc = want_nopc_h8300h;
+ }
+#endif
+ fetch_regs_from_dump (gch, wanted_nopc);
/* And supply the extra ones the simulator uses */
for (regno = NUM_REALREGS; regno < NUM_REGS; regno++)
supply_register (regno, (char *) &buf);
}
+ stop_reason = why_stop ();
expect_full_prompt ();
- WSETSTOP ((*status), SIGTRAP);
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ switch (stop_reason)
+ {
+ case 1: /* Breakpoint */
+ write_pc (read_pc ()); /* PC is always off by 2 for breakpoints */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 0: /* Single step */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 2: /* Interrupt */
+ if (had_sleep)
+ {
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ sub2_from_pc ();
+ }
+ else
+ {
+ 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 */
+/* Stop the running program. */
+
+static void
+e7000_stop (void)
+{
+ /* Sending a ^C is supposed to stop the running program. */
+ putchar_e7000 (CTRLC);
+}
+
+/* Define the target subroutine names. */
+
+struct target_ops e7000_ops;
-struct target_ops e7000_ops =
+static void
+init_e7000_ops (void)
{
- "e7000",
- "Remote Hitachi e7000 target",
- "Use a remote Hitachi e7000 ICE connected by a serial line,\n\
+ e7000_ops.to_shortname = "e7000";
+ e7000_ops.to_longname = "Remote Hitachi e7000 target";
+ e7000_ops.to_doc = "Use a remote Hitachi e7000 ICE connected by a serial line;\n\
or a network connection.\n\
Arguments are the name of the device for the serial line,\n\
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,
- 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 */
- OPS_MAGIC, /* Always the last thing */
+target e7000 foobar";
+ e7000_ops.to_open = e7000_open;
+ e7000_ops.to_close = e7000_close;
+ e7000_ops.to_attach = 0;
+ e7000_ops.to_post_attach = NULL;
+ e7000_ops.to_require_attach = NULL;
+ e7000_ops.to_detach = e7000_detach;
+ e7000_ops.to_require_detach = NULL;
+ e7000_ops.to_resume = e7000_resume;
+ e7000_ops.to_wait = e7000_wait;
+ e7000_ops.to_post_wait = NULL;
+ e7000_ops.to_fetch_registers = e7000_fetch_register;
+ e7000_ops.to_store_registers = e7000_store_register;
+ e7000_ops.to_prepare_to_store = e7000_prepare_to_store;
+ e7000_ops.to_xfer_memory = e7000_xfer_inferior_memory;
+ e7000_ops.to_files_info = e7000_files_info;
+ e7000_ops.to_insert_breakpoint = e7000_insert_breakpoint;
+ e7000_ops.to_remove_breakpoint = e7000_remove_breakpoint;
+ e7000_ops.to_terminal_init = 0;
+ e7000_ops.to_terminal_inferior = 0;
+ e7000_ops.to_terminal_ours_for_output = 0;
+ e7000_ops.to_terminal_ours = 0;
+ e7000_ops.to_terminal_info = 0;
+ e7000_ops.to_kill = e7000_kill;
+ e7000_ops.to_load = e7000_load;
+ e7000_ops.to_lookup_symbol = 0;
+ e7000_ops.to_create_inferior = e7000_create_inferior;
+ e7000_ops.to_post_startup_inferior = NULL;
+ e7000_ops.to_acknowledge_created_inferior = NULL;
+ e7000_ops.to_clone_and_follow_inferior = NULL;
+ e7000_ops.to_post_follow_inferior_by_clone = NULL;
+ e7000_ops.to_insert_fork_catchpoint = NULL;
+ e7000_ops.to_remove_fork_catchpoint = NULL;
+ e7000_ops.to_insert_vfork_catchpoint = NULL;
+ e7000_ops.to_remove_vfork_catchpoint = NULL;
+ e7000_ops.to_has_forked = NULL;
+ e7000_ops.to_has_vforked = NULL;
+ e7000_ops.to_can_follow_vfork_prior_to_exec = NULL;
+ e7000_ops.to_post_follow_vfork = NULL;
+ e7000_ops.to_insert_exec_catchpoint = NULL;
+ e7000_ops.to_remove_exec_catchpoint = NULL;
+ e7000_ops.to_has_execd = NULL;
+ e7000_ops.to_reported_exec_events_per_exec_call = NULL;
+ e7000_ops.to_has_exited = NULL;
+ e7000_ops.to_mourn_inferior = e7000_mourn_inferior;
+ e7000_ops.to_can_run = 0;
+ e7000_ops.to_notice_signals = 0;
+ e7000_ops.to_thread_alive = 0;
+ e7000_ops.to_stop = e7000_stop;
+ e7000_ops.to_pid_to_exec_file = NULL;
+ e7000_ops.to_core_file_to_sym_file = NULL;
+ e7000_ops.to_stratum = process_stratum;
+ e7000_ops.DONT_USE = 0;
+ e7000_ops.to_has_all_memory = 1;
+ e7000_ops.to_has_memory = 1;
+ e7000_ops.to_has_stack = 1;
+ e7000_ops.to_has_registers = 1;
+ e7000_ops.to_has_execution = 1;
+ e7000_ops.to_sections = 0;
+ e7000_ops.to_sections_end = 0;
+ e7000_ops.to_magic = OPS_MAGIC;
};
void
-_initialize_remote_e7000 ()
+_initialize_remote_e7000 (void)
{
+ init_e7000_ops ();
add_target (&e7000_ops);
- add_com ("e7000 <command>", class_obscure, e7000_command,
+
+ add_com ("e7000", 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", class_obscure, e7000_login_command,
"Login to machine and change to directory.");
- add_com ("ftpload <file>", class_obscure, e7000_ftp,
+ add_com ("ftpload", 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 ("echo", class_obscure, e7000_noecho, "Toggle monitor echo.");
+ add_show_from_set (add_set_cmd ("usehardbreakpoints", no_class,
+ var_integer, (char *) &use_hard_breakpoints,
+ "Set use of hardware breakpoints for all breakpoints.\n", &setlist),
+ &showlist);
}