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