Mon Feb 3 11:06:05 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
authorMichael Snyder <msnyder@vmware.com>
Mon, 3 Feb 1997 19:18:32 +0000 (19:18 +0000)
committerMichael Snyder <msnyder@vmware.com>
Mon, 3 Feb 1997 19:18:32 +0000 (19:18 +0000)
        * m32r-stub.c: New -- remote protocol support for M32R cpu.
        * m32r-rom.c:  Several experiments with improved download time.
        * .Sanitize:   Add entry for m32r-stub.c

gdb/.Sanitize
gdb/ChangeLog
gdb/m32r-rom.c [new file with mode: 0644]

index fd32ab0e43e7c938d49d07b2380c9f0fef380890..1425e499aa477d5553890e1396a5fd384927fa81 100644 (file)
@@ -102,7 +102,7 @@ else
        fi
 fi
 
-m32r_files="m32r-tdep.c m32r-rom.c"
+m32r_files="m32r-tdep.c m32r-rom.c m32r-stub.c"
 
 if ( echo $* | grep keep\-m32r > /dev/null ) ; then
        keep_these_too="${m32r_files} ${keep_these_too}"
index 54c7b53906d0bb49fe49a5299d091cea443c1f26..77275c2cfe0c7548fe76d30157db2129b6960078 100644 (file)
@@ -1,3 +1,11 @@
+start-sanitize-m32r
+Mon Feb  3 11:06:05 1997  Michael Snyder  <msnyder@cleaver.cygnus.com>
+
+       * m32r-stub.c: New -- remote protocol support for M32R cpu.
+       * m32r-rom.c:  Several experiments with improved download time.
+       * .Sanitize:   Add entry for m32r-stub.c
+end-sanitize-m32r
+
 Fri Jan 31 08:26:39 1997  Mark Alexander  <marka@cygnus.com>
 
        * mips-tdep.c (MIPS16_INSTLEN): Define.
diff --git a/gdb/m32r-rom.c b/gdb/m32r-rom.c
new file mode 100644 (file)
index 0000000..25280c2
--- /dev/null
@@ -0,0 +1,563 @@
+/* Remote debugging interface to m32r ROM monitor for GDB, the GNU debugger.
+   Copyright 1996 Free Software Foundation, Inc.
+
+   Adapted by Michael Snyder of Cygnus Support.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* This module defines communication with the Mitsubishi m32r monitor */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "symtab.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "symfile.h"   /* for generic load */
+#include <time.h>      /* for time_t */
+#include "gdb_string.h"
+
+/*
+ * All this stuff just to get my host computer's IP address!
+ */
+#include <netdb.h>     /* for hostent */
+#include <netinet/in.h>        /* for struct in_addr */
+#if 1
+#include <arpa/inet.h> /* for inet_ntoa */
+#endif
+
+static char *board_addr;       /* user-settable IP address for M32R-EVA */
+static char *server_addr;      /* user-settable IP address for gdb host */
+static char *download_path;    /* user-settable path for SREC files     */
+
+
+/* 
+ * Function: m32r_load_1 (helper function)
+ */
+
+static void
+m32r_load_section (abfd, s, data_count)
+     bfd      *abfd;
+     asection *s;
+     unsigned int *data_count;
+{
+  if (s->flags & SEC_LOAD)
+    {
+      bfd_size_type section_size = bfd_section_size (abfd, s);
+      bfd_vma       section_base = bfd_section_vma  (abfd, s);
+      unsigned int  buffer, i;
+
+      *data_count += section_size;
+
+      printf_filtered ("Loading section %s, size 0x%lx vma ",
+                      bfd_section_name (abfd, s), section_size);
+      print_address_numeric (section_base, 1, gdb_stdout);
+      printf_filtered ("\n");
+      gdb_flush (gdb_stdout);
+      monitor_printf ("%x mw\r" , section_base);
+      for (i = 0; i < section_size; i += 4)
+       {
+         QUIT;
+         monitor_expect (" -> ", NULL, 0);
+         bfd_get_section_contents (abfd, s, (char *) &buffer, i, 4);
+         monitor_printf ("%x\n", buffer);
+       }
+      monitor_expect (" -> ", NULL, 0);
+      monitor_printf ("q\n");
+      monitor_expect_prompt (NULL, 0);
+    }
+}
+
+static int 
+m32r_load_1 (dummy)
+     void *dummy;
+{
+  int data_count = 0;
+
+  bfd_map_over_sections ((bfd *) dummy, m32r_load_section, &data_count);
+  return data_count;
+}
+
+/* 
+ * Function: m32r_load (an alternate way to load) 
+ */
+
+static void
+m32r_load (filename, from_tty) 
+    char *filename;
+    int from_tty;
+{
+  extern int inferior_pid;
+  bfd *abfd;
+  asection *s;
+  unsigned int i, data_count = 0;
+  time_t start_time, end_time; /* for timing of download */
+
+  if (filename == NULL || filename[0] == 0)
+    filename = get_exec_file (1);
+
+  abfd = bfd_openr (filename, 0);
+  if (!abfd)
+    error ("Unable to open file %s\n", filename);
+  if (bfd_check_format (abfd, bfd_object) == 0)
+    error ("File is not an object file\n");
+  start_time = time (NULL);
+#if 0
+  for (s = abfd->sections; s; s = s->next)
+    if (s->flags & SEC_LOAD)
+      {
+       bfd_size_type section_size = bfd_section_size (abfd, s);
+       bfd_vma       section_base = bfd_section_vma  (abfd, s);
+       unsigned int  buffer;
+
+       data_count += section_size;
+
+       printf_filtered ("Loading section %s, size 0x%lx vma ",
+                        bfd_section_name (abfd, s), section_size);
+       print_address_numeric (section_base, 1, gdb_stdout);
+       printf_filtered ("\n");
+       gdb_flush (gdb_stdout);
+       monitor_printf ("%x mw\r" , section_base);
+       for (i = 0; i < section_size; i += 4)
+         {
+           monitor_expect (" -> ", NULL, 0);
+           bfd_get_section_contents (abfd, s, (char *) &buffer, i, 4);
+           monitor_printf ("%x\n", buffer);
+         }
+       monitor_expect (" -> ", NULL, 0);
+       monitor_printf ("q\n");
+       monitor_expect_prompt (NULL, 0);
+      }
+#else
+  if (!(catch_errors (m32r_load_1, abfd, "Load aborted!\n", RETURN_MASK_ALL)))
+    {
+      monitor_printf ("q\n");
+      return;
+    }
+#endif
+  end_time = time (NULL);
+  printf_filtered ("Start address 0x%lx\n", bfd_get_start_address (abfd));
+  report_transfer_performance (data_count, start_time, end_time);
+
+  /* Finally, make the PC point at the start address */
+  if (exec_bfd)
+    write_pc (bfd_get_start_address (exec_bfd));
+
+  inferior_pid = 0;             /* No process now */
+
+  /* This is necessary because many things were based on the PC at the
+     time that we attached to the monitor, which is no longer valid
+     now that we have loaded new code (and just changed the PC).
+     Another way to do this might be to call normal_stop, except that
+     the stack may not be valid, and things would get horribly
+     confused... */
+
+  clear_symtab_users ();
+}
+
+static void
+m32r_load_gen (filename, from_tty) 
+    char *filename;
+    int from_tty;
+{
+  generic_load (filename, from_tty);
+}
+
+static void m32r_open PARAMS ((char *args, int from_tty));
+
+/* This array of registers needs to match the indexes used by GDB. The
+   whole reason this exists is because the various ROM monitors use
+   different names than GDB does, and don't support all the registers
+   either. So, typing "info reg sp" becomes an "A7". */
+
+static char *m32r_regnames[] = 
+{ "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7", 
+  "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15", 
+  "psw", "cbr", "spi", "spu", "bpc", "pc",  "accl", "acch", 
+};
+
+static void
+m32r_supply_register (regname, regnamelen, val, vallen)
+     char *regname;
+     int regnamelen;
+     char *val;
+     int vallen;
+{
+  int regno;
+  int num_regs = sizeof(m32r_regnames) / sizeof(m32r_regnames[0]);
+
+  for (regno = 0; regno < num_regs; regno++)
+    if (strncmp(regname, m32r_regnames[regno], regnamelen) == 0)
+      break;
+
+  if (regno >= num_regs)
+    return;            /* no match */
+
+  if (regno == ACCL_REGNUM)
+    { /* special handling for 64-bit acc reg */
+      monitor_supply_register (ACCH_REGNUM, val);
+      if (val = (char *) strchr(val, ':'))  /* skip past ':' to get 2nd word */
+       monitor_supply_register (ACCL_REGNUM, val + 1);
+    }
+  else
+    {
+      monitor_supply_register (regno, val);
+      if (regno == PSW_REGNUM)
+       {
+         unsigned long psw = strtoul (val, NULL, 16);
+         char *zero = "00000000", *one = "00000001";
+
+#ifdef SM_REGNUM
+         /* Stack mode bit */
+         monitor_supply_register (SM_REGNUM, (psw & 0x80) ? one : zero);
+#endif
+#ifdef BSM_REGNUM
+         /* Backup stack mode bit */
+         monitor_supply_register (BSM_REGNUM, (psw & 0x8000) ? one : zero);
+#endif
+#ifdef IE_REGNUM
+         /* Interrupt enable bit */
+         monitor_supply_register (IE_REGNUM, (psw & 0x40) ? one : zero);
+#endif
+#ifdef BIE_REGNUM
+         /* Backup interrupt enable bit */
+         monitor_supply_register (BIE_REGNUM, (psw & 0x4000) ? one : zero);
+#endif
+#ifdef COND_REGNUM
+         /* Condition bit (carry etc.) */
+         monitor_supply_register (COND_REGNUM, (psw & 0x1) ? one : zero);
+#endif
+#ifdef CBR_REGNUM
+         monitor_supply_register (CBR_REGNUM, (psw & 0x1) ? one : zero);
+#endif
+#ifdef BPC_REGNUM
+         monitor_supply_register (BPC_REGNUM, zero); /* KLUDGE:   (???????) */
+#endif
+#ifdef BCARRY_REGNUM
+         monitor_supply_register (BCARRY_REGNUM, zero); /* KLUDGE: (??????) */
+#endif
+       }         
+
+      if (regno == SPI_REGNUM || regno == SPU_REGNUM)  
+       { /* special handling for stack pointer (spu or spi) */
+         unsigned long stackmode = read_register (PSW_REGNUM) & 0x80;
+
+         if (regno == SPI_REGNUM && !stackmode)        /* SP == SPI */
+           monitor_supply_register (SP_REGNUM, val);
+         else if (regno == SPU_REGNUM && stackmode)    /* SP == SPU */
+           monitor_supply_register (SP_REGNUM, val);
+       }
+    }
+}
+
+static struct target_ops m32r_ops;
+
+static char *m32r_inits[] = {"\r", NULL};
+
+static struct monitor_ops m32r_cmds =
+{
+  MO_CLR_BREAK_USES_ADDR | MO_REGISTER_VALUE_FIRST,
+  m32r_inits,                  /* Init strings */
+  "go\r",                      /* continue command */
+  "step\r",                    /* single step */
+  NULL,                                /* interrupt command */
+  "%x +bp\r",                  /* set a breakpoint */
+  "%x -bp\r",                  /* clear a breakpoint */
+  "bpoff\r",                   /* clear all breakpoints */
+  "%x %x %x fill\r",           /* fill (start length val) */
+  {
+    "%x 1 %x fill\r",          /* setmem.cmdb (addr, value) */
+    "%x 1 %x fillh\r",         /* setmem.cmdw (addr, value) */
+    "%x 1 %x fillw\r",         /* setmem.cmdl (addr, value) */
+    NULL,                      /* setmem.cmdll (addr, value) */
+    NULL,                      /* setmem.resp_delim */
+    NULL,                      /* setmem.term */
+    NULL                       /* setmem.term_cmd */
+  },
+  {
+    "%x %x dump\r",            /* getmem.cmdb (addr, len) */
+    NULL,                      /* getmem.cmdw (addr, len) */
+    NULL,                      /* getmem.cmdl (addr, len) */
+    NULL,                      /* getmem.cmdll (addr, len) */
+    ": ",                      /* getmem.resp_delim */
+    NULL,                      /* getmem.term */
+    NULL                       /* getmem.term_cmd */
+  },
+  {
+    "%x to %%%s\r",            /* setreg.cmd (name, value) */
+    NULL,                      /* setreg.resp_delim */
+    NULL,                      /* setreg.term */
+    NULL                       /* setreg.term_cmd */
+  },
+  {
+    NULL,                      /* getreg.cmd (name) */
+    NULL,                      /* getreg.resp_delim */
+    NULL,                      /* getreg.term */
+    NULL                       /* getreg.term_cmd */
+  },
+  ".reg\r",                    /* dump_registers */
+  "\\(\\w+\\) += \\([0-9a-fA-F]+\\b\\)", /* register_pattern */
+  m32r_supply_register,                /* supply_register */
+  NULL,                                /* load_routine (defaults to SRECs) */
+  NULL,                                /* download command */
+  NULL,                                /* load response */
+  "ok ",                       /* monitor command prompt */
+  "\r",                                /* end-of-line terminator */
+  NULL,                                /* optional command terminator */
+  &m32r_ops,                   /* target operations */
+  SERIAL_1_STOPBITS,           /* number of stop bits */
+  m32r_regnames,               /* registers names */
+  MONITOR_OPS_MAGIC            /* magic */
+  };
+
+static void
+m32r_open(args, from_tty)
+     char *args;
+     int from_tty;
+{
+  monitor_open (args, &m32r_cmds, from_tty);
+}
+
+/* Function: set_board_address
+   Tell the BootOne monitor what it's ethernet IP address is. */
+
+static void
+m32r_set_board_address (args, from_tty)
+     char *args;
+     int  from_tty;
+{
+  int resp_len;
+  char buf[1024];
+
+  if (args && *args)
+    {
+      monitor_printf ("ulip %s\n", args);
+      resp_len = monitor_expect_prompt (buf, sizeof(buf));
+      /* now parse the result for success */
+    }
+  else
+    error ("Requires argument (IP address for M32R-EVA board)");
+}
+
+/* Function: set_server_address
+   Tell the BootOne monitor what gdb's ethernet IP address is. */
+
+static void
+m32r_set_server_address (args, from_tty)
+     char *args;
+     int  from_tty;
+{
+  int resp_len;
+  char buf[1024];
+
+  if (args && *args)
+    {
+      monitor_printf ("uhip %s\n", args);
+      resp_len = monitor_expect_prompt (buf, sizeof(buf));
+      /* now parse the result for success */
+    }
+  else
+    error ("Requires argument (IP address of GDB's host computer)");
+}
+
+/* Function: set_download_path
+   Tell the BootOne monitor the default path for downloadable SREC files. */
+
+static void
+m32r_set_download_path (args, from_tty)
+     char *args;
+     int  from_tty;
+{
+  int resp_len;
+  char buf[1024];
+
+  if (args && *args)
+    {
+      monitor_printf ("up %s\n", args);
+      resp_len = monitor_expect_prompt (buf, sizeof(buf));
+      /* now parse the result for success */
+    }
+  else
+    error ("Requires argument (default path for downloadable SREC files)");
+}
+
+static void
+m32r_upload_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  bfd *abfd;
+  asection *s;
+  time_t start_time, end_time; /* for timing of download */
+  extern int inferior_pid;
+  int resp_len, data_count = 0;
+  char buf[1024];
+  struct hostent *hostent;
+  struct in_addr inet_addr;
+
+  /* first check to see if there's an ethernet port! */
+  monitor_printf ("ust\r");
+  resp_len = monitor_expect_prompt (buf, sizeof(buf));
+  if (!strchr (buf, ':'))
+    error ("No ethernet connection!");
+
+  if (board_addr == 0)
+    {
+      /* scan second colon in the output from the "ust" command */
+      char * myIPaddress = strchr (strchr (buf, ':') + 1, ':') + 1;
+
+      while (isspace(*myIPaddress))
+       myIPaddress++;
+
+      if (!strncmp (myIPaddress, "0.0.", 4))    /* empty */
+       error ("Please use 'set board-address' to set the M32R-EVA board's IP address.");
+      if (strchr (myIPaddress, '('))
+       *(strchr (myIPaddress, '(')) = '\0';    /* delete trailing junk */
+      board_addr = strsave (myIPaddress);
+    }
+  if (server_addr == 0)
+    {
+      buf[0] = 0;
+      gethostname (buf, sizeof(buf));
+      if (buf[0] != 0)
+       hostent = gethostbyname (buf);
+      if (hostent != 0)
+       {
+#if 1
+         memcpy (&inet_addr.s_addr, hostent->h_addr, 
+                 sizeof(inet_addr.s_addr));
+         server_addr = (char *) inet_ntoa (inet_addr);
+#else
+         server_addr = (char *) inet_ntoa (hostent->h_addr);
+#endif
+       }
+      if (server_addr == 0)    /* failed? */
+       error ("Need to know gdb host computer's IP address (use 'set server-address')");
+    }
+
+  if (args == 0 || args[0] == 0)       /* no args: upload the current file */
+    args = get_exec_file (1);
+
+  if (args[0] != '/' && download_path == 0)
+    if (current_directory)
+      download_path = strsave (current_directory);
+    else
+      error ("Need to know default download path (use 'set download-path')");
+
+  start_time = time (NULL);
+  monitor_printf ("uhip %s\r", server_addr);
+  resp_len = monitor_expect_prompt (buf, sizeof(buf));  /* parse result? */
+  monitor_printf ("ulip %s\r", board_addr);
+  resp_len = monitor_expect_prompt (buf, sizeof(buf));  /* parse result? */
+  if (args[0] != '/')
+    monitor_printf ("up %s\r", download_path); /* use default path */
+  else
+    monitor_printf ("up\r");                   /* rooted filename/path */
+  resp_len = monitor_expect_prompt (buf, sizeof(buf));  /* parse result? */
+
+  if (strrchr (args, '.') && !strcmp (strrchr (args, '.'), ".srec"))
+    monitor_printf ("ul %s\r", args);
+  else                                 /* add ".srec" suffix */
+    monitor_printf ("ul %s.srec\r", args);
+  resp_len = monitor_expect_prompt (buf, sizeof(buf));  /* parse result? */
+
+  if (buf[0] == 0 || strstr(buf, "complete") == 0)
+    error("Upload file not found: %s.srec\nCheck IP addresses and download path.", args);
+  else
+    printf_filtered (" -- Ethernet load complete.\n");
+
+  end_time = time (NULL);
+  if (abfd = bfd_openr (args, 0))
+    { /* Download is done -- print section statistics */
+      if (bfd_check_format (abfd, bfd_object) == 0)
+       {
+         printf_filtered ("File is not an object file\n");
+       }
+      for (s = abfd->sections; s; s = s->next)
+       if (s->flags & SEC_LOAD)
+         {
+           bfd_size_type section_size = bfd_section_size (abfd, s);
+           bfd_vma       section_base = bfd_section_vma  (abfd, s);
+           unsigned int  buffer;
+
+           data_count += section_size;
+
+           printf_filtered ("Loading section %s, size 0x%lx vma ",
+                            bfd_section_name (abfd, s), section_size);
+           print_address_numeric (section_base, 1, gdb_stdout);
+           printf_filtered ("\n");
+           gdb_flush (gdb_stdout);
+         }
+      /* Finally, make the PC point at the start address */
+      write_pc (bfd_get_start_address (abfd));
+      report_transfer_performance (data_count, start_time, end_time);
+      printf_filtered ("Start address 0x%lx\n", bfd_get_start_address (abfd));
+    }
+  inferior_pid = 0;             /* No process now */
+
+  /* This is necessary because many things were based on the PC at the
+     time that we attached to the monitor, which is no longer valid
+     now that we have loaded new code (and just changed the PC).
+     Another way to do this might be to call normal_stop, except that
+     the stack may not be valid, and things would get horribly
+     confused... */
+
+  clear_symtab_users ();
+}
+
+void
+_initialize_m32r_rom ()
+{
+  init_monitor_ops (&m32r_ops);
+
+  m32r_ops.to_shortname = "m32r";
+  m32r_ops.to_longname = "m32r monitor";
+  m32r_ops.to_load = m32r_load_gen;    /* monitor lacks a download command */
+  m32r_ops.to_doc = "Debug via the m32r monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+  m32r_ops.to_open = m32r_open;
+
+  add_show_from_set
+    (add_set_cmd ("download-path", class_obscure, var_string,
+                 (char *) &download_path,
+                 "Set the default path for downloadable SREC files.",
+                 &setlist),
+     &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("board-address", class_obscure, var_string,
+                 (char *) &board_addr,
+                 "Set IP address for M32R-EVA target board.",
+                 &setlist),
+     &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("server-address", class_obscure, var_string,
+                 (char *) &server_addr,
+                 "Set IP address for download server (GDB's host computer).",
+                 &setlist),
+     &showlist);
+
+  add_com ("upload", class_obscure, m32r_upload_command,
+          "Upload the srec file via the monitor's Ethernet upload capability."); 
+
+  add_com ("tload", class_obscure, m32r_load, "test upload command.");
+
+  add_target (&m32r_ops);
+}