Patches for eCos: Dump literal pool on section change. Mark thumb function
[external/binutils.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, 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 */
29 #include <time.h>
30
31 extern void report_transfer_performance PARAMS ((unsigned long, time_t, time_t));
32
33 static struct target_ops sparclet_ops;
34
35 static void sparclet_open PARAMS ((char *args, int from_tty));
36
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".  */
41
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
54 pc:  0x12010000 0x00000000    unimp
55 npc: 0x12010004 0x00001000    unimp     0x1000
56 tbr: 0x00000000
57 y:   0x00000000
58 */
59 /* these correspond to the offsets from tm-* files from config directories */
60
61 /* is wim part of psr?? */
62 /* monitor wants lower case */
63 static char *sparclet_regnames[NUM_REGS] = REGISTER_NAMES;
64
65
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.  */
72
73 static void
74 sparclet_supply_register (regname, regnamelen, val, vallen)
75      char *regname;
76      int regnamelen;
77      char *val;
78      int vallen;
79 {
80   return;
81 }
82
83 static void
84 sparclet_load (desc, file, hashmark)
85      serial_t desc;
86      char *file;
87      int hashmark;
88 {
89   bfd *abfd;
90   asection *s;
91   int i;
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;
109
110   abfd = bfd_openr (file, 0);
111   if (!abfd)
112     {
113       printf_filtered ("Unable to open file %s\n", file);
114       return;
115     }
116
117   if (bfd_check_format (abfd, bfd_object) == 0)
118     {
119       printf_filtered ("File is not an object file\n");
120       return;
121     }
122   
123   start_time = time (NULL);
124
125   for (s = abfd->sections; s; s = s->next)
126     if (s->flags & SEC_LOAD)
127       {
128         bfd_size_type section_size;
129         bfd_vma vma;
130
131         vma = bfd_get_section_vma (abfd, s) + load_offset;
132         section_size = bfd_section_size (abfd, s);
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)
147           {
148             int numbytes;
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
157             if (hashmark)
158               {
159                 putchar_unfiltered ('#');
160                 gdb_flush (gdb_stdout);
161               }
162           }                     /* Per-packet (or S-record) loop */
163
164         monitor_expect_prompt (NULL, 0);
165
166         putchar_unfiltered ('\n');
167       }                         /* Loadable sections */
168
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);
173
174   monitor_printf ("run\r");
175
176   end_time = time (NULL);
177
178   if (hashmark) 
179     putchar_unfiltered ('\n');
180
181   report_transfer_performance (data_count, start_time, end_time);
182
183   pop_target ();
184   push_remote_target (monitor_get_dev_name (), 1);
185
186   return_to_top_level (RETURN_QUIT);
187 }
188
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
195 static char *sparclet_inits[] = {"\n\r\r\n", NULL};
196
197 static struct monitor_ops sparclet_cmds ;
198
199 static void 
200 init_sparclet_cmds(void)
201 {
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 */
252   /* yikes!  gdb core dumps without this delimitor!! */
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 */
259 };
260
261 static void
262 sparclet_open (args, from_tty)
263      char *args;
264      int from_tty;
265 {
266   monitor_open (args, &sparclet_cmds, from_tty);
267 }
268
269 void
270 _initialize_sparclet ()
271 {
272   int i;
273   init_sparclet_cmds() ;
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 */
279
280   sparclet_regnames[0] = 0;             /* mon won't report %G0 */
281
282   init_monitor_ops (&sparclet_ops);
283   sparclet_ops.to_shortname = "sparclet"; /* for the target command */
284   sparclet_ops.to_longname = "SPARC Sparclet monitor";
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; 
288
289   sparclet_ops.to_doc = 
290     "Use a board running the Sparclet debug monitor.\n\
291 Specify 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