]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/sparclet-rom.c
import gdb-1999-07-07 post reformat
[thirdparty/binutils-gdb.git] / gdb / sparclet-rom.c
1 /* Remote target glue for the SPARC Sparclet ROM monitor.
2 Copyright 1995, 1996 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
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 "symtab.h"
29 #include "symfile.h" /* for generic_load */
30 #include <time.h>
31
32 extern void report_transfer_performance PARAMS ((unsigned long, time_t, time_t));
33
34 static struct target_ops sparclet_ops;
35
36 static void sparclet_open PARAMS ((char *args, int from_tty));
37
38 /* This array of registers need to match the indexes used by GDB.
39 This exists because the various ROM monitors use different strings
40 than does GDB, and don't necessarily support all the registers
41 either. So, typing "info reg sp" becomes a "r30". */
42
43 /*PSR 0x00000080 impl ver icc AW LE EE EC EF PIL S PS ET CWP WIM
44 0x0 0x0 0x0 0 0 0 0 0 0x0 1 0 0 0x00 0x2
45 0000010
46 INS LOCALS OUTS GLOBALS
47 0 0x00000000 0x00000000 0x00000000 0x00000000
48 1 0x00000000 0x00000000 0x00000000 0x00000000
49 2 0x00000000 0x00000000 0x00000000 0x00000000
50 3 0x00000000 0x00000000 0x00000000 0x00000000
51 4 0x00000000 0x00000000 0x00000000 0x00000000
52 5 0x00000000 0x00001000 0x00000000 0x00000000
53 6 0x00000000 0x00000000 0x123f0000 0x00000000
54 7 0x00000000 0x00000000 0x00000000 0x00000000
55 pc: 0x12010000 0x00000000 unimp
56 npc: 0x12010004 0x00001000 unimp 0x1000
57 tbr: 0x00000000
58 y: 0x00000000
59 */
60 /* these correspond to the offsets from tm-* files from config directories */
61
62 /* is wim part of psr?? */
63 /* monitor wants lower case */
64 static char *sparclet_regnames[NUM_REGS] = REGISTER_NAMES;
65
66
67 /* Function: sparclet_supply_register
68 Just returns with no action.
69 This function is required, because parse_register_dump (monitor.c)
70 expects to be able to call it. If we don't supply something, it will
71 call a null pointer and core-dump. Since this function does not
72 actually do anything, GDB will request the registers individually. */
73
74 static void
75 sparclet_supply_register (regname, regnamelen, val, vallen)
76 char *regname;
77 int regnamelen;
78 char *val;
79 int vallen;
80 {
81 return;
82 }
83
84 static void
85 sparclet_load (desc, file, hashmark)
86 serial_t desc;
87 char *file;
88 int hashmark;
89 {
90 bfd *abfd;
91 asection *s;
92 int i;
93 CORE_ADDR load_offset;
94 time_t start_time, end_time;
95 unsigned long data_count = 0;
96
97 /* enable user to specify address for downloading as 2nd arg to load */
98
99 i = sscanf (file, "%*s 0x%lx", &load_offset);
100 if (i >= 1)
101 {
102 char *p;
103
104 for (p = file; *p != '\000' && !isspace (*p); p++);
105
106 *p = '\000';
107 }
108 else
109 load_offset = 0;
110
111 abfd = bfd_openr (file, 0);
112 if (!abfd)
113 {
114 printf_filtered ("Unable to open file %s\n", file);
115 return;
116 }
117
118 if (bfd_check_format (abfd, bfd_object) == 0)
119 {
120 printf_filtered ("File is not an object file\n");
121 return;
122 }
123
124 start_time = time (NULL);
125
126 for (s = abfd->sections; s; s = s->next)
127 if (s->flags & SEC_LOAD)
128 {
129 bfd_size_type section_size;
130 bfd_vma vma;
131
132 vma = bfd_get_section_vma (abfd, s) + load_offset;
133 section_size = bfd_section_size (abfd, s);
134
135 data_count += section_size;
136
137 printf_filtered ("%s\t: 0x%4x .. 0x%4x ",
138 bfd_get_section_name (abfd, s), vma,
139 vma + section_size);
140 gdb_flush (gdb_stdout);
141
142 monitor_printf ("load c r %x %x\r", vma, section_size);
143
144 monitor_expect ("load: loading ", NULL, 0);
145 monitor_expect ("\r", NULL, 0);
146
147 for (i = 0; i < section_size; i += 2048)
148 {
149 int numbytes;
150 char buf[2048];
151
152 numbytes = min (sizeof buf, section_size - i);
153
154 bfd_get_section_contents (abfd, s, buf, i, numbytes);
155
156 SERIAL_WRITE (desc, buf, numbytes);
157
158 if (hashmark)
159 {
160 putchar_unfiltered ('#');
161 gdb_flush (gdb_stdout);
162 }
163 } /* Per-packet (or S-record) loop */
164
165 monitor_expect_prompt (NULL, 0);
166
167 putchar_unfiltered ('\n');
168 } /* Loadable sections */
169
170 monitor_printf ("reg pc %x\r", bfd_get_start_address (abfd));
171 monitor_expect_prompt (NULL, 0);
172 monitor_printf ("reg npc %x\r", bfd_get_start_address (abfd) + 4);
173 monitor_expect_prompt (NULL, 0);
174
175 monitor_printf ("run\r");
176
177 end_time = time (NULL);
178
179 if (hashmark)
180 putchar_unfiltered ('\n');
181
182 report_transfer_performance (data_count, start_time, end_time);
183
184 pop_target ();
185 push_remote_target (monitor_get_dev_name (), 1);
186
187 return_to_top_level (RETURN_QUIT);
188 }
189
190 /* Define the monitor command strings. Since these are passed directly
191 through to a printf style function, we may include formatting
192 strings. We also need a CR or LF on the end. */
193
194 /* need to pause the monitor for timing reasons, so slow it down */
195
196 static char *sparclet_inits[] =
197 {"\n\r\r\n", NULL};
198
199 static struct monitor_ops sparclet_cmds;
200
201 static void
202 init_sparclet_cmds (void)
203 {
204 sparclet_cmds.flags = MO_CLR_BREAK_USES_ADDR |
205 MO_HEX_PREFIX |
206 MO_NO_ECHO_ON_OPEN |
207 MO_NO_ECHO_ON_SETMEM |
208 MO_RUN_FIRST_TIME |
209 MO_GETMEM_READ_SINGLE; /* flags */
210 sparclet_cmds.init = sparclet_inits; /* Init strings */
211 sparclet_cmds.cont = "cont\r"; /* continue command */
212 sparclet_cmds.step = "step\r"; /* single step */
213 sparclet_cmds.stop = "\r"; /* break interrupts the program */
214 sparclet_cmds.set_break = "+bp %x\r"; /* set a breakpoint */
215 sparclet_cmds.clr_break = "-bp %x\r"; /* can't use "br" because only 2 hw bps are supported */
216 sparclet_cmds.clr_all_break = "-bp %x\r"; /* clear a breakpoint */
217 "-bp\r"; /* clear all breakpoints */
218 sparclet_cmds.fill = "fill %x -n %x -v %x -b\r"; /* fill (start length val) */
219 /* can't use "fi" because it takes words, not bytes */
220 /* ex [addr] [-n count] [-b|-s|-l] default: ex cur -n 1 -b */
221 sparclet_cmds.setmem.cmdb = "ex %x -b\r%x\rq\r"; /* setmem.cmdb (addr, value) */
222 sparclet_cmds.setmem.cmdw = "ex %x -s\r%x\rq\r"; /* setmem.cmdw (addr, value) */
223 sparclet_cmds.setmem.cmdl = "ex %x -l\r%x\rq\r"; /* setmem.cmdl (addr, value) */
224 sparclet_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
225 sparclet_cmds.setmem.resp_delim = NULL; /*": " *//* setmem.resp_delim */
226 sparclet_cmds.setmem.term = NULL; /*"? " *//* setmem.term */
227 sparclet_cmds.setmem.term_cmd = NULL; /*"q\r" *//* setmem.term_cmd */
228 /* since the parsing of multiple bytes is difficult due to
229 interspersed addresses, we'll only read 1 value at a time,
230 even tho these can handle a count */
231 /* we can use -n to set count to read, but may have to parse? */
232 sparclet_cmds.getmem.cmdb = "ex %x -n 1 -b\r"; /* getmem.cmdb (addr, #bytes) */
233 sparclet_cmds.getmem.cmdw = "ex %x -n 1 -s\r"; /* getmem.cmdw (addr, #swords) */
234 sparclet_cmds.getmem.cmdl = "ex %x -n 1 -l\r"; /* getmem.cmdl (addr, #words) */
235 sparclet_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, #dwords) */
236 sparclet_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
237 sparclet_cmds.getmem.term = NULL; /* getmem.term */
238 sparclet_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
239 sparclet_cmds.setreg.cmd = "reg %s 0x%x\r"; /* setreg.cmd (name, value) */
240 sparclet_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
241 sparclet_cmds.setreg.term = NULL; /* setreg.term */
242 sparclet_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
243 sparclet_cmds.getreg.cmd = "reg %s\r"; /* getreg.cmd (name) */
244 sparclet_cmds.getreg.resp_delim = " "; /* getreg.resp_delim */
245 sparclet_cmds.getreg.term = NULL; /* getreg.term */
246 sparclet_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
247 sparclet_cmds.dump_registers = "reg\r"; /* dump_registers */
248 sparclet_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\)"; /* register_pattern */
249 sparclet_cmds.supply_register = sparclet_supply_register; /* supply_register */
250 sparclet_cmds.load_routine = sparclet_load; /* load_routine */
251 sparclet_cmds.load = NULL; /* download command (srecs on console) */
252 sparclet_cmds.loadresp = NULL; /* load response */
253 sparclet_cmds.prompt = "monitor>"; /* monitor command prompt */
254 /* yikes! gdb core dumps without this delimitor!! */
255 sparclet_cmds.line_term = "\r"; /* end-of-command delimitor */
256 sparclet_cmds.cmd_end = NULL; /* optional command terminator */
257 sparclet_cmds.target = &sparclet_ops; /* target operations */
258 sparclet_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
259 sparclet_cmds.regnames = sparclet_regnames; /* registers names */
260 sparclet_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
261 };
262
263 static void
264 sparclet_open (args, from_tty)
265 char *args;
266 int from_tty;
267 {
268 monitor_open (args, &sparclet_cmds, from_tty);
269 }
270
271 void
272 _initialize_sparclet ()
273 {
274 int i;
275 init_sparclet_cmds ();
276
277 for (i = 0; i < NUM_REGS; i++)
278 if (sparclet_regnames[i][0] == 'c' ||
279 sparclet_regnames[i][0] == 'a')
280 sparclet_regnames[i] = 0; /* mon can't report c* or a* regs */
281
282 sparclet_regnames[0] = 0; /* mon won't report %G0 */
283
284 init_monitor_ops (&sparclet_ops);
285 sparclet_ops.to_shortname = "sparclet"; /* for the target command */
286 sparclet_ops.to_longname = "SPARC Sparclet monitor";
287 /* use SW breaks; target only supports 2 HW breakpoints */
288 sparclet_ops.to_insert_breakpoint = memory_insert_breakpoint;
289 sparclet_ops.to_remove_breakpoint = memory_remove_breakpoint;
290
291 sparclet_ops.to_doc =
292 "Use a board running the Sparclet debug monitor.\n\
293 Specify the serial device it is connected to (e.g. /dev/ttya).";
294
295 sparclet_ops.to_open = sparclet_open;
296 add_target (&sparclet_ops);
297 }