1/* Remote target glue for the Renesas SH-3 ROM monitor.
2   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
3   Free Software Foundation, Inc.
4
5   This file is part of GDB.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330,
20   Boston, MA 02111-1307, USA.  */
21
22#include "defs.h"
23#include "gdbcore.h"
24#include "target.h"
25#include "monitor.h"
26#include "serial.h"
27#include "srec.h"
28#include "arch-utils.h"
29#include "regcache.h"
30#include "gdb_string.h"
31
32#include "sh-tdep.h"
33
34static struct serial *parallel;
35static int parallel_in_use;
36
37static void sh3_open (char *args, int from_tty);
38
39static void
40sh3_supply_register (char *regname, int regnamelen, char *val, int vallen)
41{
42  int numregs;
43  int regno;
44
45  numregs = 1;
46  regno = -1;
47
48  if (regnamelen == 2)
49    {
50      switch (regname[0])
51	{
52	case 'S':
53	  if (regname[1] == 'R')
54	    regno = SR_REGNUM;
55	  break;
56	case 'P':
57	  if (regname[1] == 'C')
58	    regno = PC_REGNUM;
59	  else if (regname[1] == 'R')
60	    regno = PR_REGNUM;
61	  break;
62	}
63    }
64  else if (regnamelen == 3)
65    {
66      switch (regname[0])
67	{
68	case 'G':
69	case 'V':
70	  if (regname[1] == 'B' && regname[2] == 'R')
71	    {
72	      if (regname[0] == 'G')
73		regno = VBR_REGNUM;
74	      else
75		regno = GBR_REGNUM;
76	    }
77	  break;
78	case 'S':
79	  if (regname[1] == 'S' && regname[2] == 'R')
80	    regno = SSR_REGNUM;
81	  else if (regname[1] == 'P' && regname[2] == 'C')
82	    regno = SPC_REGNUM;
83	  break;
84	}
85    }
86  else if (regnamelen == 4)
87    {
88      switch (regname[0])
89	{
90	case 'M':
91	  if (regname[1] == 'A' && regname[2] == 'C')
92	    {
93	      if (regname[3] == 'H')
94		regno = MACH_REGNUM;
95	      else if (regname[3] == 'L')
96		regno = MACL_REGNUM;
97	    }
98	  break;
99	case 'R':
100	  if (regname[1] == '0' && regname[2] == '-' && regname[3] == '7')
101	    {
102	      regno = R0_REGNUM;
103	      numregs = 8;
104	    }
105	}
106    }
107  else if (regnamelen == 5)
108    {
109      if (regname[1] == '8' && regname[2] == '-' && regname[3] == '1'
110	  && regname[4] == '5')
111	{
112	  regno = R0_REGNUM + 8;
113	  numregs = 8;
114	}
115    }
116  else if (regnamelen == 17)
117    {
118    }
119
120  if (regno >= 0)
121    while (numregs-- > 0)
122      val = monitor_supply_register (regno++, val);
123}
124
125static void
126sh3_load (struct serial *desc, char *file, int hashmark)
127{
128  if (parallel_in_use)
129    {
130      monitor_printf ("pl;s\r");
131      load_srec (parallel, file, 0, 80, SREC_ALL, hashmark, NULL);
132      monitor_expect_prompt (NULL, 0);
133    }
134  else
135    {
136      monitor_printf ("il;s:x\r");
137      monitor_expect ("\005", NULL, 0);		/* Look for ENQ */
138      serial_write (desc, "\006", 1);	/* Send ACK */
139      monitor_expect ("LO x\r", NULL, 0);	/* Look for filename */
140
141      load_srec (desc, file, 0, 80, SREC_ALL, hashmark, NULL);
142
143      monitor_expect ("\005", NULL, 0);		/* Look for ENQ */
144      serial_write (desc, "\006", 1);	/* Send ACK */
145      monitor_expect_prompt (NULL, 0);
146    }
147}
148
149/* This array of registers need to match the indexes used by GDB.
150   This exists because the various ROM monitors use different strings
151   than does GDB, and don't necessarily support all the registers
152   either. So, typing "info reg sp" becomes a "r30".  */
153
154static char *sh3_regnames[] =
155{
156  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
157  "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
158  "PC", "PR", "GBR", "VBR", "MACH", "MACL", "SR",
159  NULL, NULL,
160  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
161  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
162  "SSR", "SPC",
163  "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
164  "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
165  "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
166  "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
167};
168
169static char *sh3e_regnames[] =
170{
171  "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
172  "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
173  "PC", "PR", "GBR", "VBR", "MACH", "MACL", "SR",
174  "FPUL", "FPSCR",
175  "FR0", "FR1", "FR2", "FR3", "FR4", "FR5", "FR6", "FR7",
176  "FR8", "FR9", "FR10", "FR11", "FR12", "FR13", "FR14", "FR15",
177  "SSR", "SPC",
178  "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0",
179  "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0",
180  "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1",
181  "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1"
182};
183
184/* Define the monitor command strings. Since these are passed directly
185   through to a printf style function, we may include formatting
186   strings. We also need a CR or LF on the end.  */
187
188static struct target_ops sh3_ops, sh3e_ops;
189
190static char *sh3_inits[] =
191{"\003", NULL};			/* Exits sub-command mode & download cmds */
192
193static struct monitor_ops sh3_cmds;
194
195static void
196init_sh3_cmds (void)
197{
198  sh3_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_GETMEM_READ_SINGLE;	/* flags */
199  sh3_cmds.init = sh3_inits;	/* monitor init string */
200  sh3_cmds.cont = "g\r";	/* continue command */
201  sh3_cmds.step = "s\r";	/* single step */
202  sh3_cmds.stop = "\003";	/* Interrupt program */
203  sh3_cmds.set_break = "b %x\r";	/* set a breakpoint */
204  sh3_cmds.clr_break = "b -%x\r";	/* clear a breakpoint */
205  sh3_cmds.clr_all_break = "b -\r";	/* clear all breakpoints */
206  sh3_cmds.fill = "f %x @%x %x\r";	/* fill (start len val) */
207  sh3_cmds.setmem.cmdb = "m %x %x\r";	/* setmem.cmdb (addr, value) */
208  sh3_cmds.setmem.cmdw = "m %x %x;w\r";		/* setmem.cmdw (addr, value) */
209  sh3_cmds.setmem.cmdl = "m %x %x;l\r";		/* setmem.cmdl (addr, value) */
210  sh3_cmds.setmem.cmdll = NULL;	/* setmem.cmdll (addr, value) */
211  sh3_cmds.setmem.resp_delim = NULL;	/* setreg.resp_delim */
212  sh3_cmds.setmem.term = NULL;	/* setreg.term */
213  sh3_cmds.setmem.term_cmd = NULL;	/* setreg.term_cmd */
214  sh3_cmds.getmem.cmdb = "m %x\r";	/* getmem.cmdb (addr, len) */
215  sh3_cmds.getmem.cmdw = "m %x;w\r";	/* getmem.cmdw (addr, len) */
216  sh3_cmds.getmem.cmdl = "m %x;l\r";	/* getmem.cmdl (addr, len) */
217  sh3_cmds.getmem.cmdll = NULL;	/* getmem.cmdll (addr, len) */
218  sh3_cmds.getmem.resp_delim = "^ [0-9A-F]+ ";	/* getmem.resp_delim */
219  sh3_cmds.getmem.term = "? ";	/* getmem.term */
220  sh3_cmds.getmem.term_cmd = ".\r";	/* getmem.term_cmd */
221  sh3_cmds.setreg.cmd = ".%s %x\r";	/* setreg.cmd (name, value) */
222  sh3_cmds.setreg.resp_delim = NULL;	/* setreg.resp_delim */
223  sh3_cmds.setreg.term = NULL;	/* setreg.term */
224  sh3_cmds.setreg.term_cmd = NULL;	/* setreg.term_cmd */
225  sh3_cmds.getreg.cmd = ".%s\r";	/* getreg.cmd (name) */
226  sh3_cmds.getreg.resp_delim = "=";	/* getreg.resp_delim */
227  sh3_cmds.getreg.term = "? ";	/* getreg.term */
228  sh3_cmds.getreg.term_cmd = ".\r";	/* getreg.term_cmd */
229  sh3_cmds.dump_registers = "r\r";	/* dump_registers */
230  sh3_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\( +[0-9a-fA-F]+\\b\\)*\\)";
231  sh3_cmds.supply_register = sh3_supply_register;
232  sh3_cmds.load_routine = sh3_load;	/* load_routine */
233  sh3_cmds.load = NULL;		/* download command */
234  sh3_cmds.loadresp = NULL;	/* Load response */
235  sh3_cmds.prompt = "\n:";	/* monitor command prompt */
236  sh3_cmds.line_term = "\r";	/* end-of-line terminator */
237  sh3_cmds.cmd_end = ".\r";	/* optional command terminator */
238  sh3_cmds.target = &sh3_ops;	/* target operations */
239  sh3_cmds.stopbits = SERIAL_1_STOPBITS;	/* number of stop bits */
240  sh3_cmds.regnames = sh3_regnames;	/* registers names */
241  sh3_cmds.magic = MONITOR_OPS_MAGIC;	/* magic */
242}				/* init_sh3_cmds */
243
244/* This monitor structure is identical except for a couple slots, so
245   we will fill it in from the base structure when needed.  */
246
247static struct monitor_ops sh3e_cmds;
248
249static void
250sh3_open (char *args, int from_tty)
251{
252  char *serial_port_name = args;
253  char *parallel_port_name = 0;
254
255  if (args)
256    {
257      char *cursor = serial_port_name = xstrdup (args);
258
259      while (*cursor && *cursor != ' ')
260	cursor++;
261
262      if (*cursor)
263	*cursor++ = 0;
264
265      while (*cursor == ' ')
266	cursor++;
267
268      if (*cursor)
269	parallel_port_name = cursor;
270    }
271
272  monitor_open (serial_port_name, &sh3_cmds, from_tty);
273
274  if (parallel_port_name)
275    {
276      parallel = serial_open (parallel_port_name);
277
278      if (!parallel)
279	perror_with_name ("Unable to open parallel port.");
280
281      parallel_in_use = 1;
282    }
283
284
285  /* If we connected successfully, we know the processor is an SH3.  */
286  {
287    struct gdbarch_info info;
288    gdbarch_info_init (&info);
289    info.bfd_arch_info = bfd_lookup_arch (bfd_arch_sh, bfd_mach_sh3);
290    if (!gdbarch_update_p (info))
291      error ("Target is not an SH3");
292  }
293}
294
295
296static void
297sh3e_open (char *args, int from_tty)
298{
299  char *serial_port_name = args;
300  char *parallel_port_name = 0;
301
302  if (args)
303    {
304      char *cursor = serial_port_name = xstrdup (args);
305
306      while (*cursor && *cursor != ' ')
307	cursor++;
308
309      if (*cursor)
310	*cursor++ = 0;
311
312      while (*cursor == ' ')
313	cursor++;
314
315      if (*cursor)
316	parallel_port_name = cursor;
317    }
318
319  /* Set up the SH-3E monitor commands structure.  */
320
321  memcpy (&sh3e_cmds, &sh3_cmds, sizeof (struct monitor_ops));
322
323  sh3e_cmds.target = &sh3e_ops;
324  sh3e_cmds.regnames = sh3e_regnames;
325
326  monitor_open (serial_port_name, &sh3e_cmds, from_tty);
327
328  if (parallel_port_name)
329    {
330      parallel = serial_open (parallel_port_name);
331
332      if (!parallel)
333	perror_with_name ("Unable to open parallel port.");
334
335      parallel_in_use = 1;
336    }
337
338  /* If we connected successfully, we know the processor is an SH3E.  */
339  {
340    struct gdbarch_info info;
341    gdbarch_info_init (&info);
342    info.bfd_arch_info = bfd_lookup_arch (bfd_arch_sh, bfd_mach_sh3);
343    if (!gdbarch_update_p (info))
344      error ("Target is not an SH3");
345  }
346}
347
348static void
349sh3_close (int quitting)
350{
351  monitor_close (quitting);
352  if (parallel_in_use)
353    {
354      serial_close (parallel);
355      parallel_in_use = 0;
356    }
357}
358
359extern initialize_file_ftype _initialize_sh3_rom; /* -Wmissing-prototypes */
360
361void
362_initialize_sh3_rom (void)
363{
364  init_sh3_cmds ();
365  init_monitor_ops (&sh3_ops);
366
367  sh3_ops.to_shortname = "sh3";
368  sh3_ops.to_longname = "Renesas SH-3 rom monitor";
369
370  sh3_ops.to_doc =
371  /* We can download through the parallel port too. */
372    "Debug on a Renesas eval board running the SH-3E rom monitor.\n"
373    "Specify the serial device it is connected to.\n"
374    "If you want to use the parallel port to download to it, specify that\n"
375    "as an additional second argument.";
376
377  sh3_ops.to_open = sh3_open;
378  sh3_ops.to_close = sh3_close;
379
380  add_target (&sh3_ops);
381
382  /* Setup the SH3e, which has float registers.  */
383
384  init_monitor_ops (&sh3e_ops);
385
386  sh3e_ops.to_shortname = "sh3e";
387  sh3e_ops.to_longname = "Renesas SH-3E rom monitor";
388
389  sh3e_ops.to_doc =
390  /* We can download through the parallel port too. */
391    "Debug on a Renesas eval board running the SH-3E rom monitor.\n"
392    "Specify the serial device it is connected to.\n"
393    "If you want to use the parallel port to download to it, specify that\n"
394    "as an additional second argument.";
395
396  sh3e_ops.to_open = sh3e_open;
397  sh3e_ops.to_close = sh3_close;
398
399  add_target (&sh3e_ops);
400}
401