* monitor.c: Move all xmodem stuff into xmodem.[ch]. Remove
[external/binutils.git] / gdb / w89k-rom.c
1 /* Remote target glue for the WinBond ROM monitor running on the "Cougar"
2    W89k eval board.
3
4    Copyright 1988, 1991, 1992, 1993, 1994 Free 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "target.h"
25 #include "monitor.h"
26 #include "serial.h"
27 #include "xmodem.h"
28
29 static void w89k_open PARAMS ((char *args, int from_tty));
30
31 /*
32  * this array of registers need to match the indexes used by GDB. The
33  * whole reason this exists is cause the various ROM monitors use
34  * different strings than GDB does, and doesn't support all the
35  * registers either. So, typing "info reg sp" becomes a "r30".
36  */
37 static char *w89k_regnames[NUM_REGS] =
38 {
39   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
40   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
41   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
42   "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
43   "SAR", "PC", NULL, NULL, NULL, "EIEM", "IIR", "IVA",
44   "IOR", "IPSW", NULL, NULL, NULL, NULL, NULL,
45   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
46   "CCR", NULL, NULL, "TR0", "TR1",
47 };
48
49 static void
50 w89k_supply_register (regname, regnamelen, val, vallen)
51      char *regname;
52      int regnamelen;
53      char *val;
54      int vallen;
55 {
56   int numregs;
57   int regno;
58
59   numregs = 1;
60   regno = -1;
61
62   if (regnamelen == 2)
63     switch (regname[0])
64       {
65       case 'r':
66         numregs = 4;
67         switch (regname[1])
68           {
69           case '0':
70             regno = R0_REGNUM;
71             break;
72           case '4':
73             regno = R0_REGNUM + 4;
74             break;
75           case '8':
76             regno = R0_REGNUM + 8;
77             break;
78           }
79         break;
80       case 'P':
81         if (regname[1] == 'C')
82           regno = PC_REGNUM;
83         break;
84       }
85   else if (regnamelen == 3)
86     switch (regname[0])
87       {
88       case 'r':
89         numregs = 4;
90         if (regname[1] == '1' && regname[2] == '2')
91           regno = R0_REGNUM + 12;
92         else if (regname[1] == '1' && regname[2] == '6')
93           regno = R0_REGNUM + 16;
94         else if (regname[1] == '2' && regname[2] == '0')
95           regno = R0_REGNUM + 20;
96         else if (regname[1] == '2' && regname[2] == '4')
97           regno = R0_REGNUM + 24;
98         else if (regname[1] == '2' && regname[2] == '8')
99           regno = R0_REGNUM + 28;
100         break;
101       case 'R':
102         if (regname[1] == 'C' && regname[2] == 'R')
103           regno = RCR_REGNUM;
104         break;
105       case 'C':
106         if (regname[1] == 'C' && regname[2] == 'R')
107           regno = CCR_REGNUM;
108         break;
109       case 'S':
110         if (regname[1] == 'A' && regname[2] == 'R')
111           regno = SAR_REGNUM;
112         break;
113       case 'I':
114         if (regname[1] == 'I' && regname[2] == 'R')
115           regno = IIR_REGNUM;
116         else if (regname[1] == 'O' && regname[2] == 'R')
117           regno = IOR_REGNUM;
118         break;
119       case 'T':
120         numregs = 4;
121         if (regname[1] == 'R')
122           if (regname[2] == '0')
123             regno = TR0_REGNUM;
124           else if (regname[2] == '4')
125             regno = TR0_REGNUM + 4;
126         break;
127       }
128   else if (regnamelen == 4)
129     switch (regname[0])
130       {
131       case 'E':
132         if (regname[1] == 'I')
133           if (regname[2] == 'E' && regname[3] == 'M')
134             regno = EIEM_REGNUM;
135         break;
136       case 'I':
137         if (regname[1] == 'P' && regname[2] == 'S' && regname[3] == 'W')
138           regno = IPSW_REGNUM;
139         break;
140       }
141   else if (regnamelen == 5)
142     switch (regname[0])
143       {
144       case 'I':
145         if (regname[1] == 'A'
146             && regname[2] == 'O'
147             && regname[3] == 'Q'
148             && regname[4] == 'B')
149           regno = PCOQ_TAIL_REGNUM;
150         break;
151       }
152
153   if (regno >= 0)
154     while (numregs-- > 0)
155       val = monitor_supply_register (regno++, val);
156 }
157
158 static int hashmark = 1;        /* flag set by "set hash" */
159
160 extern struct monitor_ops w89k_cmds; /* fwd decl */
161
162 static void
163 w89k_load (desc, file, hashmark)
164      serial_t desc;
165      char *file;
166      int hashmark;
167 {
168   bfd *abfd;
169   asection *s;
170   char *buffer;
171   int i;
172
173   buffer = alloca (XMODEM_PACKETSIZE);
174
175   abfd = bfd_openr (file, 0);
176   if (!abfd)
177     {
178       printf_filtered ("Unable to open file %s\n", file);
179       return;
180     }
181
182   if (bfd_check_format (abfd, bfd_object) == 0)
183     {
184       printf_filtered ("File is not an object file\n");
185       return;
186     }
187   
188   for (s = abfd->sections; s; s = s->next)
189     if (s->flags & SEC_LOAD)
190       {
191         bfd_size_type section_size;
192
193         printf_filtered ("%s\t: 0x%4x .. 0x%4x  ", s->name, s->vma,
194                          s->vma + s->_raw_size);
195         gdb_flush (gdb_stdout);
196
197         monitor_printf (w89k_cmds.load, s->vma);
198         if (w89k_cmds.loadresp)
199           monitor_expect (w89k_cmds.loadresp, NULL, 0);
200
201         xmodem_init_xfer (desc);
202
203         section_size = bfd_section_size (abfd, s);
204
205         for (i = 0; i < section_size; i += XMODEM_DATASIZE)
206           {
207             int numbytes;
208
209             numbytes = min (XMODEM_DATASIZE, section_size - i);
210
211             bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i,
212                                       numbytes);
213
214             xmodem_send_packet (desc, buffer, numbytes, hashmark);
215
216             if (hashmark)
217               {
218                 putchar_unfiltered ('#');
219                 gdb_flush (gdb_stdout);
220               }
221           }                     /* Per-packet (or S-record) loop */
222
223         xmodem_finish_xfer (desc);
224
225         monitor_expect_prompt (NULL, 0);
226
227         putchar_unfiltered ('\n');
228       }                         /* Loadable sections */
229   
230   if (hashmark) 
231     putchar_unfiltered ('\n');
232 }
233
234 /*
235  * Define the monitor command strings. Since these are passed directly
236  * through to a printf style function, we need can include formatting
237  * strings. We also need a CR or LF on the end.
238  */
239
240 static struct target_ops w89k_ops;
241
242 static char *w89k_loadtypes[] = {"binary", NULL};
243 static char *w89k_loadprotos[] = {"xmodem", NULL};
244
245 static char *w89k_inits[] = {"\r", NULL};
246
247 static struct monitor_ops w89k_cmds =
248 {
249   MO_GETMEM_NEEDS_RANGE|MO_FILL_USES_ADDR, /* flags */
250   w89k_inits,                   /* Init strings */
251   "g\r",                        /* continue command */
252   "t\r",                        /* single step */
253   NULL,                         /* Interrupt char */
254   "bp %x\r",                    /* set a breakpoint */
255   "bc %x\r",                    /* clear a breakpoint */
256   "bc *\r",                     /* clear all breakpoints */
257   "f %x %x %x\r",               /* memory fill cmd */
258   {
259     "eb %x %x\r",               /* setmem.cmdb (addr, value) */
260     "eh %x %x\r",               /* setmem.cmdw (addr, value) */
261     "ew %x %x\r",               /* setmem.cmdl (addr, value) */
262     NULL,                       /* setmem.cmdll (addr, value) */
263     NULL,                       /* setreg.resp_delim */
264     NULL,                       /* setreg.term */
265     NULL,                       /* setreg.term_cmd */
266   },
267   {
268     "db %x %x\r",               /* getmem.cmdb (startaddr, endaddr) */
269     "dh %x %x\r",               /* getmem.cmdw (startaddr, endaddr) */
270     "dw %x %x\r",               /* getmem.cmdl (startaddr, endaddr) */
271     NULL,                       /* getmem.cmdll (startaddr, endaddr) */
272     "  ",                       /* getmem.resp_delim */
273     NULL,                       /* getmem.term */
274     NULL,                       /* getmem.term_cmd */
275   },
276   {
277     "r %s %x\r",                /* setreg.cmd (name, value) */
278     NULL,                       /* setreg.resp_delim */
279     NULL,                       /* setreg.term */
280     NULL,                       /* setreg.term_cmd */
281   },
282   {
283     "r %s\r",                   /* getreg.cmd (name) */
284     "\r",                       /* getreg.resp_delim */
285     NULL,                       /* getreg.term */
286     NULL,                       /* getreg.term_cmd */
287   },
288   "r\r",                        /* dump_registers */
289   "\\(\\w+\\)\\( +[0-9a-fA-F]+\\b\\)+",
290   w89k_supply_register,         /* supply_register */
291   w89k_load,                    /* load routine */
292   "u %x\r",                     /* download command */
293   "\r",                         /* load response */
294   "ROM>",                       /* monitor command prompt */
295   NULL,                         /* end-of-command delimitor */
296   NULL,                         /* optional command terminator */
297   &w89k_ops,                    /* target operations */
298   w89k_loadtypes,               /* loadtypes */
299   w89k_loadprotos,              /* loadprotos */
300   "9600",                       /* supported baud rates */
301   SERIAL_1_STOPBITS,            /* number of stop bits */
302   w89k_regnames,                /* register names */
303   MONITOR_OPS_MAGIC             /* magic */
304   };
305
306 void
307 w89k_open(args, from_tty)
308      char *args;
309      int from_tty;
310 {
311   monitor_open (args, &w89k_cmds, from_tty);
312 }
313
314 void
315 _initialize_w89k ()
316 {
317   init_monitor_ops (&w89k_ops);
318
319   w89k_ops.to_shortname = "w89k";
320   w89k_ops.to_longname = "WinBond's debug monitor for the W89k Eval board";
321   w89k_ops.to_doc = "Debug on a WinBond W89K eval board.\n\
322 Specify the serial device it is connected to (e.g. /dev/ttya).";
323   w89k_ops.to_open = w89k_open;
324
325   add_target (&w89k_ops);
326 }