diff options
author | Steve Chamberlain <sac@cygnus> | 1994-12-24 01:12:47 +0000 |
---|---|---|
committer | Steve Chamberlain <sac@cygnus> | 1994-12-24 01:12:47 +0000 |
commit | 93584146c524bda90be0c5021952d3262a45d1d9 (patch) | |
tree | 5c1767b11884e7fa3facc52833ca33a084881f6e /gdb/remote-est.c | |
parent | 8eac0979a0c0fe7aa6b378f8fc5701fc07cf59b2 (diff) | |
download | gdb-93584146c524bda90be0c5021952d3262a45d1d9.zip gdb-93584146c524bda90be0c5021952d3262a45d1d9.tar.gz gdb-93584146c524bda90be0c5021952d3262a45d1d9.tar.bz2 |
* remote-est.c: New file supports EST-300 CPU32 background
mode ICE.
* remote-utils.c (sr_com): Call registers_changed.
* configure.in (m68*-*-est*): New configuration.
* config/m68k/tm-est.h: New file.
Diffstat (limited to 'gdb/remote-est.c')
-rw-r--r-- | gdb/remote-est.c | 589 |
1 files changed, 589 insertions, 0 deletions
diff --git a/gdb/remote-est.c b/gdb/remote-est.c new file mode 100644 index 0000000..1fbdfac --- /dev/null +++ b/gdb/remote-est.c @@ -0,0 +1,589 @@ +/* Remote debugging interface for EST-300 ICE, for GDB + Copyright 1994 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., 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 "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 (); + } + + 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 () +{ + 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 + 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) + { + 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; + 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) + char *args; + int from_tty; +{ + gr_open (args, from_tty, &est_settings); +} + +/* 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 () +{ + add_target (&est_ops); +} |