1130803Smarcel/* Remote target glue for the ROM68K ROM monitor.
2130803Smarcel   Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001
3130803Smarcel   Free Software Foundation, Inc.
4130803Smarcel
5130803Smarcel   This file is part of GDB.
6130803Smarcel
7130803Smarcel   This program is free software; you can redistribute it and/or modify
8130803Smarcel   it under the terms of the GNU General Public License as published by
9130803Smarcel   the Free Software Foundation; either version 2 of the License, or
10130803Smarcel   (at your option) any later version.
11130803Smarcel
12130803Smarcel   This program is distributed in the hope that it will be useful,
13130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130803Smarcel   GNU General Public License for more details.
16130803Smarcel
17130803Smarcel   You should have received a copy of the GNU General Public License
18130803Smarcel   along with this program; if not, write to the Free Software
19130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130803Smarcel   Boston, MA 02111-1307, USA.  */
21130803Smarcel
22130803Smarcel#include "defs.h"
23130803Smarcel#include "gdbcore.h"
24130803Smarcel#include "target.h"
25130803Smarcel#include "monitor.h"
26130803Smarcel#include "serial.h"
27130803Smarcel#include "regcache.h"
28130803Smarcel#include "value.h"
29130803Smarcel
30130803Smarcel#include "m68k-tdep.h"
31130803Smarcel
32130803Smarcelstatic void rom68k_open (char *args, int from_tty);
33130803Smarcel
34130803Smarcel/* Return true if C is a hex digit.
35130803Smarcel   We can't use isxdigit here: that is affected by the current locale;
36130803Smarcel   ROM68K is not.  */
37130803Smarcelstatic int
38130803Smarcelis_hex_digit (int c)
39130803Smarcel{
40130803Smarcel  return (('0' <= c && c <= '9')
41130803Smarcel          || ('a' <= c && c <= 'f')
42130803Smarcel          || ('A' <= c && c <= 'F'));
43130803Smarcel}
44130803Smarcel
45130803Smarcel
46130803Smarcel/* Convert hex digit A to a number.  */
47130803Smarcelstatic int
48130803Smarcelhex_digit_value (int a)
49130803Smarcel{
50130803Smarcel  if (a >= '0' && a <= '9')
51130803Smarcel    return a - '0';
52130803Smarcel  else if (a >= 'a' && a <= 'f')
53130803Smarcel    return a - 'a' + 10;
54130803Smarcel  else if (a >= 'A' && a <= 'F')
55130803Smarcel    return a - 'A' + 10;
56130803Smarcel  else
57130803Smarcel    error ("Invalid hex digit %d", a);
58130803Smarcel}
59130803Smarcel
60130803Smarcel
61130803Smarcel/* Return true iff C is a whitespace character.
62130803Smarcel   We can't use isspace here: that is affected by the current locale;
63130803Smarcel   ROM68K is not.  */
64130803Smarcelstatic int
65130803Smarcelis_whitespace (int c)
66130803Smarcel{
67130803Smarcel  return (c == ' '
68130803Smarcel          || c == '\r'
69130803Smarcel          || c == '\n'
70130803Smarcel          || c == '\t'
71130803Smarcel          || c == '\f');
72130803Smarcel}
73130803Smarcel
74130803Smarcel
75130803Smarcel/* Parse a string of hex digits starting at HEX, supply them as the
76130803Smarcel   value of register REGNO, skip any whitespace, and return a pointer
77130803Smarcel   to the next character.
78130803Smarcel
79130803Smarcel   There is a function in monitor.c, monitor_supply_register, which is
80130803Smarcel   supposed to do this job.  However, there is some rather odd stuff
81130803Smarcel   in there (whitespace characters don't terminate numbers, for
82130803Smarcel   example) that is incorrect for ROM68k.  It's basically impossible
83130803Smarcel   to safely tweak monitor_supply_register --- it's used by a zillion
84130803Smarcel   other monitors; who knows what behaviors they're depending on.  So
85130803Smarcel   instead, we'll just use our own function, which can behave exactly
86130803Smarcel   the way we want it to.  */
87130803Smarcelstatic char *
88130803Smarcelrom68k_supply_one_register (int regno, unsigned char *hex)
89130803Smarcel{
90130803Smarcel  ULONGEST value;
91130803Smarcel  unsigned char regbuf[MAX_REGISTER_SIZE];
92130803Smarcel
93130803Smarcel  value = 0;
94130803Smarcel  while (*hex != '\0')
95130803Smarcel    if (is_hex_digit (*hex))
96130803Smarcel      value = (value * 16) + hex_digit_value (*hex++);
97130803Smarcel    else
98130803Smarcel      break;
99130803Smarcel
100130803Smarcel  /* Skip any whitespace.  */
101130803Smarcel  while (is_whitespace (*hex))
102130803Smarcel    hex++;
103130803Smarcel
104130803Smarcel  store_unsigned_integer (regbuf, DEPRECATED_REGISTER_RAW_SIZE (regno), value);
105130803Smarcel  supply_register (regno, regbuf);
106130803Smarcel
107130803Smarcel  return hex;
108130803Smarcel}
109130803Smarcel
110130803Smarcel
111130803Smarcelstatic void
112130803Smarcelrom68k_supply_register (char *regname, int regnamelen, char *val, int vallen)
113130803Smarcel{
114130803Smarcel  int numregs;
115130803Smarcel  int regno;
116130803Smarcel
117130803Smarcel  numregs = 1;
118130803Smarcel  regno = -1;
119130803Smarcel
120130803Smarcel  if (regnamelen == 2)
121130803Smarcel    switch (regname[0])
122130803Smarcel      {
123130803Smarcel      case 'S':
124130803Smarcel	if (regname[1] == 'R')
125130803Smarcel	  regno = PS_REGNUM;
126130803Smarcel	break;
127130803Smarcel      case 'P':
128130803Smarcel	if (regname[1] == 'C')
129130803Smarcel	  regno = PC_REGNUM;
130130803Smarcel	break;
131130803Smarcel      case 'D':
132130803Smarcel	if (regname[1] != 'R')
133130803Smarcel	  break;
134130803Smarcel	regno = M68K_D0_REGNUM;
135130803Smarcel	numregs = 8;
136130803Smarcel	break;
137130803Smarcel      case 'A':
138130803Smarcel	if (regname[1] != 'R')
139130803Smarcel	  break;
140130803Smarcel	regno = M68K_A0_REGNUM;
141130803Smarcel	numregs = 7;
142130803Smarcel	break;
143130803Smarcel      }
144130803Smarcel  else if (regnamelen == 3)
145130803Smarcel    switch (regname[0])
146130803Smarcel      {
147130803Smarcel      case 'I':
148130803Smarcel	if (regname[1] == 'S' && regname[2] == 'P')
149130803Smarcel	  regno = SP_REGNUM;
150130803Smarcel      }
151130803Smarcel
152130803Smarcel  if (regno >= 0)
153130803Smarcel    while (numregs-- > 0)
154130803Smarcel      val = rom68k_supply_one_register (regno++, val);
155130803Smarcel}
156130803Smarcel
157130803Smarcel/* This array of registers need to match the indexes used by GDB.
158130803Smarcel   This exists because the various ROM monitors use different strings
159130803Smarcel   than does GDB, and don't necessarily support all the registers
160130803Smarcel   either. So, typing "info reg sp" becomes a "r30".  */
161130803Smarcel
162130803Smarcelstatic const char *
163130803Smarcelrom68k_regname (int index)
164130803Smarcel{
165130803Smarcel
166130803Smarcel  static char *regnames[] =
167130803Smarcel  {
168130803Smarcel    "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
169130803Smarcel    "A0", "A1", "A2", "A3", "A4", "A5", "A6", "ISP",
170130803Smarcel    "SR", "PC"
171130803Smarcel  };
172130803Smarcel
173130803Smarcel  if ((index >= (sizeof (regnames) / sizeof(regnames[0])))
174130803Smarcel       || (index < 0) || (index >= NUM_REGS))
175130803Smarcel    return NULL;
176130803Smarcel  else
177130803Smarcel    return regnames[index];
178130803Smarcel
179130803Smarcel}
180130803Smarcel
181130803Smarcel/* Define the monitor command strings. Since these are passed directly
182130803Smarcel   through to a printf style function, we may include formatting
183130803Smarcel   strings. We also need a CR or LF on the end.  */
184130803Smarcel
185130803Smarcelstatic struct target_ops rom68k_ops;
186130803Smarcel
187130803Smarcelstatic char *rom68k_inits[] =
188130803Smarcel{".\r\r", NULL};		/* Exits pm/pr & download cmds */
189130803Smarcel
190130803Smarcelstatic struct monitor_ops rom68k_cmds;
191130803Smarcel
192130803Smarcelstatic void
193130803Smarcelinit_rom68k_cmds (void)
194130803Smarcel{
195130803Smarcel  rom68k_cmds.flags = MO_PRINT_PROGRAM_OUTPUT;
196130803Smarcel  rom68k_cmds.init = rom68k_inits;	/* monitor init string */
197130803Smarcel  rom68k_cmds.cont = "go\r";
198130803Smarcel  rom68k_cmds.step = "st\r";
199130803Smarcel  rom68k_cmds.stop = NULL;
200130803Smarcel  rom68k_cmds.set_break = "db %x\r";
201130803Smarcel  rom68k_cmds.clr_break = "cb %x\r";
202130803Smarcel  rom68k_cmds.clr_all_break = "cb *\r";
203130803Smarcel  rom68k_cmds.fill = "fm %x %x %x\r";
204130803Smarcel  rom68k_cmds.setmem.cmdb = "pm %x %x\r";
205130803Smarcel  rom68k_cmds.setmem.cmdw = "pm.w %x %x\r";
206130803Smarcel  rom68k_cmds.setmem.cmdl = "pm.l %x %x\r";
207130803Smarcel  rom68k_cmds.setmem.cmdll = NULL;
208130803Smarcel  rom68k_cmds.setmem.resp_delim = NULL;
209130803Smarcel  rom68k_cmds.setmem.term = NULL;
210130803Smarcel  rom68k_cmds.setmem.term_cmd = NULL;
211130803Smarcel  rom68k_cmds.getmem.cmdb = "dm %x %x\r";
212130803Smarcel  rom68k_cmds.getmem.cmdw = "dm.w %x %x\r";
213130803Smarcel  rom68k_cmds.getmem.cmdl = "dm.l %x %x\r";
214130803Smarcel  rom68k_cmds.getmem.cmdll = NULL;
215130803Smarcel  rom68k_cmds.getmem.resp_delim = "  ";
216130803Smarcel  rom68k_cmds.getmem.term = NULL;
217130803Smarcel  rom68k_cmds.getmem.term_cmd = NULL;
218130803Smarcel  rom68k_cmds.setreg.cmd = "pr %s %x\r";
219130803Smarcel  rom68k_cmds.setreg.resp_delim = NULL;
220130803Smarcel  rom68k_cmds.setreg.term = NULL;
221130803Smarcel  rom68k_cmds.setreg.term_cmd = NULL;
222130803Smarcel  rom68k_cmds.getreg.cmd = "pr %s\r";
223130803Smarcel  rom68k_cmds.getreg.resp_delim = ":  ";
224130803Smarcel  rom68k_cmds.getreg.term = "= ";
225130803Smarcel  rom68k_cmds.getreg.term_cmd = ".\r";
226130803Smarcel  rom68k_cmds.dump_registers = "dr\r";
227130803Smarcel  rom68k_cmds.register_pattern =
228130803Smarcel    "\\(\\w+\\)=\\([0-9a-fA-F]+\\( +[0-9a-fA-F]+\\b\\)*\\)";
229130803Smarcel  rom68k_cmds.supply_register = rom68k_supply_register;
230130803Smarcel  rom68k_cmds.load_routine = NULL;
231130803Smarcel  rom68k_cmds.load = "dc\r";
232130803Smarcel  rom68k_cmds.loadresp = "Waiting for S-records from host... ";
233130803Smarcel  rom68k_cmds.prompt = "ROM68K :-> ";
234130803Smarcel  rom68k_cmds.line_term = "\r";
235130803Smarcel  rom68k_cmds.cmd_end = ".\r";
236130803Smarcel  rom68k_cmds.target = &rom68k_ops;
237130803Smarcel  rom68k_cmds.stopbits = SERIAL_1_STOPBITS;
238130803Smarcel  rom68k_cmds.regnames = NULL;
239130803Smarcel  rom68k_cmds.regname = rom68k_regname;
240130803Smarcel  rom68k_cmds.magic = MONITOR_OPS_MAGIC;
241130803Smarcel}				/* init_rom68k_cmds */
242130803Smarcel
243130803Smarcelstatic void
244130803Smarcelrom68k_open (char *args, int from_tty)
245130803Smarcel{
246130803Smarcel  monitor_open (args, &rom68k_cmds, from_tty);
247130803Smarcel}
248130803Smarcel
249130803Smarcelextern initialize_file_ftype _initialize_rom68k; /* -Wmissing-prototypes */
250130803Smarcel
251130803Smarcelvoid
252130803Smarcel_initialize_rom68k (void)
253130803Smarcel{
254130803Smarcel  init_rom68k_cmds ();
255130803Smarcel  init_monitor_ops (&rom68k_ops);
256130803Smarcel
257130803Smarcel  rom68k_ops.to_shortname = "rom68k";
258130803Smarcel  rom68k_ops.to_longname = "Rom68k debug monitor for the IDP Eval board";
259130803Smarcel  rom68k_ops.to_doc = "Debug on a Motorola IDP eval board running the ROM68K monitor.\n\
260130803SmarcelSpecify the serial device it is connected to (e.g. /dev/ttya).";
261130803Smarcel  rom68k_ops.to_open = rom68k_open;
262130803Smarcel
263130803Smarcel  add_target (&rom68k_ops);
264130803Smarcel}
265