Mon Feb 3 11:06:05 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
[external/binutils.git] / gdb / m32r-rom.c
1 /* Remote debugging interface to m32r ROM monitor for GDB, the GNU debugger.
2    Copyright 1996 Free Software Foundation, Inc.
3
4    Adapted by Michael Snyder of Cygnus Support.
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, Boston, MA 02111-1307, USA.  */
21
22 /* This module defines communication with the Mitsubishi m32r monitor */
23
24 #include "defs.h"
25 #include "gdbcore.h"
26 #include "target.h"
27 #include "monitor.h"
28 #include "serial.h"
29 #include "symtab.h"
30 #include "command.h"
31 #include "gdbcmd.h"
32 #include "symfile.h"    /* for generic load */
33 #include <time.h>       /* for time_t */
34 #include "gdb_string.h"
35
36 /*
37  * All this stuff just to get my host computer's IP address!
38  */
39 #include <netdb.h>      /* for hostent */
40 #include <netinet/in.h> /* for struct in_addr */
41 #if 1
42 #include <arpa/inet.h>  /* for inet_ntoa */
43 #endif
44
45 static char *board_addr;        /* user-settable IP address for M32R-EVA */
46 static char *server_addr;       /* user-settable IP address for gdb host */
47 static char *download_path;     /* user-settable path for SREC files     */
48
49
50 /* 
51  * Function: m32r_load_1 (helper function)
52  */
53
54 static void
55 m32r_load_section (abfd, s, data_count)
56      bfd      *abfd;
57      asection *s;
58      unsigned int *data_count;
59 {
60   if (s->flags & SEC_LOAD)
61     {
62       bfd_size_type section_size = bfd_section_size (abfd, s);
63       bfd_vma       section_base = bfd_section_vma  (abfd, s);
64       unsigned int  buffer, i;
65
66       *data_count += section_size;
67
68       printf_filtered ("Loading section %s, size 0x%lx vma ",
69                        bfd_section_name (abfd, s), section_size);
70       print_address_numeric (section_base, 1, gdb_stdout);
71       printf_filtered ("\n");
72       gdb_flush (gdb_stdout);
73       monitor_printf ("%x mw\r" , section_base);
74       for (i = 0; i < section_size; i += 4)
75         {
76           QUIT;
77           monitor_expect (" -> ", NULL, 0);
78           bfd_get_section_contents (abfd, s, (char *) &buffer, i, 4);
79           monitor_printf ("%x\n", buffer);
80         }
81       monitor_expect (" -> ", NULL, 0);
82       monitor_printf ("q\n");
83       monitor_expect_prompt (NULL, 0);
84     }
85 }
86
87 static int 
88 m32r_load_1 (dummy)
89      void *dummy;
90 {
91   int data_count = 0;
92
93   bfd_map_over_sections ((bfd *) dummy, m32r_load_section, &data_count);
94   return data_count;
95 }
96
97 /* 
98  * Function: m32r_load (an alternate way to load) 
99  */
100
101 static void
102 m32r_load (filename, from_tty) 
103     char *filename;
104     int from_tty;
105 {
106   extern int inferior_pid;
107   bfd *abfd;
108   asection *s;
109   unsigned int i, data_count = 0;
110   time_t start_time, end_time;  /* for timing of download */
111
112   if (filename == NULL || filename[0] == 0)
113     filename = get_exec_file (1);
114
115   abfd = bfd_openr (filename, 0);
116   if (!abfd)
117     error ("Unable to open file %s\n", filename);
118   if (bfd_check_format (abfd, bfd_object) == 0)
119     error ("File is not an object file\n");
120   start_time = time (NULL);
121 #if 0
122   for (s = abfd->sections; s; s = s->next)
123     if (s->flags & SEC_LOAD)
124       {
125         bfd_size_type section_size = bfd_section_size (abfd, s);
126         bfd_vma       section_base = bfd_section_vma  (abfd, s);
127         unsigned int  buffer;
128
129         data_count += section_size;
130
131         printf_filtered ("Loading section %s, size 0x%lx vma ",
132                          bfd_section_name (abfd, s), section_size);
133         print_address_numeric (section_base, 1, gdb_stdout);
134         printf_filtered ("\n");
135         gdb_flush (gdb_stdout);
136         monitor_printf ("%x mw\r" , section_base);
137         for (i = 0; i < section_size; i += 4)
138           {
139             monitor_expect (" -> ", NULL, 0);
140             bfd_get_section_contents (abfd, s, (char *) &buffer, i, 4);
141             monitor_printf ("%x\n", buffer);
142           }
143         monitor_expect (" -> ", NULL, 0);
144         monitor_printf ("q\n");
145         monitor_expect_prompt (NULL, 0);
146       }
147 #else
148   if (!(catch_errors (m32r_load_1, abfd, "Load aborted!\n", RETURN_MASK_ALL)))
149     {
150       monitor_printf ("q\n");
151       return;
152     }
153 #endif
154   end_time = time (NULL);
155   printf_filtered ("Start address 0x%lx\n", bfd_get_start_address (abfd));
156   report_transfer_performance (data_count, start_time, end_time);
157
158   /* Finally, make the PC point at the start address */
159   if (exec_bfd)
160     write_pc (bfd_get_start_address (exec_bfd));
161
162   inferior_pid = 0;             /* No process now */
163
164   /* This is necessary because many things were based on the PC at the
165      time that we attached to the monitor, which is no longer valid
166      now that we have loaded new code (and just changed the PC).
167      Another way to do this might be to call normal_stop, except that
168      the stack may not be valid, and things would get horribly
169      confused... */
170
171   clear_symtab_users ();
172 }
173
174 static void
175 m32r_load_gen (filename, from_tty) 
176     char *filename;
177     int from_tty;
178 {
179   generic_load (filename, from_tty);
180 }
181
182 static void m32r_open PARAMS ((char *args, int from_tty));
183
184 /* This array of registers needs to match the indexes used by GDB. The
185    whole reason this exists is because the various ROM monitors use
186    different names than GDB does, and don't support all the registers
187    either. So, typing "info reg sp" becomes an "A7". */
188
189 static char *m32r_regnames[] = 
190 { "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", 
191   "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15", 
192   "psw", "cbr", "spi", "spu", "bpc", "pc",  "accl", "acch", 
193 };
194
195 static void
196 m32r_supply_register (regname, regnamelen, val, vallen)
197      char *regname;
198      int regnamelen;
199      char *val;
200      int vallen;
201 {
202   int regno;
203   int num_regs = sizeof(m32r_regnames) / sizeof(m32r_regnames[0]);
204
205   for (regno = 0; regno < num_regs; regno++)
206     if (strncmp(regname, m32r_regnames[regno], regnamelen) == 0)
207       break;
208
209   if (regno >= num_regs)
210     return;             /* no match */
211
212   if (regno == ACCL_REGNUM)
213     { /* special handling for 64-bit acc reg */
214       monitor_supply_register (ACCH_REGNUM, val);
215       if (val = (char *) strchr(val, ':'))  /* skip past ':' to get 2nd word */
216         monitor_supply_register (ACCL_REGNUM, val + 1);
217     }
218   else
219     {
220       monitor_supply_register (regno, val);
221       if (regno == PSW_REGNUM)
222         {
223           unsigned long psw = strtoul (val, NULL, 16);
224           char *zero = "00000000", *one = "00000001";
225
226 #ifdef SM_REGNUM
227           /* Stack mode bit */
228           monitor_supply_register (SM_REGNUM, (psw & 0x80) ? one : zero);
229 #endif
230 #ifdef BSM_REGNUM
231           /* Backup stack mode bit */
232           monitor_supply_register (BSM_REGNUM, (psw & 0x8000) ? one : zero);
233 #endif
234 #ifdef IE_REGNUM
235           /* Interrupt enable bit */
236           monitor_supply_register (IE_REGNUM, (psw & 0x40) ? one : zero);
237 #endif
238 #ifdef BIE_REGNUM
239           /* Backup interrupt enable bit */
240           monitor_supply_register (BIE_REGNUM, (psw & 0x4000) ? one : zero);
241 #endif
242 #ifdef COND_REGNUM
243           /* Condition bit (carry etc.) */
244           monitor_supply_register (COND_REGNUM, (psw & 0x1) ? one : zero);
245 #endif
246 #ifdef CBR_REGNUM
247           monitor_supply_register (CBR_REGNUM, (psw & 0x1) ? one : zero);
248 #endif
249 #ifdef BPC_REGNUM
250           monitor_supply_register (BPC_REGNUM, zero); /* KLUDGE:   (???????) */
251 #endif
252 #ifdef BCARRY_REGNUM
253           monitor_supply_register (BCARRY_REGNUM, zero); /* KLUDGE: (??????) */
254 #endif
255         }         
256
257       if (regno == SPI_REGNUM || regno == SPU_REGNUM)   
258         { /* special handling for stack pointer (spu or spi) */
259           unsigned long stackmode = read_register (PSW_REGNUM) & 0x80;
260
261           if (regno == SPI_REGNUM && !stackmode)        /* SP == SPI */
262             monitor_supply_register (SP_REGNUM, val);
263           else if (regno == SPU_REGNUM && stackmode)    /* SP == SPU */
264             monitor_supply_register (SP_REGNUM, val);
265         }
266     }
267 }
268
269 static struct target_ops m32r_ops;
270
271 static char *m32r_inits[] = {"\r", NULL};
272
273 static struct monitor_ops m32r_cmds =
274 {
275   MO_CLR_BREAK_USES_ADDR | MO_REGISTER_VALUE_FIRST,
276   m32r_inits,                   /* Init strings */
277   "go\r",                       /* continue command */
278   "step\r",                     /* single step */
279   NULL,                         /* interrupt command */
280   "%x +bp\r",                   /* set a breakpoint */
281   "%x -bp\r",                   /* clear a breakpoint */
282   "bpoff\r",                    /* clear all breakpoints */
283   "%x %x %x fill\r",            /* fill (start length val) */
284   {
285     "%x 1 %x fill\r",           /* setmem.cmdb (addr, value) */
286     "%x 1 %x fillh\r",          /* setmem.cmdw (addr, value) */
287     "%x 1 %x fillw\r",          /* setmem.cmdl (addr, value) */
288     NULL,                       /* setmem.cmdll (addr, value) */
289     NULL,                       /* setmem.resp_delim */
290     NULL,                       /* setmem.term */
291     NULL                        /* setmem.term_cmd */
292   },
293   {
294     "%x %x dump\r",             /* getmem.cmdb (addr, len) */
295     NULL,                       /* getmem.cmdw (addr, len) */
296     NULL,                       /* getmem.cmdl (addr, len) */
297     NULL,                       /* getmem.cmdll (addr, len) */
298     ": ",                       /* getmem.resp_delim */
299     NULL,                       /* getmem.term */
300     NULL                        /* getmem.term_cmd */
301   },
302   {
303     "%x to %%%s\r",             /* setreg.cmd (name, value) */
304     NULL,                       /* setreg.resp_delim */
305     NULL,                       /* setreg.term */
306     NULL                        /* setreg.term_cmd */
307   },
308   {
309     NULL,                       /* getreg.cmd (name) */
310     NULL,                       /* getreg.resp_delim */
311     NULL,                       /* getreg.term */
312     NULL                        /* getreg.term_cmd */
313   },
314   ".reg\r",                     /* dump_registers */
315   "\\(\\w+\\) += \\([0-9a-fA-F]+\\b\\)", /* register_pattern */
316   m32r_supply_register,         /* supply_register */
317   NULL,                         /* load_routine (defaults to SRECs) */
318   NULL,                         /* download command */
319   NULL,                         /* load response */
320   "ok ",                        /* monitor command prompt */
321   "\r",                         /* end-of-line terminator */
322   NULL,                         /* optional command terminator */
323   &m32r_ops,                    /* target operations */
324   SERIAL_1_STOPBITS,            /* number of stop bits */
325   m32r_regnames,                /* registers names */
326   MONITOR_OPS_MAGIC             /* magic */
327   };
328
329 static void
330 m32r_open(args, from_tty)
331      char *args;
332      int from_tty;
333 {
334   monitor_open (args, &m32r_cmds, from_tty);
335 }
336
337 /* Function: set_board_address
338    Tell the BootOne monitor what it's ethernet IP address is. */
339
340 static void
341 m32r_set_board_address (args, from_tty)
342      char *args;
343      int  from_tty;
344 {
345   int resp_len;
346   char buf[1024];
347
348   if (args && *args)
349     {
350       monitor_printf ("ulip %s\n", args);
351       resp_len = monitor_expect_prompt (buf, sizeof(buf));
352       /* now parse the result for success */
353     }
354   else
355     error ("Requires argument (IP address for M32R-EVA board)");
356 }
357
358 /* Function: set_server_address
359    Tell the BootOne monitor what gdb's ethernet IP address is. */
360
361 static void
362 m32r_set_server_address (args, from_tty)
363      char *args;
364      int  from_tty;
365 {
366   int resp_len;
367   char buf[1024];
368
369   if (args && *args)
370     {
371       monitor_printf ("uhip %s\n", args);
372       resp_len = monitor_expect_prompt (buf, sizeof(buf));
373       /* now parse the result for success */
374     }
375   else
376     error ("Requires argument (IP address of GDB's host computer)");
377 }
378
379 /* Function: set_download_path
380    Tell the BootOne monitor the default path for downloadable SREC files. */
381
382 static void
383 m32r_set_download_path (args, from_tty)
384      char *args;
385      int  from_tty;
386 {
387   int resp_len;
388   char buf[1024];
389
390   if (args && *args)
391     {
392       monitor_printf ("up %s\n", args);
393       resp_len = monitor_expect_prompt (buf, sizeof(buf));
394       /* now parse the result for success */
395     }
396   else
397     error ("Requires argument (default path for downloadable SREC files)");
398 }
399
400 static void
401 m32r_upload_command (args, from_tty)
402      char *args;
403      int from_tty;
404 {
405   bfd *abfd;
406   asection *s;
407   time_t start_time, end_time;  /* for timing of download */
408   extern int inferior_pid;
409   int resp_len, data_count = 0;
410   char buf[1024];
411   struct hostent *hostent;
412   struct in_addr inet_addr;
413
414   /* first check to see if there's an ethernet port! */
415   monitor_printf ("ust\r");
416   resp_len = monitor_expect_prompt (buf, sizeof(buf));
417   if (!strchr (buf, ':'))
418     error ("No ethernet connection!");
419
420   if (board_addr == 0)
421     {
422       /* scan second colon in the output from the "ust" command */
423       char * myIPaddress = strchr (strchr (buf, ':') + 1, ':') + 1;
424
425       while (isspace(*myIPaddress))
426         myIPaddress++;
427
428       if (!strncmp (myIPaddress, "0.0.", 4))    /* empty */
429         error ("Please use 'set board-address' to set the M32R-EVA board's IP address.");
430       if (strchr (myIPaddress, '('))
431         *(strchr (myIPaddress, '(')) = '\0';    /* delete trailing junk */
432       board_addr = strsave (myIPaddress);
433     }
434   if (server_addr == 0)
435     {
436       buf[0] = 0;
437       gethostname (buf, sizeof(buf));
438       if (buf[0] != 0)
439         hostent = gethostbyname (buf);
440       if (hostent != 0)
441         {
442 #if 1
443           memcpy (&inet_addr.s_addr, hostent->h_addr, 
444                   sizeof(inet_addr.s_addr));
445           server_addr = (char *) inet_ntoa (inet_addr);
446 #else
447           server_addr = (char *) inet_ntoa (hostent->h_addr);
448 #endif
449         }
450       if (server_addr == 0)     /* failed? */
451         error ("Need to know gdb host computer's IP address (use 'set server-address')");
452     }
453
454   if (args == 0 || args[0] == 0)        /* no args: upload the current file */
455     args = get_exec_file (1);
456
457   if (args[0] != '/' && download_path == 0)
458     if (current_directory)
459       download_path = strsave (current_directory);
460     else
461       error ("Need to know default download path (use 'set download-path')");
462
463   start_time = time (NULL);
464   monitor_printf ("uhip %s\r", server_addr);
465   resp_len = monitor_expect_prompt (buf, sizeof(buf));  /* parse result? */
466   monitor_printf ("ulip %s\r", board_addr);
467   resp_len = monitor_expect_prompt (buf, sizeof(buf));  /* parse result? */
468   if (args[0] != '/')
469     monitor_printf ("up %s\r", download_path);  /* use default path */
470   else
471     monitor_printf ("up\r");                    /* rooted filename/path */
472   resp_len = monitor_expect_prompt (buf, sizeof(buf));  /* parse result? */
473
474   if (strrchr (args, '.') && !strcmp (strrchr (args, '.'), ".srec"))
475     monitor_printf ("ul %s\r", args);
476   else                                  /* add ".srec" suffix */
477     monitor_printf ("ul %s.srec\r", args);
478   resp_len = monitor_expect_prompt (buf, sizeof(buf));  /* parse result? */
479
480   if (buf[0] == 0 || strstr(buf, "complete") == 0)
481     error("Upload file not found: %s.srec\nCheck IP addresses and download path.", args);
482   else
483     printf_filtered (" -- Ethernet load complete.\n");
484
485   end_time = time (NULL);
486   if (abfd = bfd_openr (args, 0))
487     { /* Download is done -- print section statistics */
488       if (bfd_check_format (abfd, bfd_object) == 0)
489         {
490           printf_filtered ("File is not an object file\n");
491         }
492       for (s = abfd->sections; s; s = s->next)
493         if (s->flags & SEC_LOAD)
494           {
495             bfd_size_type section_size = bfd_section_size (abfd, s);
496             bfd_vma       section_base = bfd_section_vma  (abfd, s);
497             unsigned int  buffer;
498
499             data_count += section_size;
500
501             printf_filtered ("Loading section %s, size 0x%lx vma ",
502                              bfd_section_name (abfd, s), section_size);
503             print_address_numeric (section_base, 1, gdb_stdout);
504             printf_filtered ("\n");
505             gdb_flush (gdb_stdout);
506           }
507       /* Finally, make the PC point at the start address */
508       write_pc (bfd_get_start_address (abfd));
509       report_transfer_performance (data_count, start_time, end_time);
510       printf_filtered ("Start address 0x%lx\n", bfd_get_start_address (abfd));
511     }
512   inferior_pid = 0;             /* No process now */
513
514   /* This is necessary because many things were based on the PC at the
515      time that we attached to the monitor, which is no longer valid
516      now that we have loaded new code (and just changed the PC).
517      Another way to do this might be to call normal_stop, except that
518      the stack may not be valid, and things would get horribly
519      confused... */
520
521   clear_symtab_users ();
522 }
523
524 void
525 _initialize_m32r_rom ()
526 {
527   init_monitor_ops (&m32r_ops);
528
529   m32r_ops.to_shortname = "m32r";
530   m32r_ops.to_longname = "m32r monitor";
531   m32r_ops.to_load = m32r_load_gen;     /* monitor lacks a download command */
532   m32r_ops.to_doc = "Debug via the m32r monitor.\n\
533 Specify the serial device it is connected to (e.g. /dev/ttya).";
534   m32r_ops.to_open = m32r_open;
535
536   add_show_from_set
537     (add_set_cmd ("download-path", class_obscure, var_string,
538                   (char *) &download_path,
539                   "Set the default path for downloadable SREC files.",
540                   &setlist),
541      &showlist);
542
543   add_show_from_set
544     (add_set_cmd ("board-address", class_obscure, var_string,
545                   (char *) &board_addr,
546                   "Set IP address for M32R-EVA target board.",
547                   &setlist),
548      &showlist);
549
550   add_show_from_set
551     (add_set_cmd ("server-address", class_obscure, var_string,
552                   (char *) &server_addr,
553                   "Set IP address for download server (GDB's host computer).",
554                   &setlist),
555      &showlist);
556
557   add_com ("upload", class_obscure, m32r_upload_command,
558            "Upload the srec file via the monitor's Ethernet upload capability."); 
559
560   add_com ("tload", class_obscure, m32r_load, "test upload command.");
561
562   add_target (&m32r_ops);
563 }