1/* Remote debugging interface to dBUG ROM monitor for GDB, the GNU debugger.
2   Copyright 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3
4   Written by Stan Shebs of Cygnus Support.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place - Suite 330,
21   Boston, MA 02111-1307, USA.  */
22
23/* dBUG is a monitor supplied on various Motorola boards, including
24   m68k, ColdFire, and PowerPC-based designs.  The code here assumes
25   the ColdFire, and (as of 9/25/96) has only been tested with a
26   ColdFire IDP board.  */
27
28#include "defs.h"
29#include "gdbcore.h"
30#include "target.h"
31#include "monitor.h"
32#include "serial.h"
33#include "regcache.h"
34
35#include "m68k-tdep.h"
36
37static void dbug_open (char *args, int from_tty);
38
39static void
40dbug_supply_register (char *regname, int regnamelen, char *val, int vallen)
41{
42  int regno;
43
44  if (regnamelen != 2)
45    return;
46
47  switch (regname[0])
48    {
49    case 'S':
50      if (regname[1] != 'R')
51	return;
52      regno = PS_REGNUM;
53      break;
54    case 'P':
55      if (regname[1] != 'C')
56	return;
57      regno = PC_REGNUM;
58      break;
59    case 'D':
60      if (regname[1] < '0' || regname[1] > '7')
61	return;
62      regno = regname[1] - '0' + M68K_D0_REGNUM;
63      break;
64    case 'A':
65      if (regname[1] < '0' || regname[1] > '7')
66	return;
67      regno = regname[1] - '0' + M68K_A0_REGNUM;
68      break;
69    default:
70      return;
71    }
72
73  monitor_supply_register (regno, val);
74}
75
76/* This array of registers needs to match the indexes used by GDB. The
77   whole reason this exists is because the various ROM monitors use
78   different names than GDB does, and don't support all the registers
79   either. So, typing "info reg sp" becomes an "A7". */
80
81static const char *
82dbug_regname (int index)
83{
84  static char *regnames[] =
85  {
86    "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
87    "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
88    "SR", "PC"
89    /* no float registers */
90  };
91
92  if ((index >= (sizeof (regnames) / sizeof (regnames[0])))
93      || (index < 0) || (index >= NUM_REGS))
94    return NULL;
95  else
96    return regnames[index];
97
98}
99
100static struct target_ops dbug_ops;
101static struct monitor_ops dbug_cmds;
102
103static char *dbug_inits[] =
104{"\r", NULL};
105
106
107static void
108init_dbug_cmds (void)
109{
110  dbug_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_GETMEM_NEEDS_RANGE | MO_FILL_USES_ADDR;
111  dbug_cmds.init = dbug_inits;	/* Init strings */
112  dbug_cmds.cont = "go\r";	/* continue command */
113  dbug_cmds.step = "trace\r";	/* single step */
114  dbug_cmds.stop = NULL;	/* interrupt command */
115  dbug_cmds.set_break = "br %x\r";	/* set a breakpoint */
116  dbug_cmds.clr_break = "br -r %x\r";	/* clear a breakpoint */
117  dbug_cmds.clr_all_break = "br -r\r";	/* clear all breakpoints */
118  dbug_cmds.fill = "bf.b %x %x %x\r";	/* fill (start end val) */
119  dbug_cmds.setmem.cmdb = "mm.b %x %x\r";	/* setmem.cmdb (addr, value) */
120  dbug_cmds.setmem.cmdw = "mm.w %x %x\r";	/* setmem.cmdw (addr, value) */
121  dbug_cmds.setmem.cmdl = "mm.l %x %x\r";	/* setmem.cmdl (addr, value) */
122  dbug_cmds.setmem.cmdll = NULL;	/* setmem.cmdll (addr, value) */
123  dbug_cmds.setmem.resp_delim = NULL;	/* setmem.resp_delim */
124  dbug_cmds.setmem.term = NULL;	/* setmem.term */
125  dbug_cmds.setmem.term_cmd = NULL;	/* setmem.term_cmd */
126  dbug_cmds.getmem.cmdb = "md.b %x %x\r";	/* getmem.cmdb (addr, addr2) */
127  dbug_cmds.getmem.cmdw = "md.w %x %x\r";	/* getmem.cmdw (addr, addr2) */
128  dbug_cmds.getmem.cmdl = "md.l %x %x\r";	/* getmem.cmdl (addr, addr2) */
129  dbug_cmds.getmem.cmdll = NULL;	/* getmem.cmdll (addr, addr2) */
130  dbug_cmds.getmem.resp_delim = ":";	/* getmem.resp_delim */
131  dbug_cmds.getmem.term = NULL;	/* getmem.term */
132  dbug_cmds.getmem.term_cmd = NULL;	/* getmem.term_cmd */
133  dbug_cmds.setreg.cmd = "rm %s %x\r";	/* setreg.cmd (name, value) */
134  dbug_cmds.setreg.resp_delim = NULL;	/* setreg.resp_delim */
135  dbug_cmds.setreg.term = NULL;	/* setreg.term */
136  dbug_cmds.setreg.term_cmd = NULL;	/* setreg.term_cmd */
137  dbug_cmds.getreg.cmd = "rd %s\r";	/* getreg.cmd (name) */
138  dbug_cmds.getreg.resp_delim = ":";	/* getreg.resp_delim */
139  dbug_cmds.getreg.term = NULL;	/* getreg.term */
140  dbug_cmds.getreg.term_cmd = NULL;	/* getreg.term_cmd */
141  dbug_cmds.dump_registers = "rd\r";	/* dump_registers */
142  dbug_cmds.register_pattern = "\\(\\w+\\) +:\\([0-9a-fA-F]+\\b\\)";	/* register_pattern */
143  dbug_cmds.supply_register = dbug_supply_register;	/* supply_register */
144  dbug_cmds.load_routine = NULL;	/* load_routine (defaults to SRECs) */
145  dbug_cmds.load = "dl\r";	/* download command */
146  dbug_cmds.loadresp = "\n";	/* load response */
147  dbug_cmds.prompt = "dBUG>";	/* monitor command prompt */
148  dbug_cmds.line_term = "\r";	/* end-of-line terminator */
149  dbug_cmds.cmd_end = NULL;	/* optional command terminator */
150  dbug_cmds.target = &dbug_ops;	/* target operations */
151  dbug_cmds.stopbits = SERIAL_1_STOPBITS;	/* number of stop bits */
152  dbug_cmds.regnames = NULL;	/* registers names */
153  dbug_cmds.regname = dbug_regname;
154  dbug_cmds.magic = MONITOR_OPS_MAGIC;	/* magic */
155}				/* init_debug_ops */
156
157static void
158dbug_open (char *args, int from_tty)
159{
160  monitor_open (args, &dbug_cmds, from_tty);
161}
162
163extern initialize_file_ftype _initialize_dbug_rom; /* -Wmissing-prototypes */
164
165void
166_initialize_dbug_rom (void)
167{
168  init_dbug_cmds ();
169  init_monitor_ops (&dbug_ops);
170
171  dbug_ops.to_shortname = "dbug";
172  dbug_ops.to_longname = "dBUG monitor";
173  dbug_ops.to_doc = "Debug via the dBUG monitor.\n\
174Specify the serial device it is connected to (e.g. /dev/ttya).";
175  dbug_ops.to_open = dbug_open;
176
177  add_target (&dbug_ops);
178}
179