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