]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/sparclet-rom.c
PARAMS removal.
[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 (unsigned long, time_t, time_t);
33
34 static struct target_ops sparclet_ops;
35
36 static void sparclet_open (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[] = {
65 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
66 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
67 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
68 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
69
70 "", "", "", "", "", "", "", "", /* no FPU regs */
71 "", "", "", "", "", "", "", "",
72 "", "", "", "", "", "", "", "",
73 "", "", "", "", "", "", "", "",
74 /* no CPSR, FPSR */
75 "y", "psr", "wim", "tbr", "pc", "npc", "", "",
76
77 "ccsr", "ccpr", "cccrcr", "ccor", "ccobr", "ccibr", "ccir", "",
78
79 /* ASR15 ASR19 (don't display them) */
80 "asr1", "", "asr17", "asr18", "", "asr20", "asr21", "asr22",
81 /*
82 "awr0", "awr1", "awr2", "awr3", "awr4", "awr5", "awr6", "awr7",
83 "awr8", "awr9", "awr10", "awr11", "awr12", "awr13", "awr14", "awr15",
84 "awr16", "awr17", "awr18", "awr19", "awr20", "awr21", "awr22", "awr23",
85 "awr24", "awr25", "awr26", "awr27", "awr28", "awr29", "awr30", "awr31",
86 "apsr",
87 */
88 };
89
90
91
92 /* Function: sparclet_supply_register
93 Just returns with no action.
94 This function is required, because parse_register_dump (monitor.c)
95 expects to be able to call it. If we don't supply something, it will
96 call a null pointer and core-dump. Since this function does not
97 actually do anything, GDB will request the registers individually. */
98
99 static void
100 sparclet_supply_register (regname, regnamelen, val, vallen)
101 char *regname;
102 int regnamelen;
103 char *val;
104 int vallen;
105 {
106 return;
107 }
108
109 static void
110 sparclet_load (desc, file, hashmark)
111 serial_t desc;
112 char *file;
113 int hashmark;
114 {
115 bfd *abfd;
116 asection *s;
117 int i;
118 CORE_ADDR load_offset;
119 time_t start_time, end_time;
120 unsigned long data_count = 0;
121
122 /* enable user to specify address for downloading as 2nd arg to load */
123
124 i = sscanf (file, "%*s 0x%lx", &load_offset);
125 if (i >= 1)
126 {
127 char *p;
128
129 for (p = file; *p != '\000' && !isspace (*p); p++);
130
131 *p = '\000';
132 }
133 else
134 load_offset = 0;
135
136 abfd = bfd_openr (file, 0);
137 if (!abfd)
138 {
139 printf_filtered ("Unable to open file %s\n", file);
140 return;
141 }
142
143 if (bfd_check_format (abfd, bfd_object) == 0)
144 {
145 printf_filtered ("File is not an object file\n");
146 return;
147 }
148
149 start_time = time (NULL);
150
151 for (s = abfd->sections; s; s = s->next)
152 if (s->flags & SEC_LOAD)
153 {
154 bfd_size_type section_size;
155 bfd_vma vma;
156
157 vma = bfd_get_section_vma (abfd, s) + load_offset;
158 section_size = bfd_section_size (abfd, s);
159
160 data_count += section_size;
161
162 printf_filtered ("%s\t: 0x%4x .. 0x%4x ",
163 bfd_get_section_name (abfd, s), vma,
164 vma + section_size);
165 gdb_flush (gdb_stdout);
166
167 monitor_printf ("load c r %x %x\r", vma, section_size);
168
169 monitor_expect ("load: loading ", NULL, 0);
170 monitor_expect ("\r", NULL, 0);
171
172 for (i = 0; i < section_size; i += 2048)
173 {
174 int numbytes;
175 char buf[2048];
176
177 numbytes = min (sizeof buf, section_size - i);
178
179 bfd_get_section_contents (abfd, s, buf, i, numbytes);
180
181 SERIAL_WRITE (desc, buf, numbytes);
182
183 if (hashmark)
184 {
185 putchar_unfiltered ('#');
186 gdb_flush (gdb_stdout);
187 }
188 } /* Per-packet (or S-record) loop */
189
190 monitor_expect_prompt (NULL, 0);
191
192 putchar_unfiltered ('\n');
193 } /* Loadable sections */
194
195 monitor_printf ("reg pc %x\r", bfd_get_start_address (abfd));
196 monitor_expect_prompt (NULL, 0);
197 monitor_printf ("reg npc %x\r", bfd_get_start_address (abfd) + 4);
198 monitor_expect_prompt (NULL, 0);
199
200 monitor_printf ("run\r");
201
202 end_time = time (NULL);
203
204 if (hashmark)
205 putchar_unfiltered ('\n');
206
207 report_transfer_performance (data_count, start_time, end_time);
208
209 pop_target ();
210 push_remote_target (monitor_get_dev_name (), 1);
211
212 return_to_top_level (RETURN_QUIT);
213 }
214
215 /* Define the monitor command strings. Since these are passed directly
216 through to a printf style function, we may include formatting
217 strings. We also need a CR or LF on the end. */
218
219 /* need to pause the monitor for timing reasons, so slow it down */
220
221 static char *sparclet_inits[] =
222 {"\n\r\r\n", NULL};
223
224 static struct monitor_ops sparclet_cmds;
225
226 static void
227 init_sparclet_cmds (void)
228 {
229 sparclet_cmds.flags = MO_CLR_BREAK_USES_ADDR |
230 MO_HEX_PREFIX |
231 MO_NO_ECHO_ON_OPEN |
232 MO_NO_ECHO_ON_SETMEM |
233 MO_RUN_FIRST_TIME |
234 MO_GETMEM_READ_SINGLE; /* flags */
235 sparclet_cmds.init = sparclet_inits; /* Init strings */
236 sparclet_cmds.cont = "cont\r"; /* continue command */
237 sparclet_cmds.step = "step\r"; /* single step */
238 sparclet_cmds.stop = "\r"; /* break interrupts the program */
239 sparclet_cmds.set_break = "+bp %x\r"; /* set a breakpoint */
240 sparclet_cmds.clr_break = "-bp %x\r"; /* can't use "br" because only 2 hw bps are supported */
241 sparclet_cmds.clr_all_break = "-bp %x\r"; /* clear a breakpoint */
242 "-bp\r"; /* clear all breakpoints */
243 sparclet_cmds.fill = "fill %x -n %x -v %x -b\r"; /* fill (start length val) */
244 /* can't use "fi" because it takes words, not bytes */
245 /* ex [addr] [-n count] [-b|-s|-l] default: ex cur -n 1 -b */
246 sparclet_cmds.setmem.cmdb = "ex %x -b\r%x\rq\r"; /* setmem.cmdb (addr, value) */
247 sparclet_cmds.setmem.cmdw = "ex %x -s\r%x\rq\r"; /* setmem.cmdw (addr, value) */
248 sparclet_cmds.setmem.cmdl = "ex %x -l\r%x\rq\r"; /* setmem.cmdl (addr, value) */
249 sparclet_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
250 sparclet_cmds.setmem.resp_delim = NULL; /*": " *//* setmem.resp_delim */
251 sparclet_cmds.setmem.term = NULL; /*"? " *//* setmem.term */
252 sparclet_cmds.setmem.term_cmd = NULL; /*"q\r" *//* setmem.term_cmd */
253 /* since the parsing of multiple bytes is difficult due to
254 interspersed addresses, we'll only read 1 value at a time,
255 even tho these can handle a count */
256 /* we can use -n to set count to read, but may have to parse? */
257 sparclet_cmds.getmem.cmdb = "ex %x -n 1 -b\r"; /* getmem.cmdb (addr, #bytes) */
258 sparclet_cmds.getmem.cmdw = "ex %x -n 1 -s\r"; /* getmem.cmdw (addr, #swords) */
259 sparclet_cmds.getmem.cmdl = "ex %x -n 1 -l\r"; /* getmem.cmdl (addr, #words) */
260 sparclet_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, #dwords) */
261 sparclet_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
262 sparclet_cmds.getmem.term = NULL; /* getmem.term */
263 sparclet_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
264 sparclet_cmds.setreg.cmd = "reg %s 0x%x\r"; /* setreg.cmd (name, value) */
265 sparclet_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
266 sparclet_cmds.setreg.term = NULL; /* setreg.term */
267 sparclet_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
268 sparclet_cmds.getreg.cmd = "reg %s\r"; /* getreg.cmd (name) */
269 sparclet_cmds.getreg.resp_delim = " "; /* getreg.resp_delim */
270 sparclet_cmds.getreg.term = NULL; /* getreg.term */
271 sparclet_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
272 sparclet_cmds.dump_registers = "reg\r"; /* dump_registers */
273 sparclet_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\)"; /* register_pattern */
274 sparclet_cmds.supply_register = sparclet_supply_register; /* supply_register */
275 sparclet_cmds.load_routine = sparclet_load; /* load_routine */
276 sparclet_cmds.load = NULL; /* download command (srecs on console) */
277 sparclet_cmds.loadresp = NULL; /* load response */
278 sparclet_cmds.prompt = "monitor>"; /* monitor command prompt */
279 /* yikes! gdb core dumps without this delimitor!! */
280 sparclet_cmds.line_term = "\r"; /* end-of-command delimitor */
281 sparclet_cmds.cmd_end = NULL; /* optional command terminator */
282 sparclet_cmds.target = &sparclet_ops; /* target operations */
283 sparclet_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
284 sparclet_cmds.regnames = sparclet_regnames; /* registers names */
285 sparclet_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
286 };
287
288 static void
289 sparclet_open (args, from_tty)
290 char *args;
291 int from_tty;
292 {
293 monitor_open (args, &sparclet_cmds, from_tty);
294 }
295
296 void
297 _initialize_sparclet ()
298 {
299 int i;
300 init_sparclet_cmds ();
301
302 for (i = 0; i < NUM_REGS; i++)
303 if (sparclet_regnames[i][0] == 'c' ||
304 sparclet_regnames[i][0] == 'a')
305 sparclet_regnames[i] = 0; /* mon can't report c* or a* regs */
306
307 sparclet_regnames[0] = 0; /* mon won't report %G0 */
308
309 init_monitor_ops (&sparclet_ops);
310 sparclet_ops.to_shortname = "sparclet"; /* for the target command */
311 sparclet_ops.to_longname = "SPARC Sparclet monitor";
312 /* use SW breaks; target only supports 2 HW breakpoints */
313 sparclet_ops.to_insert_breakpoint = memory_insert_breakpoint;
314 sparclet_ops.to_remove_breakpoint = memory_remove_breakpoint;
315
316 sparclet_ops.to_doc =
317 "Use a board running the Sparclet debug monitor.\n\
318 Specify the serial device it is connected to (e.g. /dev/ttya).";
319
320 sparclet_ops.to_open = sparclet_open;
321 add_target (&sparclet_ops);
322 }