* rom68k-rom.c (init_rom68k_cmds): Set the flag indicating that
[platform/upstream/binutils.git] / gdb / rom68k-rom.c
1 /* Remote target glue for the ROM68K ROM monitor.
2    Copyright 1988, 1991, 1992, 1993, 1994, 1995, 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 "regcache.h"
28 #include "value.h"
29
30 static void rom68k_open (char *args, int from_tty);
31
32 /* Return true if C is a hex digit.
33    We can't use isxdigit here: that is affected by the current locale;
34    ROM68K is not.  */
35 static int
36 is_hex_digit (int c)
37 {
38   return (('0' <= c && c <= '9')
39           || ('a' <= c && c <= 'f')
40           || ('A' <= c && c <= 'F'));
41 }
42
43
44 /* Convert hex digit A to a number.  */
45 static int
46 hex_digit_value (int a)
47 {
48   if (a >= '0' && a <= '9')
49     return a - '0';
50   else if (a >= 'a' && a <= 'f')
51     return a - 'a' + 10;
52   else if (a >= 'A' && a <= 'F')
53     return a - 'A' + 10;
54   else
55     error ("Invalid hex digit %d", a);
56 }
57
58
59 /* Return true iff C is a whitespace character.
60    We can't use isspace here: that is affected by the current locale;
61    ROM68K is not.  */
62 static int
63 is_whitespace (int c)
64 {
65   return (c == ' '
66           || c == '\r'
67           || c == '\n'
68           || c == '\t'
69           || c == '\f');
70 }
71
72
73 /* Parse a string of hex digits starting at HEX, supply them as the
74    value of register REGNO, skip any whitespace, and return a pointer
75    to the next character.
76
77    There is a function in monitor.c, monitor_supply_register, which is
78    supposed to do this job.  However, there is some rather odd stuff
79    in there (whitespace characters don't terminate numbers, for
80    example) that is incorrect for ROM68k.  It's basically impossible
81    to safely tweak monitor_supply_register --- it's used by a zillion
82    other monitors; who knows what behaviors they're depending on.  So
83    instead, we'll just use our own function, which can behave exactly
84    the way we want it to.  */
85 static char *
86 rom68k_supply_one_register (int regno, unsigned char *hex)
87 {
88   ULONGEST value;
89   unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
90
91   value = 0;
92   while (*hex != '\0')
93     if (is_hex_digit (*hex))
94       value = (value * 16) + hex_digit_value (*hex++);
95     else
96       break;
97
98   /* Skip any whitespace.  */
99   while (is_whitespace (*hex))
100     hex++;
101
102   store_unsigned_integer (regbuf, REGISTER_RAW_SIZE (regno), value);
103   supply_register (regno, regbuf);
104
105   return hex;
106 }
107
108
109 static void
110 rom68k_supply_register (char *regname, int regnamelen, char *val, int vallen)
111 {
112   int numregs;
113   int regno;
114
115   numregs = 1;
116   regno = -1;
117
118   if (regnamelen == 2)
119     switch (regname[0])
120       {
121       case 'S':
122         if (regname[1] == 'R')
123           regno = PS_REGNUM;
124         break;
125       case 'P':
126         if (regname[1] == 'C')
127           regno = PC_REGNUM;
128         break;
129       case 'D':
130         if (regname[1] != 'R')
131           break;
132         regno = D0_REGNUM;
133         numregs = 8;
134         break;
135       case 'A':
136         if (regname[1] != 'R')
137           break;
138         regno = A0_REGNUM;
139         numregs = 7;
140         break;
141       }
142   else if (regnamelen == 3)
143     switch (regname[0])
144       {
145       case 'I':
146         if (regname[1] == 'S' && regname[2] == 'P')
147           regno = SP_REGNUM;
148       }
149
150   if (regno >= 0)
151     while (numregs-- > 0)
152       val = rom68k_supply_one_register (regno++, val);
153 }
154
155 /* This array of registers need to match the indexes used by GDB.
156    This exists because the various ROM monitors use different strings
157    than does GDB, and don't necessarily support all the registers
158    either. So, typing "info reg sp" becomes a "r30".  */
159
160 static char *rom68k_regnames[NUM_REGS] =
161 {
162   "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
163   "A0", "A1", "A2", "A3", "A4", "A5", "A6", "ISP",
164   "SR", "PC"};
165
166 /* Define the monitor command strings. Since these are passed directly
167    through to a printf style function, we may include formatting
168    strings. We also need a CR or LF on the end.  */
169
170 static struct target_ops rom68k_ops;
171
172 static char *rom68k_inits[] =
173 {".\r\r", NULL};                /* Exits pm/pr & download cmds */
174
175 static struct monitor_ops rom68k_cmds;
176
177 static void
178 init_rom68k_cmds (void)
179 {
180   rom68k_cmds.flags = MO_PRINT_PROGRAM_OUTPUT;
181   rom68k_cmds.init = rom68k_inits;      /* monitor init string */
182   rom68k_cmds.cont = "go\r";
183   rom68k_cmds.step = "st\r";
184   rom68k_cmds.stop = NULL;
185   rom68k_cmds.set_break = "db %x\r";
186   rom68k_cmds.clr_break = "cb %x\r";
187   rom68k_cmds.clr_all_break = "cb *\r";
188   rom68k_cmds.fill = "fm %x %x %x\r";
189   rom68k_cmds.setmem.cmdb = "pm %x %x\r";
190   rom68k_cmds.setmem.cmdw = "pm.w %x %x\r";
191   rom68k_cmds.setmem.cmdl = "pm.l %x %x\r";
192   rom68k_cmds.setmem.cmdll = NULL;
193   rom68k_cmds.setmem.resp_delim = NULL;
194   rom68k_cmds.setmem.term = NULL;
195   rom68k_cmds.setmem.term_cmd = NULL;
196   rom68k_cmds.getmem.cmdb = "dm %x %x\r";
197   rom68k_cmds.getmem.cmdw = "dm.w %x %x\r";
198   rom68k_cmds.getmem.cmdl = "dm.l %x %x\r";
199   rom68k_cmds.getmem.cmdll = NULL;
200   rom68k_cmds.getmem.resp_delim = "  ";
201   rom68k_cmds.getmem.term = NULL;
202   rom68k_cmds.getmem.term_cmd = NULL;
203   rom68k_cmds.setreg.cmd = "pr %s %x\r";
204   rom68k_cmds.setreg.resp_delim = NULL;
205   rom68k_cmds.setreg.term = NULL;
206   rom68k_cmds.setreg.term_cmd = NULL;
207   rom68k_cmds.getreg.cmd = "pr %s\r";
208   rom68k_cmds.getreg.resp_delim = ":  ";
209   rom68k_cmds.getreg.term = "= ";
210   rom68k_cmds.getreg.term_cmd = ".\r";
211   rom68k_cmds.dump_registers = "dr\r";
212   rom68k_cmds.register_pattern =
213     "\\(\\w+\\)=\\([0-9a-fA-F]+\\( +[0-9a-fA-F]+\\b\\)*\\)";
214   rom68k_cmds.supply_register = rom68k_supply_register;
215   rom68k_cmds.load_routine = NULL;
216   rom68k_cmds.load = "dc\r";
217   rom68k_cmds.loadresp = "Waiting for S-records from host... ";
218   rom68k_cmds.prompt = "ROM68K :-> ";
219   rom68k_cmds.line_term = "\r";
220   rom68k_cmds.cmd_end = ".\r";
221   rom68k_cmds.target = &rom68k_ops;
222   rom68k_cmds.stopbits = SERIAL_1_STOPBITS;
223   rom68k_cmds.regnames = rom68k_regnames;
224   rom68k_cmds.magic = MONITOR_OPS_MAGIC;
225 }                               /* init_rom68k_cmds */
226
227 static void
228 rom68k_open (char *args, int from_tty)
229 {
230   monitor_open (args, &rom68k_cmds, from_tty);
231 }
232
233 void
234 _initialize_rom68k (void)
235 {
236   init_rom68k_cmds ();
237   init_monitor_ops (&rom68k_ops);
238
239   rom68k_ops.to_shortname = "rom68k";
240   rom68k_ops.to_longname = "Rom68k debug monitor for the IDP Eval board";
241   rom68k_ops.to_doc = "Debug on a Motorola IDP eval board running the ROM68K monitor.\n\
242 Specify the serial device it is connected to (e.g. /dev/ttya).";
243   rom68k_ops.to_open = rom68k_open;
244
245   add_target (&rom68k_ops);
246 }