Replace "exec" with "executable" in messages.
[deliverable/binutils-gdb.git] / gdb / sparclet-rom.c
index 98bc27b9fd56e61479595a26d197d91bbd5ae883..24484cd80504f6654a89cb7f53fbc96fb44e8c1a 100644 (file)
@@ -26,139 +26,165 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "srec.h"
 #include "symtab.h"
 #include "symfile.h" /* for generic_load */
+#include <time.h>
 
-#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
-#define HAVE_SGTTY
-#endif
+extern void report_transfer_performance PARAMS ((unsigned long, time_t, time_t));
 
-#ifdef HAVE_SGTTY
-#include <sys/ioctl.h>
-#endif
+static struct target_ops sparclet_ops;
 
-#include <sys/types.h> /* Needed by file.h on Sys V */
-#include <sys/file.h>
-#include <signal.h>
-#include <sys/stat.h>
+static void sparclet_open PARAMS ((char *args, int from_tty));
 
-#define USE_GENERIC_LOAD
-#define USE_SW_BREAKS
+/* This array of registers need to match the indexes used by GDB.
+   This exists because the various ROM monitors use different strings
+   than does GDB, and don't necessarily support all the registers
+   either. So, typing "info reg sp" becomes a "r30".  */
 
-static struct target_ops sparclet_ops;
+/*PSR 0x00000080  impl ver icc AW LE EE EC EF PIL S PS ET CWP  WIM
+                0x0  0x0 0x0  0  0  0  0  0 0x0 1  0  0 0x00 0x2
+                                                             0000010
+       INS        LOCALS       OUTS      GLOBALS
+ 0  0x00000000  0x00000000  0x00000000  0x00000000
+ 1  0x00000000  0x00000000  0x00000000  0x00000000
+ 2  0x00000000  0x00000000  0x00000000  0x00000000
+ 3  0x00000000  0x00000000  0x00000000  0x00000000
+ 4  0x00000000  0x00000000  0x00000000  0x00000000
+ 5  0x00000000  0x00001000  0x00000000  0x00000000
+ 6  0x00000000  0x00000000  0x123f0000  0x00000000
+ 7  0x00000000  0x00000000  0x00000000  0x00000000
+pc:  0x12010000 0x00000000    unimp
+npc: 0x12010004 0x00001000    unimp     0x1000
+tbr: 0x00000000
+y:   0x00000000
+*/
+/* these correspond to the offsets from tm-* files from config directories */
 
-static void sparclet_open PARAMS ((char *args, int from_tty));
+/* is wim part of psr?? */
+/* monitor wants lower case */
+static char *sparclet_regnames[NUM_REGS] = REGISTER_NAMES;
 
-#ifdef USE_GENERIC_LOAD
+
+/* Function: sparclet_supply_register
+   Just returns with no action.
+   This function is required, because parse_register_dump (monitor.c)
+   expects to be able to call it.  If we don't supply something, it will
+   call a null pointer and core-dump.  Since this function does not 
+   actually do anything, GDB will request the registers individually.  */
 
 static void
-sparclet_load_gen (filename, from_tty) 
-    char *filename;
-    int from_tty;
+sparclet_supply_register (regname, regnamelen, val, vallen)
+     char *regname;
+     int regnamelen;
+     char *val;
+     int vallen;
 {
-  extern int inferior_pid;
-
-  generic_load (filename, from_tty);
-  /* 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 */
+  return;
 }
 
-#else
-
 static void
-sparclet_xmodem_load (desc, file, hashmark)
+sparclet_load (desc, file, hashmark)
      serial_t desc;
      char *file;
      int hashmark;
 {
   bfd *abfd;
   asection *s;
-  char *buffer;
   int i;
+  CORE_ADDR load_offset;
+  time_t start_time, end_time;
+  unsigned long data_count = 0;
+
+  /* enable user to specify address for downloading as 2nd arg to load */
+
+  i = sscanf(file, "%*s 0x%lx", &load_offset);
+  if (i >= 1 ) 
+    {
+      char *p;
+
+      for (p = file; *p != '\000' && !isspace (*p); p++);
+
+      *p = '\000';
+    }
+  else
+    load_offset = 0;
 
-  buffer = alloca (XMODEM_PACKETSIZE);
   abfd = bfd_openr (file, 0);
   if (!abfd)
     {
       printf_filtered ("Unable to open file %s\n", file);
       return;
     }
+
   if (bfd_check_format (abfd, bfd_object) == 0)
     {
       printf_filtered ("File is not an object file\n");
       return;
     }
+  
+  start_time = time (NULL);
+
   for (s = abfd->sections; s; s = s->next)
     if (s->flags & SEC_LOAD)
       {
        bfd_size_type section_size;
-       printf_filtered ("%s\t: 0x%4x .. 0x%4x  ", s->name, s->vma,
-                        s->vma + s->_raw_size);
-       gdb_flush (gdb_stdout);
-       monitor_printf (current_monitor->load, s->vma);
-       if (current_monitor->loadresp)
-         monitor_expect (current_monitor->loadresp, NULL, 0);
-       xmodem_init_xfer (desc);
+       bfd_vma vma;
+
+       vma = bfd_get_section_vma (abfd, s) + load_offset;
        section_size = bfd_section_size (abfd, s);
-       for (i = 0; i < section_size; i += XMODEM_DATASIZE)
+
+       data_count += section_size;
+
+       printf_filtered ("%s\t: 0x%4x .. 0x%4x  ",
+                        bfd_get_section_name (abfd, s), vma,
+                        vma + section_size);
+       gdb_flush (gdb_stdout);
+
+       monitor_printf ("load c r %x %x\r", vma, section_size);
+
+       monitor_expect ("load: loading ", NULL, 0);
+       monitor_expect ("\r", NULL, 0);
+
+       for (i = 0; i < section_size; i += 2048)
          {
            int numbytes;
-           numbytes = min (XMODEM_DATASIZE, section_size - i);
-           bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i,
-                                     numbytes);
-           xmodem_send_packet (desc, buffer, numbytes, hashmark);
+           char buf[2048];
+
+           numbytes = min (sizeof buf, section_size - i);
+
+           bfd_get_section_contents (abfd, s, buf, i, numbytes);
+
+           SERIAL_WRITE (desc, buf, numbytes);
+
            if (hashmark)
              {
                putchar_unfiltered ('#');
                gdb_flush (gdb_stdout);
              }
          }                     /* Per-packet (or S-record) loop */
-       xmodem_finish_xfer (desc);
+
        monitor_expect_prompt (NULL, 0);
+
        putchar_unfiltered ('\n');
       }                                /* Loadable sections */
+
+  monitor_printf ("reg pc %x\r", bfd_get_start_address (abfd));
+  monitor_expect_prompt (NULL, 0);
+  monitor_printf ("reg npc %x\r", bfd_get_start_address (abfd) + 4);
+  monitor_expect_prompt (NULL, 0);
+
+  monitor_printf ("run\r");
+
+  end_time = time (NULL);
+
   if (hashmark) 
     putchar_unfiltered ('\n');
-}
 
-static void
-sparclet_load (desc, file, hashmark)
-     serial_t desc;
-     char *file;
-     int hashmark;
-{
-???
-}
-#endif /* USE_GENERIC_LOAD */
-
-/* This array of registers need to match the indexes used by GDB.
-   This exists because the various ROM monitors use different strings
-   than does GDB, and don't necessarily support all the registers
-   either. So, typing "info reg sp" becomes a "r30".  */
+  report_transfer_performance (data_count, start_time, end_time);
 
-/*PSR 0x00000080  impl ver icc AW LE EE EC EF PIL S PS ET CWP  WIM
-                0x0  0x0 0x0  0  0  0  0  0 0x0 1  0  0 0x00 0x2
-                                                             0000010
-       INS        LOCALS       OUTS      GLOBALS
- 0  0x00000000  0x00000000  0x00000000  0x00000000
- 1  0x00000000  0x00000000  0x00000000  0x00000000
- 2  0x00000000  0x00000000  0x00000000  0x00000000
- 3  0x00000000  0x00000000  0x00000000  0x00000000
- 4  0x00000000  0x00000000  0x00000000  0x00000000
- 5  0x00000000  0x00001000  0x00000000  0x00000000
- 6  0x00000000  0x00000000  0x123f0000  0x00000000
- 7  0x00000000  0x00000000  0x00000000  0x00000000
-pc:  0x12010000 0x00000000    unimp
-npc: 0x12010004 0x00001000    unimp     0x1000
-tbr: 0x00000000
-y:   0x00000000
-*/
-/* these correspond to the offsets from tm-* files from config directories */
+  pop_target ();
+  push_remote_target (monitor_get_dev_name (), 1);
 
-/* is wim part of psr?? */
-/* monitor wants lower case */
-static char *sparclet_regnames[NUM_REGS] = REGISTER_NAMES;
+  return_to_top_level (RETURN_QUIT);
+}
 
 /* Define the monitor command strings. Since these are passed directly
    through to a printf style function, we may include formatting
@@ -168,81 +194,66 @@ static char *sparclet_regnames[NUM_REGS] = REGISTER_NAMES;
 
 static char *sparclet_inits[] = {"\n\r\r\n", NULL};
 
-static struct monitor_ops sparclet_cmds =
+static struct monitor_ops sparclet_cmds ;
+static void init_sparclet_cmds(void)
 {
-  MO_CLR_BREAK_USES_ADDR
-    | MO_HEX_PREFIX
-    | MO_HANDLE_NL
-    | MO_NO_ECHO_ON_OPEN
-    | MO_NO_ECHO_ON_SETMEM
-    | MO_RUN_FIRST_TIME
-    | MO_GETMEM_READ_SINGLE,    /* flags */
-  sparclet_inits,                      /* Init strings */
-  "cont\r",                    /* continue command */
-  "step\r",                    /* single step */
-  "\r",                        /* break interrupts the program */
-  "+bp %x\r",                          /* set a breakpoint */
-                               /* can't use "br" because only 2 hw bps are supported */
-  "-bp %x\r",                          /* clear a breakpoint */
-  "-bp\r",                             /* clear all breakpoints */
-  NULL,                                /* fill (start end val) */
-                               /* can't use "fi" because it takes words, not bytes */
-  {
-    /* ex [addr] [-n count] [-b|-s|-l]          default: ex cur -n 1 -b */
-    "ex %x -b\r%x\rq\r",                        /* setmem.cmdb (addr, value) */
-    "ex %x -s\r%x\rq\r",                /* setmem.cmdw (addr, value) */
-    "ex %x -l\r%x\rq\r",         
-    NULL,                      /* setmem.cmdll (addr, value) */
-    NULL, /*": ",                      /* setmem.resp_delim */
-    NULL, /*"? ",                      /* setmem.term */
-    NULL, /*"q\r",                     /* setmem.term_cmd */
-  },
-  {
-    /* since the parsing of multiple bytes is difficult due to
-       interspersed addresses, we'll only read 1 value at a time, 
-       even tho these can handle a count */
-    /* we can use -n to set count to read, but may have to parse? */
-    "ex %x -n 1 -b\r",         /* getmem.cmdb (addr, #bytes) */
-    "ex %x -n 1 -s\r",         /* getmem.cmdw (addr, #swords) */
-    "ex %x -n 1 -l\r",         /* getmem.cmdl (addr, #words) */
-    NULL,              /* getmem.cmdll (addr, #dwords) */
-    ": ",                      /* getmem.resp_delim */
-    NULL,                      /* getmem.term */
-    NULL,                      /* getmem.term_cmd */
-  },
-  {
-    "reg %s 0x%x\r",           /* setreg.cmd (name, value) */
-    NULL,                      /* setreg.resp_delim */
-    NULL,                      /* setreg.term */
-    NULL                       /* setreg.term_cmd */
-  },
-  {
-    "reg %s\r",                /* getreg.cmd (name) */
-    ": ",                      /* getreg.resp_delim */
-    NULL,                      /* getreg.term */
-    NULL,                      /* getreg.term_cmd */
-  },
-  "reg\r",                     /* dump_registers */
-  "\\(\\w+\\)=\\([0-9a-fA-F]+\\)",     /* register_pattern */
-  NULL,                                /* supply_register */
-#ifdef USE_GENERIC_LOAD
-  NULL,                                /* load_routine (defaults to SRECs) */
-  NULL,                                /* download command */
-  NULL,                                /* load response */
-#else
-  sparclet_load,                       /* load_routine (defaults to SRECs) */
-  /* load [c|a] [s|f|r] [addr count] */
-  "load a s %x\r",                     /* download command */
-  "load: ",            /* load response */
-#endif
-  "monitor>",                          /* monitor command prompt */
+  sparclet_cmds.flags =   MO_CLR_BREAK_USES_ADDR |
+    MO_HEX_PREFIX          |
+    MO_NO_ECHO_ON_OPEN     |
+    MO_NO_ECHO_ON_SETMEM   |
+    MO_RUN_FIRST_TIME      |
+    MO_GETMEM_READ_SINGLE ;    /* flags */
+  sparclet_cmds.init =   sparclet_inits;               /* Init strings */
+  sparclet_cmds.cont =   "cont\r";                     /* continue command */
+  sparclet_cmds.step =   "step\r";                     /* single step */
+  sparclet_cmds.stop =   "\r";                         /* break interrupts the program */
+  sparclet_cmds.set_break =   "+bp %x\r";              /* set a breakpoint */
+  sparclet_cmds.clr_break =  "-bp %x\r" ;              /* can't use "br" because only 2 hw bps are supported */
+  sparclet_cmds.clr_all_break =   "-bp %x\r";          /* clear a breakpoint */
+  "-bp\r" ;                    /* clear all breakpoints */
+  sparclet_cmds.fill =   "fill %x -n %x -v %x -b\r";   /* fill (start length val) */
+  /* can't use "fi" because it takes words, not bytes */
+  /* ex [addr] [-n count] [-b|-s|-l]          default: ex cur -n 1 -b */
+  sparclet_cmds.setmem.cmdb =     "ex %x -b\r%x\rq\r"; /* setmem.cmdb (addr, value) */
+  sparclet_cmds.setmem.cmdw =     "ex %x -s\r%x\rq\r"; /* setmem.cmdw (addr, value) */
+  sparclet_cmds.setmem.cmdl =     "ex %x -l\r%x\rq\r";  /* setmem.cmdl (addr, value) */
+  sparclet_cmds.setmem.cmdll =     NULL;               /* setmem.cmdll (addr, value) */
+  sparclet_cmds.setmem.resp_delim =     NULL; /*": " */        /* setmem.resp_delim */
+  sparclet_cmds.setmem.term =     NULL; /*"? " */      /* setmem.term */
+  sparclet_cmds.setmem.term_cmd =     NULL; /*"q\r" */ /* setmem.term_cmd */
+  /* since the parsing of multiple bytes is difficult due to
+     interspersed addresses, we'll only read 1 value at a time,
+     even tho these can handle a count */
+  /* we can use -n to set count to read, but may have to parse? */
+  sparclet_cmds.getmem.cmdb =     "ex %x -n 1 -b\r";   /* getmem.cmdb (addr, #bytes) */
+  sparclet_cmds.getmem.cmdw =     "ex %x -n 1 -s\r";   /* getmem.cmdw (addr, #swords) */
+  sparclet_cmds.getmem.cmdl =     "ex %x -n 1 -l\r";   /* getmem.cmdl (addr, #words) */
+  sparclet_cmds.getmem.cmdll =     NULL;               /* getmem.cmdll (addr, #dwords) */
+  sparclet_cmds.getmem.resp_delim =     ": ";          /* getmem.resp_delim */
+  sparclet_cmds.getmem.term =     NULL;                        /* getmem.term */
+  sparclet_cmds.getmem.term_cmd =     NULL;            /* getmem.term_cmd */
+  sparclet_cmds.setreg.cmd =     "reg %s 0x%x\r";      /* setreg.cmd (name, value) */
+  sparclet_cmds.setreg.resp_delim =     NULL;          /* setreg.resp_delim */
+  sparclet_cmds.setreg.term =     NULL;                        /* setreg.term */
+  sparclet_cmds.setreg.term_cmd =  NULL ;              /* setreg.term_cmd */
+  sparclet_cmds.getreg.cmd =     "reg %s\r";           /* getreg.cmd (name) */
+  sparclet_cmds.getreg.resp_delim =     " ";           /* getreg.resp_delim */
+  sparclet_cmds.getreg.term =     NULL;                        /* getreg.term */
+  sparclet_cmds.getreg.term_cmd =     NULL;            /* getreg.term_cmd */
+  sparclet_cmds.dump_registers =   "reg\r";            /* dump_registers */
+  sparclet_cmds.register_pattern =   "\\(\\w+\\)=\\([0-9a-fA-F]+\\)";  /* register_pattern */
+  sparclet_cmds.supply_register =   sparclet_supply_register;  /* supply_register */
+  sparclet_cmds.load_routine =   sparclet_load;                /* load_routine */
+  sparclet_cmds.load =   NULL;                         /* download command (srecs on console) */
+  sparclet_cmds.loadresp =   NULL;                     /* load response */
+  sparclet_cmds.prompt =   "monitor>";                 /* monitor command prompt */
   /* yikes!  gdb core dumps without this delimitor!! */
-  "\r",                        /* end-of-command delimitor */
-  NULL,                                /* optional command terminator */
-  &sparclet_ops,                       /* target operations */
-  SERIAL_1_STOPBITS,           /* number of stop bits */
-  sparclet_regnames,           /* registers names */
-  MONITOR_OPS_MAGIC            /* magic */
+  sparclet_cmds.line_term =   "\r";                    /* end-of-command delimitor */
+  sparclet_cmds.cmd_end =   NULL;                      /* optional command terminator */
+  sparclet_cmds.target =   &sparclet_ops;              /* target operations */
+  sparclet_cmds.stopbits =   SERIAL_1_STOPBITS;                /* number of stop bits */
+  sparclet_cmds.regnames =   sparclet_regnames;                /* registers names */
+  sparclet_cmds.magic =   MONITOR_OPS_MAGIC ;  /* magic */
 };
 
 static void
@@ -256,18 +267,22 @@ sparclet_open (args, from_tty)
 void
 _initialize_sparclet ()
 {
-  init_monitor_ops (&sparclet_ops);
+  int i;
+  init_sparclet_cmds() ;
 
+  for (i = 0; i < NUM_REGS; i++)
+    if (sparclet_regnames[i][0] == 'c' ||
+       sparclet_regnames[i][0] == 'a')
+      sparclet_regnames[i] = 0;                /* mon can't report c* or a* regs */
+
+  sparclet_regnames[0] = 0;            /* mon won't report %G0 */
+
+  init_monitor_ops (&sparclet_ops);
   sparclet_ops.to_shortname = "sparclet"; /* for the target command */
   sparclet_ops.to_longname = "SPARC Sparclet monitor";
-#ifdef USE_GENERIC_LOAD
-  sparclet_ops.to_load = sparclet_load_gen; /* FIXME - should go back and try "do" */
-#endif
-#ifdef USE_SW_BREAKS
   /* use SW breaks; target only supports 2 HW breakpoints */
   sparclet_ops.to_insert_breakpoint = memory_insert_breakpoint; 
   sparclet_ops.to_remove_breakpoint = memory_remove_breakpoint; 
-#endif
 
   sparclet_ops.to_doc = 
     "Use a board running the Sparclet debug monitor.\n\
This page took 0.026818 seconds and 4 git commands to generate.