ignored if TERM is NULL.
*/
-struct cmd_resp {
- char *cmd; /* Command to send */
+struct memrw_cmd
+{
+ char *cmdb; /* Command to send for byte read/write */
+ char *cmdw; /* Command for word (16 bit) read/write */
+ char *cmdl; /* Command for long (32 bit) read/write */
+ char *cmdll; /* Command for long long (64 bit) read/write */
char *resp_delim; /* String just prior to the desired value */
char *term; /* Terminating string to search for */
char *term_cmd; /* String to get out of sub-mode (if necessary) */
};
-struct monitor_ops {
- int type; /* 1 is ascii, 0 is GDB remote protocol */
- char *init; /* initialize to the monitor */
- char *execute; /* execute or usually GO command */
- char *resume; /* continue command */
- char *step; /* single step */
- char *set_break; /* set a breakpoint */
- char *clr_break; /* clear a breakpoint */
- int clr_type; /* number or address for clearing */
- struct cmd_resp setmem; /* set memory to a value */
- struct cmd_resp getmem; /* display memory */
- struct cmd_resp setreg; /* set a register */
- struct cmd_resp getreg; /* get a register */
+struct regrw_cmd
+{
+ char *cmd; /* Command to send for reg read/write */
+ char *resp_delim; /* String just prior to the desired value */
+ char *term; /* Terminating string to search for */
+ char *term_cmd; /* String to get out of sub-mode (if necessary) */
+};
+
+struct monitor_ops
+{
+ int flags; /* See below */
+ char **init; /* List of init commands. NULL terminated. */
+ char *cont; /* continue command */
+ char *step; /* single step */
+ char *set_break; /* set a breakpoint */
+ char *clr_break; /* clear a breakpoint */
+ char *clr_all_break; /* Clear all breakpoints */
+ char *fill; /* Memory fill cmd (addr len val) */
+ struct memrw_cmd setmem; /* set memory to a value */
+ struct memrw_cmd getmem; /* display memory */
+ struct regrw_cmd setreg; /* set a register */
+ struct regrw_cmd getreg; /* get a register */
/* Some commands can dump a bunch of registers
at once. This comes as a set of REG=VAL
pairs. This should be called for each pair
of registers that we can parse to supply
GDB with the value of a register. */
+ char *dump_registers; /* Command to dump all regs at once */
char *register_pattern; /* Pattern that picks out register from reg dump */
- void (*supply_register) PARAMS ((char *name, int namelen, char *val, int vallen));
- char *load; /* load command */
- char *prompt; /* monitor command prompt */
- char *cmd_delim; /* end-of-command delimitor */
- char *cmd_end; /* optional command terminator */
+ void (*supply_register) PARAMS ((char *name, int namelen, char *val, int vallen));
+ char *load; /* load command */
+ char *loadresp; /* Response to load command */
+ char *prompt; /* monitor command prompt */
+ char *cmd_delim; /* end-of-command delimitor */
+ char *cmd_end; /* optional command terminator */
struct target_ops *target; /* target operations */
- char **loadtypes; /* the load types that are supported */
- char **loadprotos; /* the load protocols that are supported */
- char *baudrates; /* supported baud rates */
- int stopbits; /* number of stop bits */
- char **regnames; /* array of register names in ascii */
+ char **loadtypes; /* the load types that are supported */
+ char **loadprotos; /* the load protocols that are supported */
+ char *baudrates; /* supported baud rates */
+ int stopbits; /* number of stop bits */
+ char **regnames; /* array of register names in ascii */
+ int magic; /* Check value */
};
+#define MONITOR_OPS_MAGIC 600925
+
+/* Flag defintions */
+
+#define MO_CLR_BREAK_USES_ADDR 0x1 /* If set, then clear breakpoint command
+ uses address, otherwise it uses an index
+ returned by the monitor. */
+#define MO_FILL_USES_ADDR 0x2 /* If set, then memory fill command uses
+ STARTADDR, ENDADDR+1, VALUE as args, else it
+ uses STARTADDR, LENGTH, VALUE as args. */
+#define MO_NEED_REGDUMP_AFTER_CONT 0x4 /* If set, then monitor doesn't auto-
+ matically supply register dump when
+ coming back after a continue. */
+
extern struct monitor_ops *current_monitor;
-#define PROTO_TYPE (current_monitor->type)
#define LOADTYPES (current_monitor->loadtypes)
#define LOADPROTOS (current_monitor->loadprotos)
#define INIT_CMD (current_monitor->init)
-#define GO_CMD (current_monitor->execute)
-#define CONT_CMD (current_monitor->resume)
+#define CONT_CMD (current_monitor->cont)
#define STEP_CMD (current_monitor->step)
#define SET_BREAK_CMD (current_monitor->set_break)
#define CLR_BREAK_CMD (current_monitor->clr_break)
-#define CLR_BREAK_ADDR (current_monitor->clr_type)
#define SET_MEM (current_monitor->setmem)
#define GET_MEM (current_monitor->getmem)
#define LOAD_CMD (current_monitor->load)
#define push_monitor(x) current_monitor = x;
#define SREC_SIZE 160
-#define GDBPROTO ((current_monitor->type) ? 0: 1)
/*
* FIXME: These are to temporarily maintain compatability with the
Contributed by Cygnus Support.
Written by Steve Chamberlain for Cygnus Support.
+ Re-written by Stu Grossman of Cygnus Support
This file is part of GDB.
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
#include "defs.h"
-#include "command.h"
#include "gdbcore.h"
#include "target.h"
-#include "wait.h"
-#include <varargs.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/types.h>
+#include "monitor.h"
#include "serial.h"
-#include "remote-utils.h"
-
-
-static void expect_char PARAMS ((int));
-
-
-static void
-write_and_expect (x)
-char *x;
-{
- sr_write_cr (x);
- sr_expect (x);
-}
-
-static void
-expect_char (want)
- int want;
-{
- int c = sr_readchar ();
- while (c != want)
- c = sr_readchar ();
-}
-
-
-static void
-expect_prompt ()
-{
- expect_char ('>');
-}
-
-static int
-get_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 = get_hex_digit (*start);
- int try;
-
- *start = sr_readchar ();
- while ((try = get_hex_digit (*start)) >= 0)
- {
- value <<= 4;
- value += try;
- *start = sr_readchar ();
- }
- return value;
-}
-
-/* Tell the remote machine to resume. */
-
-static void
-est_resume (pid, step, sig)
- int pid, step, sig;
-{
- write_and_expect (step ? ".SI" : ".GO");
-}
-
-/* A reg dump looks like
- D0 = 00000000 D1 = 00000000 D2 = 00000000 D3 = 00000000
- D4 = 00000000 D5 = 00000000 D6 = 00000000 D7 = 00000000
- A0 = 00000000 A1 = 00000000 A2 = 00000000 A3 = 00000000
- A4 = 00000000 A5 = 00000000 A6 = 00000000 A7 = 001104FE
- USP = 00110400 SSP*= 001104FE PC = 00229BBC SR = 2000
- VBR = 00110000 SFC = 0005 DFC = 0005
-
-or
-
-00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00001234 00000000 001104FE 00110400 001104FE 00229BBC 2000 00110000 0005 0005
-*/
-
-static int
-target_to_gdb_rn (rn)
- int rn;
-{
- if (rn < 16)
- return rn;
- if (rn == 18)
- return PC_REGNUM;
- if (rn == 19)
- return PS_REGNUM;
- return -1;
-}
-
-
-static void est_fetch_register ();
-static void
-est_fetch_registers ()
-{
- int regno;
- unsigned long val;
- int c;
- int target_rn;
- char buf[4];
- write_and_expect (".DR");
- buf[0] = 0;
- buf[1] = 0;
- buf[2] = 0;
- buf[3] = 0;
- for (regno = 0; regno < NUM_REGS; regno++)
- supply_register (regno, buf);
-
- c = sr_readchar ();
- for (target_rn = 0; target_rn < 23; target_rn++)
- {
- unsigned long val;
- while (!isdigit (c) && !isalpha (c))
- c = sr_readchar ();
- while (isdigit (c) || (c >= 'A' && c <= 'F'))
- {
- val <<= 4;
- if (isdigit (c))
- val = val + c - '0';
- else
- val = val + c - 'A' + 10;
- c = sr_readchar ();
- }
+static void est_open PARAMS ((char *args, int from_tty));
- regno = target_to_gdb_rn (target_rn);
- if (regno >= 0)
- {
- buf[0] = val >> 24;
- buf[1] = val >> 16;
- buf[2] = val >> 8;
- buf[3] = val >> 0;
- supply_register (regno, buf);
- }
- }
- expect_prompt();
-}
-
-/* Fetch register REGNO, or all registers if REGNO is -1.
- Returns errno value. */
-
-static
-void
-est_fetch_register (regno)
- int regno;
-{
- est_fetch_registers ();
-}
-
-/* Store the remote registers from the contents of the block REGS. */
-
-static void est_store_register ();
static void
-est_store_registers ()
+est_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
{
int regno;
- for (regno = 0; regno < 18; regno++)
- est_store_register (regno);
- registers_changed ();
-}
-
-/* Store register REGNO, or all if REGNO == 0.
- Return errno value. */
-static void
-est_store_register (regno)
- int regno;
-{
- char buf[20];
- if (regno == -1)
- {
- est_store_registers ();
- return;
- }
-
- if (regno < 8)
- sprintf (buf, ".SR D%d %x", regno, read_register (regno));
- else if (regno < 16)
- sprintf (buf, ".SR A%d %x", regno - 8, read_register (regno));
- else if (regno == PC_REGNUM)
- sprintf (buf, ".SR PC %x", read_register (regno));
- else if (regno == PS_REGNUM)
- sprintf (buf, ".SR SR %x", read_register (regno));
- else
+ if (regnamelen != 2)
return;
- write_and_expect (buf);
- 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
-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;
-}
-
-/* Copy LEN bytes of data from debugger memory at MYADDR
- to inferior's memory at MEMADDR. Returns length moved. */
-static int
-est_write_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- unsigned char *myaddr;
- int len;
-{
- int i;
-#define maxstride 128
- int stride;
-
- write_and_expect (".DL");
- expect_char ('+');
- for (i = 0; i < len; i += stride)
+ switch (regname[0])
{
- 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;
- compose[where++] = alen - 1 + '0'; /* insert type */
- check_sum += stickbyte (compose + where, alen + stride + 1); /* Insert length */
- 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++] = 0;
-
- sr_write_cr (compose);
- while (sr_readchar () != '+')
- sr_write_cr (compose);
- }
-
- /* Send the trailer record */
- sr_write_cr ("S70500000000FA");
- expect_prompt ();
- return len;
-}
-
-
-
-/*
-
- The dump memory command generates output which looks like:
-
-
-.dmb 0 100
-4E 56 FF FC 4E 71 42 AE FF FC 72 09 B2 AE FF FC NV..NqB...r.....
-6C 02 60 12 2F 2E FF FC 4E B9 00 00 00 2A 58 4F l.`./...N....*XO
-52 AE FF FC 60 E4 4E 5E 4E 75 4E 56 00 00 20 2E R...`.N^NuNV.. .
-00 08 D1 B9 00 00 00 00 4E 5E 4E 75 06 46 40 54 ........N^Nu.F@T
-04 45 44 4C 54 45 40 56 42 F4 04 64 24 45 05 05 .EDLTE@VB..d$E..
-00 6D 04 46 00 45 4C 05 04 46 04 4C 44 CD 00 65 .m.F.EL..F.LD..e
-40 45 44 55 45 45 45 46 04 44 44 40 05 4D 00 44 @EDUEEEF.DD@.M.D
-
-*/
-
-static int
-est_read_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- unsigned char *myaddr;
- int len;
-{
- int count;
- int c;
- char buf[20];
- /* Starting address of this pass. */
-
- if (((memaddr - 1) + len) < memaddr)
- {
- errno = EIO;
- return 0;
- }
-
- sprintf (buf, ".dmb %x %x", memaddr, len);
- write_and_expect (buf);
- count = 0;
-
- c = sr_readchar ();
-
- while (count < len)
- {
- while (!isdigit (c) && !isalpha (c)) {
- if (c == '!')
- {
- expect_prompt();
- errno =EIO;
- return 0;
-
- }
- c = sr_readchar ();
- }
- myaddr[count++] = get_hex (&c);
- c = sr_readchar ();
- if (c == ' ')
- {
- c = sr_readchar ();
- if (c == ' ')
- while (c != '\r')
- c = sr_readchar ();
- }
- }
-
- expect_prompt ();
-
-
- return len;
-}
-
-static int
-est_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 est_write_memory (memaddr, myaddr, len);
- }
- else
- {
- return est_read_memory (memaddr, myaddr, len);
- }
-}
-
-
-#define MAX_DEBUG_BREAKPOINTS 100
-
-extern int memory_breakpoint_size;
-static CORE_ADDR breakaddr[MAX_DEBUG_BREAKPOINTS] =
-{0};
-
-int
-est_clear_all_breakpoints ()
-{
- int i;
- for (i = 0; i < MAX_DEBUG_BREAKPOINTS; i++)
- {
- breakaddr[i] = 0;
- }
-
- if (sr_is_open ())
- {
- write_and_expect (".RB");
- expect_prompt ();
- }
- return 0;
-}
-
-static int
-est_insert_breakpoint (addr, shadow)
- CORE_ADDR addr;
- unsigned char *shadow;
-{
- int i;
-
- for (i = 0; i <= MAX_DEBUG_BREAKPOINTS; i++)
- if (breakaddr[i] == 0)
- {
- char buf[20];
- breakaddr[i] = addr;
- sprintf (buf, ".SB %x", addr);
- write_and_expect (buf);
- expect_prompt ();
- return 0;
- }
- error ("Too many breakpoints ( > %d) for the est\n", MAX_DEBUG_BREAKPOINTS);
- return 1;
-}
-
-static int
-est_remove_breakpoint (addr, shadow)
- CORE_ADDR addr;
- unsigned char *shadow;
-{
- int i;
-
- for (i = 0; i < MAX_DEBUG_BREAKPOINTS; i++)
- if (breakaddr[i] == addr)
- {
- char buf[20];
- breakaddr[i] = 0;
- sprintf (buf, ".RB %x", addr);
- write_and_expect (buf);
- expect_prompt ();
- return 0;
- }
-
- error ("Can't find breakpoint associated with 0x%x\n", addr);
- return 1;
-}
-
-
-/* Wait until the remote machine stops, then return,
- storing status in STATUS just as `wait' would. */
-
-static int
-est_wait (pid, status)
- int pid;
- struct target_waitstatus *status;
-{
- int c = sr_readchar ();
- while (c != '!')
- c = sr_readchar ();
- /* What sort of stop */
- c = sr_readchar ();
- status->kind = TARGET_WAITKIND_STOPPED;
- switch (c)
- {
- case 'E':
- status->value.sig = TARGET_SIGNAL_BUS;
+ case 'S':
+ if (regname[1] != 'R')
+ return;
+ regno = PS_REGNUM;
break;
- /* Address error */
- case 'A':
- status->value.sig = TARGET_SIGNAL_BUS;
+ case 'P':
+ if (regname[1] != 'C')
+ return;
+ regno = PC_REGNUM;
break;
- /* Break */
- case 'B':
- status->value.sig = TARGET_SIGNAL_TRAP;
+ case 'D':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + D0_REGNUM;
break;
+ case 'A':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + A0_REGNUM;
+ break;
+ default:
+ return;
}
- expect_prompt ();
- return 0;
+
+ monitor_supply_register (regno, val);
}
-void
-est_checkin ()
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+
+static char *est_regnames[NUM_REGS] =
{
- write_and_expect (".in");
- gr_expect_prompt ();
-}
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
+ "SR", "PC",
+};
-extern struct gr_settings est_settings;
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops est_ops;
+
+static char *est_loadtypes[] = {"none", "srec", "default", NULL};
+static char *est_loadprotos[] = {"none", NULL};
+
+static char *est_inits[] = {"he\r", /* Resets the prompt, and clears repeated cmds */
+ NULL};
+
+static struct monitor_ops est_cmds =
+{
+ MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_NEED_REGDUMP_AFTER_CONT,
+ est_inits, /* Init strings */
+ "go\r", /* continue command */
+ "sidr\r", /* single step */
+ "sb %x\r", /* set a breakpoint */
+ "rb %x\r", /* clear a breakpoint */
+ "rb\r", /* clear all breakpoints */
+ "bfb %x %x %x\r", /* fill (start end val) */
+ {
+ "smb %x %x\r", /* setmem.cmdb (addr, value) */
+ "smw %x %x\r", /* setmem.cmdw (addr, value) */
+ "sml %x %x\r", /* setmem.cmdl (addr, value) */
+ NULL, /* setmem.cmdll (addr, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL, /* setreg.term_cmd */
+ },
+ {
+ "dmb %x %x\r", /* getmem.cmdb (addr, len) */
+ "dmw %x %x\r", /* getmem.cmdw (addr, len) */
+ "dml %x %x\r", /* getmem.cmdl (addr, len) */
+ NULL, /* getmem.cmdll (addr, len) */
+ ": ", /* getmem.resp_delim */
+ NULL, /* getmem.term */
+ NULL, /* getmem.term_cmd */
+ },
+ {
+ "sr %s %x\r", /* setreg.cmd (name, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL /* setreg.term_cmd */
+ },
+ {
+ "dr %s\r", /* getreg.cmd (name) */
+ " = ", /* getreg.resp_delim */
+ NULL, /* getreg.term */
+ NULL /* getreg.term_cmd */
+ },
+ "dr\r", /* dump_registers */
+ "\\(\\w+\\) = \\([0-9a-fA-F]+\\)", /* register_pattern */
+ est_supply_register, /* supply_register */
+ "dl\r", /* download command */
+ "+", /* load response */
+ ">BKM>", /* monitor command prompt */
+ NULL, /* end-of-command delimitor */
+ NULL, /* optional command terminator */
+ &est_ops, /* target operations */
+ est_loadtypes, /* loadtypes */
+ est_loadprotos, /* loadprotos */
+ "9600", /* supported baud rates */
+ SERIAL_1_STOPBITS, /* number of stop bits */
+ est_regnames, /* registers names */
+ MONITOR_OPS_MAGIC /* magic */
+ };
-static void
-est_open (args, from_tty)
+void
+est_open(args, from_tty)
char *args;
int from_tty;
{
- gr_open (args, from_tty, &est_settings);
+ monitor_open (args, &est_cmds, from_tty);
}
-/* Define the target subroutine names */
-
-struct target_ops est_ops =
+void
+_initialize_est ()
{
- "est",
- "Remote EST-300 target",
- "Use a remote EST-300 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 est /dev/ttya 9600\n\
-target est foobar",
- est_open,
- gr_close,
- 0,
- gr_detach,
- est_resume,
- est_wait,
- est_fetch_register,
- est_store_register,
- gr_prepare_to_store,
- est_xfer_inferior_memory,
- gr_files_info,
- est_insert_breakpoint,
- est_remove_breakpoint, /* Breakpoints */
- 0,
- 0,
- 0,
- 0,
- 0, /* Terminal handling */
- gr_kill,
- gr_load_image, /* load */
- 0, /* lookup_symbol */
- gr_create_inferior,
- gr_mourn,
- 0, /* can_run */
- 0, /* notice_signals */
- 0, /* to_stop */
- 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 */
-};
+ init_monitor_ops (&est_ops);
-static struct gr_settings est_settings =
-{
- NULL, /* dcache */
- ">", /* prompt */
- &est_ops, /* ops */
- est_clear_all_breakpoints,
- est_read_memory, /* readfunc */
- est_write_memory, /* writefunc */
- est_checkin, /* checkin */
-};
+ est_ops.to_shortname = "est";
+ est_ops.to_longname = "EST background debug monitor";
+ est_ops.to_doc = "Debug via the EST BDM.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ est_ops.to_open = est_open;
-void
-_initialize_remote_est ()
-{
add_target (&est_ops);
}