diff options
Diffstat (limited to 'gdb/remote-e7000.c')
-rw-r--r-- | gdb/remote-e7000.c | 2258 |
1 files changed, 2258 insertions, 0 deletions
diff --git a/gdb/remote-e7000.c b/gdb/remote-e7000.c new file mode 100644 index 0000000..92e69b3 --- /dev/null +++ b/gdb/remote-e7000.c @@ -0,0 +1,2258 @@ +/* Remote debugging interface for Hitachi E7000 ICE, for GDB + Copyright 1993, 1994, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + + Written by Steve Chamberlain for Cygnus Support. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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., 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 "value.h" +#include "command.h" +#include <signal.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> + + +#if 1 +#define HARD_BREAKPOINTS /* Now handled by set option. */ +#define BC_BREAKPOINTS use_hard_breakpoints +#endif + +#define CTRLC 0x03 +#define ENQ 0x05 +#define ACK 0x06 +#define CTRLZ 0x1a + +extern void notice_quit PARAMS ((void)); + +extern void report_transfer_performance PARAMS ((unsigned long, + time_t, time_t)); + +extern char *sh_processor_type; + +/* Local function declarations. */ + +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 ((void)); + +static void expect_prompt PARAMS ((void)); + +static int e7000_parse_device PARAMS ((char *args, char *dev_name, + int baudrate)); +/* Variables. */ + +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. */ + +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 +puts_e7000debug (buf) + char *buf; +{ + if (!e7000_desc) + error ("Use \"target e7000 ...\" first."); + + if (remote_debug) + printf_unfiltered ("Sending %s\n", buf); + + if (SERIAL_WRITE (e7000_desc, buf, strlen (buf))) + fprintf_unfiltered (gdb_stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno)); + + /* 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); +} + +static void +write_e7000 (s) + char *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. 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; +{ + int c; + + do + { + c = SERIAL_READCHAR (e7000_desc, timeout); + } + while (c > 127); + + if (c == SERIAL_TIMEOUT) + { + if (timeout == 0) + return -1; + echo = 0; + error ("Timeout reading from remote system."); + } + 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 (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. */ + +static void +expect (string) + char *string; +{ + char *p = string; + int c; + int nl = 0; + + while (1) + { + c = readchar (timeout); +#if 0 + notice_quit (); + if (quit_flag == 1) + { + if (ctrl_c) + { + putchar_e7000(CTRLC); + --ctrl_c; + } + else + { + quit (); + } + } +#endif + + if (echo) + { + if (c == '\r' || c == '\n') + { + if (!nl) + putchar_unfiltered ('\n'); + nl = 1; + } + else + { + nl = 0; + putchar_unfiltered (c); + } + gdb_flush (gdb_stdout); + } + if (normal (c) == normal (*p++)) + { + if (*p == '\0') + return; + } + else + { + p = string; + + if (normal (c) == normal (string[0])) + p++; + } + } +} + +/* Keep discarding input until we see the e7000 prompt. + + The convention for dealing with the prompt is that you + 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. */ + +static void +expect_prompt () +{ + expect (":"); +} + +static void +expect_full_prompt () +{ + expect ("\r:"); +} + +static int +convert_hex_digit (ch) + int ch; +{ + if (ch >= '0' && ch <= '9') + return ch - '0'; + else if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + return -1; +} + +static int +get_hex (start) + int *start; +{ + int value = convert_hex_digit (*start); + int try; + + *start = readchar (timeout); + while ((try = convert_hex_digit (*start)) >= 0) + { + value <<= 4; + value += try; + *start = readchar (timeout); + } + return value; +} + +#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; +{ + long val; + int i; + + for (i = 0; i < n; i++) + { + int j; + + val = 0; + for (j = 0; j < 8; j++) + val = (val << 4) + get_hex_digit (j == 0); + 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; +{ + int entry_pt; + + if (args && *args) + error ("Can't pass arguments to remote E7000DEBUG process"); + + if (execfile == 0 || exec_bfd == 0) + error ("No executable file specified"); + + entry_pt = (int) bfd_get_start_address (exec_bfd); + +#ifdef CREATE_INFERIOR_HOOK + CREATE_INFERIOR_HOOK (0); /* No process-ID */ +#endif + + /* The "process" (board) is already stopped awaiting our commands, and + the program is already downloaded. We just set its PC and go. */ + + clear_proceed_status (); + + /* Tell wait_for_inferior that we've started a new process. */ + init_wait_for_inferior (); + + /* Set up the "saved terminal modes" of the inferior + based on what modes we are starting it with. */ + target_terminal_init (); + + /* Install inferior's terminal modes. */ + target_terminal_inferior (); + + /* insert_step_breakpoint (); FIXME, do we need this? */ + proceed ((CORE_ADDR) entry_pt, -1, 0); /* Let 'er rip... */ +} + +/* 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 *machine = ""; +static char *user = ""; +static char *passwd = ""; +static char *dir = ""; + +/* Grab the next token and buy some space for it */ + +static char * +next (ptr) + char **ptr; +{ + char *p = *ptr; + char *s; + char *r; + int l = 0; + + while (*p && *p == ' ') + p++; + s = p; + while (*p && (*p != ' ' && *p != '\t')) + { + l++; + p++; + } + r = xmalloc (l + 1); + memcpy (r, s, l); + r[l] = 0; + *ptr = p; + return r; +} + +static void +e7000_login_command (args, from_tty) + char *args; + int from_tty; +{ + if (args) + { + machine = next (&args); + user = next (&args); + passwd = next (&args); + dir = next (&args); + if (from_tty) + { + printf_unfiltered ("Set info to %s %s %s %s\n", machine, user, passwd, dir); + } + } + else + { + error ("Syntax is ftplogin <machine> <user> <passwd> <directory>"); + } +} + +/* Start an ftp transfer from the E7000 to a host */ + +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 = remote_timeout; + + sprintf (buf, "ftp %s\r", machine); + puts_e7000debug (buf); + expect (" Username : "); + sprintf (buf, "%s\r", user); + puts_e7000debug (buf); + expect (" Password : "); + write_e7000 (passwd); + write_e7000 ("\r"); + expect ("success\r"); + expect ("FTP>"); + sprintf (buf, "cd %s\r", dir); + puts_e7000debug (buf); + expect ("FTP>"); + sprintf (buf, "ll 0;s:%s\r", args); + puts_e7000debug (buf); + expect ("FTP>"); + puts_e7000debug ("bye\r"); + expect (":"); + timeout = oldtimeout; +} + +static int +e7000_parse_device (args, dev_name, baudrate) + char *args; + char *dev_name; + int baudrate; +{ + char junk[128]; + int n = 0; + if (args && strcasecmp (args, "pc") == 0) + { + 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); + } + + 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; + } + + return n; +} + +/* Stub for catch_errors. */ + +static int +e7000_start_remote (dummy) + char *dummy; +{ + int loop; + int sync; + int try; + int quit_trying; + + immediate_quit = 1; /* Allow user to interrupt it */ + + /* Hello? Are you there? */ + sync = 0; + loop = 0; + try = 0; + quit_trying = 20; + putchar_e7000 (CTRLC); + while (!sync && ++try <= quit_trying) + { + int c; + + 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 (c != '\r') + { + 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) + { + putchar_e7000 (CTRLC); + loop = 0; + } + + QUIT ; + + if (quit_flag) + { + putchar_e7000 (CTRLC); + /* Was-> quit_flag = 0; */ + c = -1; + quit_trying = try+1; /* we don't want to try anymore */ + } + else + { + c = readchar (1); + } + } + } + + if (!sync) + { + fprintf_unfiltered (gdb_stderr, "Giving up after %d tries...\n",try); + error ("Unable to syncronize with target.\n"); + } + + puts_e7000debug ("\r"); + expect_prompt (); + puts_e7000debug ("b -\r"); /* Clear breakpoints */ + expect_prompt (); + + immediate_quit = 0; + +/* 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 (args, from_tty) + 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; +{ + if (e7000_desc) + { + SERIAL_CLOSE (e7000_desc); + e7000_desc = 0; + } +} + +/* 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; +{ + pop_target (); /* calls e7000_close to do the real work */ + if (from_tty) + 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; +{ + if (step) + puts_e7000debug ("S\r"); + else + 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 + */ + +#ifdef GDB_TARGET_IS_H8300 + +char *want_h8300h = "PC=%p CCR=%c\n\ + ER0 - ER3 %0 %1 %2 %3\n\ + ER4 - ER7 %4 %5 %6 %7\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_h8300s = "%p CCR=%c EXR=%9\n\ + ER0 - ER3 %0 %1 %2 %3\n\ + ER4 - ER7 %4 %5 %6 %7"; + +#endif + +#ifdef GDB_TARGET_IS_SH + +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\ + 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_sh3_nopc = "%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 () +{ + return readchar (timeout); +} + +static unsigned int +gbyte () +{ + 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; +{ + int regno; + char buf[MAX_REGISTER_RAW_SIZE]; + + int thischar = nextchar (); + + while (*want) + { + switch (*want) + { + case '\n': + /* 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 (); + want++; + break; + + default: + if (*want == thischar) + { + want++; + if (*want) + thischar = nextchar (); + + } + else if (thischar == ' ' || thischar == '\n' || thischar == '\r') + { + thischar = nextchar (); + } + else { + error ("out of sync in fetch registers wanted <%s>, got <%c 0x%x>", + want, thischar, thischar); + } + + break; + case '%': + /* Got a register command */ + want++; + switch (*want) + { +#ifdef PC_REGNUM + case 'p': + regno = PC_REGNUM; + want++; + break; +#endif +#ifdef CCR_REGNUM + case 'c': + regno = CCR_REGNUM; + want++; + break; +#endif +#ifdef SP_REGNUM + case 's': + regno = SP_REGNUM; + want++; + break; +#endif +#ifdef FP_REGNUM + case 'f': + regno = FP_REGNUM; + want++; + break; +#endif + + default: + if (isdigit (want[0])) + { + if (isdigit (want[1])) + { + regno = (want[0] - '0') * 10 + want[1] - '0'; + want += 2; + } + else + { + regno = want[0] - '0'; + want++; + } + } + + else + abort (); + } + store_signed_integer (buf, + REGISTER_RAW_SIZE(regno), + (LONGEST) get_hex (&thischar, nextchar)); + supply_register (regno, buf); + break; + } + } +} + +static void +e7000_fetch_registers () +{ + int regno; + char *wanted; + + puts_e7000debug ("R\r"); + +#ifdef GDB_TARGET_IS_SH + wanted = want; + if (TARGET_ARCHITECTURE->arch == bfd_arch_sh) + switch (TARGET_ARCHITECTURE->mach) + { + case bfd_mach_sh3: + case bfd_mach_sh3e: + wanted = want_sh3; + } +#else + if (h8300smode) + wanted = want_h8300s; + else + wanted = want_h8300h; +#endif + 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. */ + +static void +e7000_fetch_register (regno) + int regno; +{ + e7000_fetch_registers (); +} + +/* Store the remote registers from the contents of the block REGS. */ + +static void +e7000_store_registers () +{ + int regno; + + for (regno = 0; regno < NUM_REALREGS; regno++) + e7000_store_register (regno); + + registers_changed (); +} + +/* 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) + { + sprintf (buf, ".ER%d %x\r", regno, read_register (regno)); + puts_e7000debug (buf); + } + else if (regno == PC_REGNUM) + { + sprintf (buf, ".PC %x\r", read_register (regno)); + puts_e7000debug (buf); + } + else if (regno == CCR_REGNUM) + { + sprintf (buf, ".CCR %x\r", read_register (regno)); + puts_e7000debug (buf); + } +#endif /* GDB_TARGET_IS_H8300 */ + +#ifdef GDB_TARGET_IS_SH + switch (regno) + { + default: + sprintf (buf, ".R%d %x\r", regno, read_register (regno)); + puts_e7000debug (buf); + break; + + case PC_REGNUM: + sprintf (buf, ".PC %x\r", read_register (regno)); + puts_e7000debug (buf); + break; + + case SR_REGNUM: + sprintf (buf, ".SR %x\r", read_register (regno)); + puts_e7000debug (buf); + break; + + case PR_REGNUM: + sprintf (buf, ".PR %x\r", read_register (regno)); + puts_e7000debug (buf); + break; + + case GBR_REGNUM: + sprintf (buf, ".GBR %x\r", read_register (regno)); + puts_e7000debug (buf); + break; + + case VBR_REGNUM: + sprintf (buf, ".VBR %x\r", read_register (regno)); + puts_e7000debug (buf); + break; + + case MACH_REGNUM: + sprintf (buf, ".MACH %x\r", read_register (regno)); + puts_e7000debug (buf); + break; + + case MACL_REGNUM: + sprintf (buf, ".MACL %x\r", read_register (regno)); + puts_e7000debug (buf); + break; + } + +#endif /* GDB_TARGET_IS_SH */ + + expect_prompt (); +} + +/* Get ready to modify the registers array. On machines which store + individual registers, this doesn't need to do anything. On machines + which store all the registers in one fell swoop, this makes sure + that registers contains all the registers from the program being + debugged. */ + +static void +e7000_prepare_to_store () +{ + /* Do nothing, since we can store individual regs */ +} + +static void +e7000_files_info () +{ + printf_unfiltered ("\tAttached to %s at %d baud.\n", dev_name, baudrate); +} + +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. */ + +static int +write_small (memaddr, myaddr, len) + 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)) + { + /* Can be done with a long word */ + 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 + { + 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 + + 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; +{ + int i; +#define maxstride 128 + int stride; + + 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]; + int address = i + memaddr; + int j; + 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; + else if (address >= 0xffff) + alen = 3; + else + alen = 2; + /* Insert type. */ + compose[where++] = alen - 1 + '0'; + /* Insert length. */ + check_sum += stickbyte (compose + where, alen + stride + 1); + where += 2; + while (alen > 0) + { + alen--; + check_sum += stickbyte (compose + where, address >> (8 * (alen))); + where += 2; + } + + for (j = 0; j < stride; j++) + { + 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 = readchar (0); + if (j == -1) + { + /* This is ok - nothing there */ + } + else if (j == ENQ) + { + /* Hmm, it's trying to tell us something */ + expect (":"); + error ("Error writing memory"); + } + else + { + 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. + + Can't use the Srecord load over ethernet, so don't 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 || using_pc) + return write_small (memaddr, myaddr, len); + else + 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 +e7000_read_inferior_memory (memaddr, myaddr, len) + 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; + } + + sprintf (buf, "m %x;l\r", memaddr); + puts_e7000debug (buf); + + for (count = 0; count < len; count += 4) + { + /* Suck away the address */ + c = gch (); + while (c != ' ') + c = gch (); + c = gch (); + if (c == '*') + { /* Some kind of error */ + puts_e7000debug (".\r"); /* Some errors leave us in memory input mode */ + expect_full_prompt(); + return -1; + } + while (c != ' ') + c = gch (); + + /* Now read in the data */ + for (i = 0; i < 4; i++) + { + 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 (); + if (count + 4 >= len) + puts_e7000debug(".\r"); + else + puts_e7000debug("\r"); + + } + expect_prompt(); + return len; +} + + + +/* + For large transfers we used to send + + + d <addr> <endaddr>\r + + 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! +*/ + +static int +e7000_read_inferior_memory_large (memaddr, myaddr, len) + CORE_ADDR memaddr; + unsigned char *myaddr; + int len; +{ + int count; + int c; + char buf[200]; + + /* Starting address of this pass. */ + + if (((memaddr - 1) + len) < memaddr) + { + errno = EIO; + return 0; + } + + sprintf (buf, "d %x %x\r", memaddr, memaddr + len - 1); + puts_e7000debug (buf); + + count = 0; + c = gch (); + + /* skip down to the first ">" */ + while( c != '>' ) + c = gch (); + /* now skip to the end of that line */ + while( c != '\r' ) + c = gch (); + c = gch (); + + while (count < len) + { + /* 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 */ + while (c != '"' && count < len) + { + if (c == ' ') + c = gch (); + else + { + myaddr[count++] = get_hex (&c); + } + } + /* 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; +{ + int loop; + int c; + char buf[200]; + + if (((memaddr - 1) + len) < memaddr) + { + errno = EIO; + return 0; + } + + sprintf (buf, "is %x@%x:s\r", memaddr, len); + puts_e7000debug (buf); + gch (); + c = gch (); + if (c != ENQ) + { + /* Got an error */ + error ("Memory read error"); + } + putchar_e7000 (ACK); + expect ("SV s"); + loop = 1; + while (loop) + { + int type; + int length; + int addr; + int i; + + c = gch (); + switch (c) + { + case ENQ: /* ENQ, at the end */ + loop = 0; + break; + case 'S': + /* Start of an Srecord */ + type = gch (); + length = gbyte (); + switch (type) + { + case '7': /* Termination record, ignore */ + case '0': + case '8': + case '9': + /* Header record - ignore it */ + while (length--) + { + gbyte (); + } + break; + case '1': + case '2': + case '3': + { + int alen; + + alen = type - '0' + 1; + addr = 0; + while (alen--) + { + addr = (addr << 8) + gbyte (); + length--; + } + + for (i = 0; i < length - 1; i++) + myaddr[i + addr - memaddr] = gbyte (); + + gbyte (); /* Ignore checksum */ + } + } + } + } + + putchar_e7000 (ACK); + expect ("TOP ADDRESS ="); + expect ("END ADDRESS ="); + expect (":"); + + return len; +} + +#endif + +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 */ +{ + if (write) + 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_large( memaddr, myaddr, len); +} + +static void +e7000_kill (args, from_tty) + char *args; + int from_tty; +{ +} + +static void +e7000_load (args, from_tty) + 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 ((make_cleanup_func) 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 (%d 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. + + The program actually lives on in the remote processor's RAM, and may be + run again without a download. Don't leave it full of breakpoint + instructions. */ + +static void +e7000_mourn_inferior () +{ + remove_breakpoints (); + unpush_target (&e7000_ops); + generic_mourn_inferior (); /* Do all the proper things now */ +} + +#define MAX_BREAKPOINTS 200 +#ifdef HARD_BREAKPOINTS +#define MAX_E7000DEBUG_BREAKPOINTS (BC_BREAKPOINTS ? 5 : MAX_BREAKPOINTS) +#else +#define MAX_E7000DEBUG_BREAKPOINTS MAX_BREAKPOINTS +#endif + +/* 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; +{ + int i; + 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=%x\r", i+1, addr); + puts_e7000debug (buf); + } + else + { + sprintf (buf, "B %x\r", addr); + puts_e7000debug (buf); + } +#else +#if 0 + e7000_read_inferior_memory (addr, shadow, 2); + e7000_write_inferior_memory (addr, nop, 2); +#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); + return 1; +} + +static int +e7000_remove_breakpoint (addr, shadow) + CORE_ADDR addr; + unsigned char *shadow; +{ + int i; + char buf[200]; + + for (i = 0; i < MAX_E7000DEBUG_BREAKPOINTS; i++) + if (breakaddr[i] == addr) + { + breakaddr[i] = 0; +#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 (); + +#if 0 + /* Replace the insn under the break */ + e7000_write_inferior_memory (addr, shadow, 2); +#endif +#endif + + return 0; + } + + 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. */ + +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) + { + puts_e7000debug ("\r"); + } + else + { + 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 +e7000_drain_command (args, fromtty) + char *args; + int fromtty; + +{ + int c; + + 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_unfiltered ("%c", c & 0xff); + else + printf_unfiltered ("<%x>", c & 0xff); + } +} + +#define NITEMS 7 + +static int +why_stop () +{ + static char *strings[NITEMS] = { + "STEP NORMAL", + "BREAK POINT", + "BREAK KEY", + "BREAK CONDI", + "CYCLE ACCESS", + "ILLEGAL INSTRUCTION", + "WRITE PROTECT", + }; + char *p[NITEMS]; + int c; + int i; + + for (i = 0; i < NITEMS; ++i) + p[i] = strings[i]; + + c = gch (); + while (1) + { + for (i = 0; i < NITEMS; i++) + { + if (c == *(p[i])) + { + 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 (strings) +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; + } + + 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_unfiltered ("%s", buffer); + buffer = saveaway; + } + if (c != -1) + { + putchar_unfiltered (c); + gdb_flush (gdb_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. */ + +static void +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); + 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", + 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; + 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 ("="); + +#ifdef GDB_TARGET_IS_SH + wanted_nopc = want_nopc; + if (TARGET_ARCHITECTURE->arch == bfd_arch_sh) + switch (TARGET_ARCHITECTURE->mach) + { + case bfd_mach_sh3: + case bfd_mach_sh3e: + wanted_nopc = want_sh3_nopc; + } +#else + 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++) + { + int buf = 0; + supply_register (regno, (char *) &buf); + } + + stop_reason = why_stop (); + expect_full_prompt (); + + 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; +} + +/* Stop the running program. */ + +static void +e7000_stop () +{ + /* Sending a ^C is supposed to stop the running program. */ + putchar_e7000 (CTRLC); +} + +/* Define the target subroutine names. */ + +struct target_ops e7000_ops ; + +static void +init_e7000_ops(void) +{ + 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_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 () +{ + init_e7000_ops() ; + add_target (&e7000_ops); + + add_com ("e7000", class_obscure, e7000_command, + "Send a command to the e7000 monitor."); + + add_com ("ftplogin", class_obscure, e7000_login_command, + "Login to machine and change to directory."); + + add_com ("ftpload", class_obscure, e7000_ftp_command, + "Fetch and load a file from previously described place."); + + add_com ("drain", class_obscure, e7000_drain_command, + "Drain pending e7000 text buffers."); + + 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); +} |