1130812Smarcel/* Remote debugging interface for PPCbug (PowerPC) Rom monitor
2130812Smarcel   for GDB, the GNU debugger.
3130812Smarcel   Copyright 1995, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4130812Smarcel
5130812Smarcel   Written by Stu Grossman of Cygnus Support
6130812Smarcel
7130812Smarcel   This file is part of GDB.
8130812Smarcel
9130812Smarcel   This program is free software; you can redistribute it and/or modify
10130812Smarcel   it under the terms of the GNU General Public License as published by
11130812Smarcel   the Free Software Foundation; either version 2 of the License, or
12130812Smarcel   (at your option) any later version.
13130812Smarcel
14130812Smarcel   This program is distributed in the hope that it will be useful,
15130812Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
16130812Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17130812Smarcel   GNU General Public License for more details.
18130812Smarcel
19130812Smarcel   You should have received a copy of the GNU General Public License
20130812Smarcel   along with this program; if not, write to the Free Software
21130812Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
22130812Smarcel   Boston, MA 02111-1307, USA.  */
23130812Smarcel
24130812Smarcel#include "defs.h"
25130812Smarcel#include "gdbcore.h"
26130812Smarcel#include "target.h"
27130812Smarcel#include "monitor.h"
28130812Smarcel#include "serial.h"
29130812Smarcel#include "regcache.h"
30130812Smarcel
31130812Smarcelstatic void
32130812Smarcelppcbug_supply_register (char *regname, int regnamelen, char *val, int vallen)
33130812Smarcel{
34130812Smarcel  int regno = 0;
35130812Smarcel
36130812Smarcel  if (regnamelen < 2 || regnamelen > 4)
37130812Smarcel    return;
38130812Smarcel
39130812Smarcel  switch (regname[0])
40130812Smarcel    {
41130812Smarcel    case 'R':
42130812Smarcel      if (regname[1] < '0' || regname[1] > '9')
43130812Smarcel	return;
44130812Smarcel      if (regnamelen == 2)
45130812Smarcel	regno = regname[1] - '0';
46130812Smarcel      else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9')
47130812Smarcel	regno = (regname[1] - '0') * 10 + (regname[2] - '0');
48130812Smarcel      else
49130812Smarcel	return;
50130812Smarcel      break;
51130812Smarcel    case 'F':
52130812Smarcel      if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9')
53130812Smarcel	return;
54130812Smarcel      if (regnamelen == 3)
55130812Smarcel	regno = 32 + regname[2] - '0';
56130812Smarcel      else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9')
57130812Smarcel	regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0');
58130812Smarcel      else
59130812Smarcel	return;
60130812Smarcel      break;
61130812Smarcel    case 'I':
62130812Smarcel      if (regnamelen != 2 || regname[1] != 'P')
63130812Smarcel	return;
64130812Smarcel      regno = 64;
65130812Smarcel      break;
66130812Smarcel    case 'M':
67130812Smarcel      if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R')
68130812Smarcel	return;
69130812Smarcel      regno = 65;
70130812Smarcel      break;
71130812Smarcel    case 'C':
72130812Smarcel      if (regnamelen != 2 || regname[1] != 'R')
73130812Smarcel	return;
74130812Smarcel      regno = 66;
75130812Smarcel      break;
76130812Smarcel    case 'S':
77130812Smarcel      if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R')
78130812Smarcel	return;
79130812Smarcel      else if (regname[3] == '8')
80130812Smarcel	regno = 67;
81130812Smarcel      else if (regname[3] == '9')
82130812Smarcel	regno = 68;
83130812Smarcel      else if (regname[3] == '1')
84130812Smarcel	regno = 69;
85130812Smarcel      else if (regname[3] == '0')
86130812Smarcel	regno = 70;
87130812Smarcel      else
88130812Smarcel	return;
89130812Smarcel      break;
90130812Smarcel    default:
91130812Smarcel      return;
92130812Smarcel    }
93130812Smarcel
94130812Smarcel  monitor_supply_register (regno, val);
95130812Smarcel}
96130812Smarcel
97130812Smarcel/*
98130812Smarcel * This array of registers needs to match the indexes used by GDB. The
99130812Smarcel * whole reason this exists is because the various ROM monitors use
100130812Smarcel * different names than GDB does, and don't support all the
101130812Smarcel * registers either. So, typing "info reg sp" becomes an "A7".
102130812Smarcel */
103130812Smarcel
104130812Smarcelstatic char *ppcbug_regnames[] =
105130812Smarcel{
106130812Smarcel  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
107130812Smarcel  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
108130812Smarcel  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
109130812Smarcel  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
110130812Smarcel
111130812Smarcel  "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
112130812Smarcel  "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
113130812Smarcel  "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
114130812Smarcel  "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
115130812Smarcel
116130812Smarcel/* pc      ps      cnd     lr      cnt     xer     mq */
117130812Smarcel  "ip", "msr", "cr", "spr8", "spr9", "spr1", "spr0"
118130812Smarcel};
119130812Smarcel
120130812Smarcel/*
121130812Smarcel * Define the monitor command strings. Since these are passed directly
122130812Smarcel * through to a printf style function, we need can include formatting
123130812Smarcel * strings. We also need a CR or LF on the end.
124130812Smarcel */
125130812Smarcel
126130812Smarcelstatic struct target_ops ppcbug_ops0;
127130812Smarcelstatic struct target_ops ppcbug_ops1;
128130812Smarcel
129130812Smarcelstatic char *ppcbug_inits[] =
130130812Smarcel{"\r", NULL};
131130812Smarcel
132130812Smarcelstatic void
133130812Smarcelinit_ppc_cmds (char *LOAD_CMD,
134130812Smarcel	       struct monitor_ops *OPS,
135130812Smarcel	       struct target_ops *targops)
136130812Smarcel{
137130812Smarcel  OPS->flags = MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL;
138130812Smarcel  OPS->init = ppcbug_inits;	/* Init strings */
139130812Smarcel  OPS->cont = "g\r";		/* continue command */
140130812Smarcel  OPS->step = "t\r";		/* single step */
141130812Smarcel  OPS->stop = NULL;		/* interrupt command */
142130812Smarcel  OPS->set_break = "br %x\r";	/* set a breakpoint */
143130812Smarcel  OPS->clr_break = "nobr %x\r";	/* clear a breakpoint */
144130812Smarcel  OPS->clr_all_break = "nobr\r";	/* clear all breakpoints */
145130812Smarcel  OPS->fill = "bf %x:%x %x;b\r";	/* fill (start count val) */
146130812Smarcel  OPS->setmem.cmdb = "ms %x %02x\r";	/* setmem.cmdb (addr, value) */
147130812Smarcel  OPS->setmem.cmdw = "ms %x %04x\r";	/* setmem.cmdw (addr, value) */
148130812Smarcel  OPS->setmem.cmdl = "ms %x %08x\r";	/* setmem.cmdl (addr, value) */
149130812Smarcel  OPS->setmem.cmdll = NULL;	/* setmem.cmdll (addr, value) */
150130812Smarcel  OPS->setmem.resp_delim = NULL;	/* setreg.resp_delim */
151130812Smarcel  OPS->setmem.term = NULL;	/* setreg.term */
152130812Smarcel  OPS->setmem.term_cmd = NULL;	/* setreg.term_cmd */
153130812Smarcel  OPS->getmem.cmdb = "md %x:%x;b\r";	/* getmem.cmdb (addr, len) */
154130812Smarcel  OPS->getmem.cmdw = "md %x:%x;b\r";	/* getmem.cmdw (addr, len) */
155130812Smarcel  OPS->getmem.cmdl = "md %x:%x;b\r";	/* getmem.cmdl (addr, len) */
156130812Smarcel  OPS->getmem.cmdll = NULL;	/* getmem.cmdll (addr, len) */
157130812Smarcel  OPS->getmem.resp_delim = " ";	/* getmem.resp_delim */
158130812Smarcel  OPS->getmem.term = NULL;	/* getmem.term */
159130812Smarcel  OPS->getmem.term_cmd = NULL;	/* getmem.term_cmd */
160130812Smarcel  OPS->setreg.cmd = "rs %s %x\r";	/* setreg.cmd (name, value) */
161130812Smarcel  OPS->setreg.resp_delim = NULL;	/* setreg.resp_delim */
162130812Smarcel  OPS->setreg.term = NULL;	/* setreg.term */
163130812Smarcel  OPS->setreg.term_cmd = NULL;	/* setreg.term_cmd */
164130812Smarcel  OPS->getreg.cmd = "rs %s\r";	/* getreg.cmd (name) */
165130812Smarcel  OPS->getreg.resp_delim = "=";	/* getreg.resp_delim */
166130812Smarcel  OPS->getreg.term = NULL;	/* getreg.term */
167130812Smarcel  OPS->getreg.term_cmd = NULL;	/* getreg.term_cmd */
168130812Smarcel  OPS->register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)";		/* register_pattern */
169130812Smarcel  OPS->supply_register = ppcbug_supply_register;	/* supply_register */
170130812Smarcel  OPS->dump_registers = "rd\r";	/* dump all registers */
171130812Smarcel  OPS->load_routine = NULL;	/* load_routine (defaults to SRECs) */
172130812Smarcel  OPS->load = LOAD_CMD;		/* download command */
173130812Smarcel  OPS->loadresp = NULL;		/* load response */
174130812Smarcel  OPS->prompt = "PPC1-Bug>";	/* monitor command prompt */
175130812Smarcel  OPS->line_term = "\r";	/* end-of-line terminator */
176130812Smarcel  OPS->cmd_end = NULL;		/* optional command terminator */
177130812Smarcel  OPS->target = targops;	/* target operations */
178130812Smarcel  OPS->stopbits = SERIAL_1_STOPBITS;	/* number of stop bits */
179130812Smarcel  OPS->regnames = ppcbug_regnames;	/* registers names */
180130812Smarcel  OPS->magic = MONITOR_OPS_MAGIC;	/* magic */
181130812Smarcel}
182130812Smarcel
183130812Smarcel
184130812Smarcelstatic struct monitor_ops ppcbug_cmds0;
185130812Smarcelstatic struct monitor_ops ppcbug_cmds1;
186130812Smarcel
187130812Smarcelstatic void
188130812Smarcelppcbug_open0 (char *args, int from_tty)
189130812Smarcel{
190130812Smarcel  monitor_open (args, &ppcbug_cmds0, from_tty);
191130812Smarcel}
192130812Smarcel
193130812Smarcelstatic void
194130812Smarcelppcbug_open1 (char *args, int from_tty)
195130812Smarcel{
196130812Smarcel  monitor_open (args, &ppcbug_cmds1, from_tty);
197130812Smarcel}
198130812Smarcel
199130812Smarcelextern initialize_file_ftype _initialize_ppcbug_rom; /* -Wmissing-prototypes */
200130812Smarcel
201130812Smarcelvoid
202130812Smarcel_initialize_ppcbug_rom (void)
203130812Smarcel{
204130812Smarcel  init_ppc_cmds ("lo 0\r", &ppcbug_cmds0, &ppcbug_ops0);
205130812Smarcel  init_ppc_cmds ("lo 1\r", &ppcbug_cmds1, &ppcbug_ops1);
206130812Smarcel  init_monitor_ops (&ppcbug_ops0);
207130812Smarcel
208130812Smarcel  ppcbug_ops0.to_shortname = "ppcbug";
209130812Smarcel  ppcbug_ops0.to_longname = "PowerPC PPCBug monitor on port 0";
210130812Smarcel  ppcbug_ops0.to_doc = "Debug via the PowerPC PPCBug monitor using port 0.\n\
211130812SmarcelSpecify the serial device it is connected to (e.g. /dev/ttya).";
212130812Smarcel  ppcbug_ops0.to_open = ppcbug_open0;
213130812Smarcel
214130812Smarcel  add_target (&ppcbug_ops0);
215130812Smarcel
216130812Smarcel  init_monitor_ops (&ppcbug_ops1);
217130812Smarcel
218130812Smarcel  ppcbug_ops1.to_shortname = "ppcbug1";
219130812Smarcel  ppcbug_ops1.to_longname = "PowerPC PPCBug monitor on port 1";
220130812Smarcel  ppcbug_ops1.to_doc = "Debug via the PowerPC PPCBug monitor using port 1.\n\
221130812SmarcelSpecify the serial device it is connected to (e.g. /dev/ttya).";
222130812Smarcel  ppcbug_ops1.to_open = ppcbug_open1;
223130812Smarcel
224130812Smarcel  add_target (&ppcbug_ops1);
225130812Smarcel}
226