diff options
Diffstat (limited to 'gdb/remote-est.c')
-rw-r--r-- | gdb/remote-est.c | 659 |
1 files changed, 124 insertions, 535 deletions
diff --git a/gdb/remote-est.c b/gdb/remote-est.c index 1fbdfac..83e5756 100644 --- a/gdb/remote-est.c +++ b/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 -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); } |