* configure.in: Move test for m68*-est-* before m68*-*-coff*.
* findvar.c: Move default def of CANNOT_STORE_REGISTER closer to the beginning of the code. * (write_register_gen): New routine. Analogous to read_register_gen. * (write_register_bytes): Another rewrite! Make it smarter about not updating regs with the same value. * monitor.c (printf_monitor readchar): Use stderr instead of stdout to output debug info. Also cleanup readchar a little. * (expect): Make sure that excessive responses are null terminated. * (monitor_open): Check for magic number in monitor_ops struct. Allow multiple commands as init strings. Also, clear all breakpoints. * (monitor_resume monitor_wait): Send a command to dump all the regs for those targets which don't do so when waking up after a continue command. * (monitor_wait): Handle excessive response output better. * (monitor_write_memory): Use block fill, word, and long word commands (if they exist) to write memory more efficiently. * General cleanups to use flag bits instead of individual flag words in monitor_ops struct. * (monitor_command): Return output from command. * (monitor_load_srec): Allocate buffer only once. Use alloca. Wait for load response string instead of using a timeout to start sending S-records. Fix bug where value of srec_frame shrinks. If hashmark is set, print `-' for retransmissions. General cleanups. * (monitor_make_srec): Get rid of S-record default type kludge. * monitor.h: Use seperate struct for memory and register read/write commands. Memory commands can come in byte, word, long, and longlong forms. * (monitor_ops): Change lots of fields. Generalize some stuff. Put all flags into flags word. Allow init to be a list of commands. Add command for clearing all breakpoints, block fill, dumping all registers. * remote-est.c: Rewrite to use new monitor conventions. * config/m68k/est.mt (TDEPFILES): Add monitor.o. * config/m68k/tm-est.h: Set NUM_REGS to 18. * testsuite/gdb.base/break.exp: Lots of cleanups. Use gdb_test more thoroughly.
This commit is contained in:
parent
1ef0c066d9
commit
a25a9f49ca
|
@ -1,3 +1,3 @@
|
|||
# Target: m68k emulator EST-300
|
||||
TDEPFILES= m68k-tdep.o remote-est.o
|
||||
TDEPFILES= m68k-tdep.o monitor.o remote-est.o
|
||||
TM_FILE= tm-est.h
|
||||
|
|
|
@ -28,6 +28,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
/* We have more complex, useful breakpoints on the target. */
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
|
||||
#define NUM_REGS 18
|
||||
|
||||
#include "m68k/tm-m68k.h"
|
||||
|
||||
#undef FRAME_CHAIN
|
||||
|
|
|
@ -269,6 +269,7 @@ m68*-tandem-*) gdb_target=st2000 ;;
|
|||
m68*-rom68k-*) gdb_target=monitor ;;
|
||||
m68*-*bug-*) gdb_target=monitor ;;
|
||||
m68*-monitor-*) gdb_target=monitor ;;
|
||||
m68*-est-*) gdb_target=est ;;
|
||||
m68*-*-aout*) gdb_target=monitor ;;
|
||||
m68*-*-coff*) gdb_target=monitor ;;
|
||||
m68*-*-elf*) gdb_target=monitor ;;
|
||||
|
@ -279,7 +280,6 @@ m68*-*-sunos3*) gdb_target=sun3os3 ;;
|
|||
m68*-*-sunos4*) gdb_target=sun3os4 ;;
|
||||
m68*-*-sysv4*) gdb_target=m68kv4 ;;
|
||||
m68*-*-vxworks*) gdb_target=vxworks68 ;;
|
||||
m68*-*-est*) gdb_target=est ;;
|
||||
|
||||
m88*-harris-cxux*) gdb_target=cxux ;;
|
||||
m88*-motorola-sysv4*) gdb_target=delta88v4 ;;
|
||||
|
|
|
@ -56,57 +56,84 @@ struct rom_cmd_data {
|
|||
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)
|
||||
|
@ -127,7 +154,6 @@ extern struct monitor_ops *current_monitor;
|
|||
#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
|
||||
|
|
651
gdb/remote-est.c
651
gdb/remote-est.c
|
@ -3,6 +3,7 @@
|
|||
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.
|
||||
|
||||
|
@ -20,570 +21,158 @@
|
|||
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 est_open PARAMS ((char *args, int from_tty));
|
||||
|
||||
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 ();
|
||||
}
|
||||
|
||||
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 ();
|
||||
}
|
||||
if (regnamelen != 2)
|
||||
return;
|
||||
|
||||
/* 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)
|
||||
switch (regname[0])
|
||||
{
|
||||
est_store_registers ();
|
||||
case 'S':
|
||||
if (regname[1] != 'R')
|
||||
return;
|
||||
regno = PS_REGNUM;
|
||||
break;
|
||||
case 'P':
|
||||
if (regname[1] != 'C')
|
||||
return;
|
||||
regno = PC_REGNUM;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
return;
|
||||
write_and_expect (buf);
|
||||
expect_prompt ();
|
||||
monitor_supply_register (regno, val);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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".
|
||||
*/
|
||||
|
||||
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;
|
||||
static char *est_regnames[NUM_REGS] =
|
||||
{
|
||||
int count;
|
||||
int c;
|
||||
char buf[20];
|
||||
/* Starting address of this pass. */
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
|
||||
"SR", "PC",
|
||||
};
|
||||
|
||||
if (((memaddr - 1) + len) < memaddr)
|
||||
{
|
||||
errno = EIO;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
sprintf (buf, ".dmb %x %x", memaddr, len);
|
||||
write_and_expect (buf);
|
||||
count = 0;
|
||||
static struct target_ops est_ops;
|
||||
|
||||
c = sr_readchar ();
|
||||
static char *est_loadtypes[] = {"none", "srec", "default", NULL};
|
||||
static char *est_loadprotos[] = {"none", NULL};
|
||||
|
||||
while (count < len)
|
||||
{
|
||||
while (!isdigit (c) && !isalpha (c)) {
|
||||
if (c == '!')
|
||||
{
|
||||
expect_prompt();
|
||||
errno =EIO;
|
||||
return 0;
|
||||
static char *est_inits[] = {"he\r", /* Resets the prompt, and clears repeated cmds */
|
||||
NULL};
|
||||
|
||||
}
|
||||
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 */
|
||||
static struct monitor_ops est_cmds =
|
||||
{
|
||||
if (write)
|
||||
{
|
||||
return est_write_memory (memaddr, myaddr, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return est_read_memory (memaddr, myaddr, len);
|
||||
}
|
||||
}
|
||||
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 */
|
||||
};
|
||||
|
||||
|
||||
#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;
|
||||
break;
|
||||
/* Address error */
|
||||
case 'A':
|
||||
status->value.sig = TARGET_SIGNAL_BUS;
|
||||
break;
|
||||
/* Break */
|
||||
case 'B':
|
||||
status->value.sig = TARGET_SIGNAL_TRAP;
|
||||
break;
|
||||
}
|
||||
expect_prompt ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
est_checkin ()
|
||||
{
|
||||
write_and_expect (".in");
|
||||
gr_expect_prompt ();
|
||||
}
|
||||
|
||||
extern struct gr_settings est_settings;
|
||||
|
||||
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 =
|
||||
{
|
||||
"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 */
|
||||
};
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_remote_est ()
|
||||
_initialize_est ()
|
||||
{
|
||||
init_monitor_ops (&est_ops);
|
||||
|
||||
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;
|
||||
|
||||
add_target (&est_ops);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue