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