* configure,configure.in: Add target sparclet.
authorDawn Perchik <dawn@cygnus>
Fri, 28 Jun 1996 14:03:13 +0000 (14:03 +0000)
committerDawn Perchik <dawn@cygnus>
Fri, 28 Jun 1996 14:03:13 +0000 (14:03 +0000)
    * monitor.h,monitor.c:
    Added monitor flags MO_NO_ECHO_ON_SETMEM (don't expect echo on
    setmem command), MO_RUN_FIRST_TIME (if command to start process
    running on target is different from one to continue execution),
    MO_HEX_PREFIX (if addresses from monitor have a "0x" prefix).
    * monitor.c,parse.c,sparc-tdep.c:
    Don't require strings in the registers array.  This is to allow
    NULLs to be place holders in the tm-*.h file so that only minor
    changes are needed when a new processor is introduced (eg, one
    without floating point).
    * sparc-tdep.c: Conditionally remove dependancies on floating point.
    * sparclet-rom.c,config/sparc/sparclet.mt,config/sparc/tm-sparclet.h:
    New files for target sparclet.
    * symfile.c: Add option for 2nd parameter on load command : a load
    offset added to the vma of each section.

gdb/.Sanitize
gdb/ChangeLog
gdb/configure
gdb/configure.in
gdb/monitor.c
gdb/monitor.h
gdb/parse.c
gdb/sparc-tdep.c
gdb/sparclet-rom.c [new file with mode: 0644]
gdb/symfile.c

index 6de1d5d..5f5925f 100644 (file)
@@ -349,6 +349,7 @@ sparc-stub.c
 sparc-tdep.c
 sparcl-stub.c
 sparcl-tdep.c
+sparclet-rom.c
 srec.h
 stabsread.c
 stabsread.h
index eb60268..e16d983 100644 (file)
@@ -1,3 +1,25 @@
+
+
+
+Fri Jun 28 06:34:19 1996  Dawn Perchik  <dawn@cygnus.com>
+
+       * configure,configure.in: Add target sparclet.
+       * monitor.h,monitor.c:
+       Added monitor flags MO_NO_ECHO_ON_SETMEM (don't expect echo on 
+       setmem command), MO_RUN_FIRST_TIME (if command to start process 
+       running on target is different from one to continue execution), 
+       MO_HEX_PREFIX (if addresses from monitor have a "0x" prefix).
+       * monitor.c,parse.c,sparc-tdep.c:
+       Don't require strings in the registers array.  This is to allow 
+       NULLs to be place holders in the tm-*.h file so that only minor 
+       changes are needed when a new processor is introduced (eg, one 
+       without floating point).
+       * sparc-tdep.c: Conditionally remove dependancies on floating point.
+       * sparclet-rom.c,config/sparc/sparclet.mt,config/sparc/tm-sparclet.h:
+       New files for target sparclet.
+       * symfile.c: Add option for 2nd parameter on load command : a load 
+       offset added to the vma of each section.
+
 Fri Jun 28 05:39:19 1996  Dawn Perchik  <dawn@cygnus.com>
 
         * main.c (main): Add option "l" for setting remote_timeout.
index 8d7fb10..910e3d7 100755 (executable)
@@ -3535,8 +3535,7 @@ sparc-*-sunos4*)  gdb_target=sun4os4 ;;
 sparc-*-sunos5*)       gdb_target=sun4sol2 ;;
 sparc-*-vxworks*)      gdb_target=vxsparc ;;
 sparc-*-*)             gdb_target=sun4os4 ;;
-# Use sparc-em for sparclet for now.
-sparclet-*-*)          gdb_target=sparc-em ;;
+sparclet-*-*)          gdb_target=sparclet ;;
 sparclite*-*-*)                gdb_target=sparclite ;;
 # It's not clear what the right solution for "v8plus" systems is yet.
 # For now, stick with sparc-sun-solaris2 since that's what config.guess
index 2390b46..44439ab 100644 (file)
@@ -644,8 +644,7 @@ sparc-*-sunos4*)    gdb_target=sun4os4 ;;
 sparc-*-sunos5*)       gdb_target=sun4sol2 ;;
 sparc-*-vxworks*)      gdb_target=vxsparc ;;
 sparc-*-*)             gdb_target=sun4os4 ;;
-# Use sparc-em for sparclet for now.
-sparclet-*-*)          gdb_target=sparc-em ;;
+sparclet-*-*)          gdb_target=sparclet;;
 sparclite*-*-*)                gdb_target=sparclite ;;
 # It's not clear what the right solution for "v8plus" systems is yet.
 # For now, stick with sparc-sun-solaris2 since that's what config.guess
index 69edc9a..503930f 100644 (file)
@@ -123,6 +123,8 @@ static int dump_reg_flag;   /* Non-zero means do a dump_registers cmd when
                                   monitor_wait wakes up.  */
 
 static DCACHE *remote_dcache;
+static int first_time=0;       /* is this the first time we're executing after 
+                                       gaving created the child proccess? */
 
 /* monitor_debug is like fputs_unfiltered, except it prints special
    characters in printable fashion.  */
@@ -139,7 +141,7 @@ monitor_debug (prefix, string, suffix)
   static int new_line=1;
   static char *prev_prefix = "";
   static char *prev_suffix = "";
-      
+
   /* if the prefix is changing, print the previous suffix, a new line,
      and the new prefix */
   if (strcmp(prev_prefix, prefix) != 0 && !new_line)
@@ -693,6 +695,15 @@ monitor_resume (pid, step, sig)
      int pid, step;
      enum target_signal sig;
 {
+  /* Some monitors require a different command when starting a program */
+  if (current_monitor->flags & MO_RUN_FIRST_TIME && first_time == 1)
+    {
+      first_time = 0;
+      monitor_printf ("run\r");
+      if (current_monitor->flags & MO_NEED_REGDUMP_AFTER_CONT)
+           dump_reg_flag = 1;
+      return;
+    }
   dcache_flush (remote_dcache);
   if (step)
     monitor_printf (current_monitor->step);
@@ -885,6 +896,20 @@ monitor_fetch_register (regno)
   if (current_monitor->getreg.resp_delim)
     monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
 
+  /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */
+  if (current_monitor->flags & MO_HEX_PREFIX) 
+    {
+      int c;
+      c = readchar (timeout);
+      while (c == ' ')
+       c = readchar (timeout);
+      if ((c == '0') && ((c = readchar (timeout)) == 'x'))
+       ;
+      else
+         error ("Bad value returned from monitor while fetching register %x.",
+                regno);
+    }
+
   /* Read upto the maximum number of hex digits for this register, skipping
      spaces, but stop reading if something else is seen.  Some monitors
      like to drop leading zeros.  */
@@ -1078,7 +1103,10 @@ monitor_write_memory (memaddr, myaddr, len)
 
   val = extract_unsigned_integer (myaddr, len);
 
-  monitor_printf (cmd, memaddr, val);
+  if (current_monitor->flags & MO_NO_ECHO_ON_SETMEM)
+    monitor_printf_noecho (cmd, memaddr, val);
+  else
+    monitor_printf (cmd, memaddr, val);
 
   monitor_expect_prompt (NULL, 0);
 
@@ -1135,6 +1163,19 @@ monitor_read_memory_single (memaddr, myaddr, len)
 /* Now, read the appropriate number of hex digits for this loc, skipping
    spaces.  */
 
+  /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */
+  if (current_monitor->flags & MO_HEX_PREFIX) 
+    {
+      int c;
+      c = readchar (timeout);
+      while (c == ' ')
+       c = readchar (timeout);
+      if ((c == '0') && ((c = readchar (timeout)) == 'x'))
+       ;
+      else
+         error ("monitor_read_memory_single (0x%x):  bad response from monitor: %.*s%c.",
+                memaddr, i, membuf, c);
+    }
   for (i = 0; i < len * 2; i++)
     {
       int c;
@@ -1331,6 +1372,7 @@ monitor_create_inferior (exec_file, args, env)
   if (args && (*args != '\000'))
     error ("Args are not supported by the monitor.");
 
+  first_time = 1;
   clear_proceed_status ();
   proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
 }
@@ -1432,6 +1474,7 @@ monitor_load (file, from_tty)
       if (current_monitor->loadresp)
        monitor_expect (current_monitor->loadresp, NULL, 0);
 
+/* FIXME Should add arg here for load_offset (already done for generic_load) */
       load_srec (monitor_desc, file, 32, SREC_ALL, hashmark,
                 current_monitor->flags & MO_SREC_ACK ?
                   monitor_wait_srec_ack : NULL);
index dc2f124..f658921 100644 (file)
@@ -152,6 +152,18 @@ struct monitor_ops
 
 #define MO_SREC_ACK 0x100
 
+/* Allow 0x prefix on addresses retured from monitor */
+
+#define MO_HEX_PREFIX 0x200
+
+/* Some monitors require a different command when starting a program */
+
+#define MO_RUN_FIRST_TIME 0x400
+
+/* Don't expect echos when getting memory */
+
+#define MO_NO_ECHO_ON_SETMEM 0x800
+
 #define SREC_SIZE 160
 
 extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops,
index 7d458c1..e4ff571 100644 (file)
@@ -459,13 +459,13 @@ write_dollar_variable (str)
   /* Handle tokens that refer to machine registers:
      $ followed by a register name.  */
   for (i = 0; i < NUM_REGS; i++)
-    if (str.length - 1 == strlen (reg_names[i])
+    if (reg_names[i] && str.length - 1 == strlen (reg_names[i])
        && STREQN (str.ptr + 1, reg_names[i], str.length - 1))
       {
        goto handle_register;
       }
   for (i = 0; i < num_std_regs; i++)
-    if (str.length - 1 == strlen (std_regs[i].name)
+    if (std_regs[i].name && str.length - 1 == strlen (std_regs[i].name)
        && STREQN (str.ptr + 1, std_regs[i].name, str.length - 1))
       {
        i = std_regs[i].regnum;
index 5a1eaa3..98ec9e2 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-dependent code for the SPARC for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -34,9 +34,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "gdbcore.h"
 
 #ifdef GDB_TARGET_IS_SPARC64
-#define NUM_SPARC_FPREGS 64
+#define FP_REGISTER_BYTES (64 * 4)
 #else
-#define NUM_SPARC_FPREGS 32
+#define FP_REGISTER_BYTES (32 * 4)
+#endif
+
+/* If not defined, assume 32 bit sparc.  */
+#ifndef FP_MAX_REGNUM
+#define FP_MAX_REGNUM (FP0_REGNUM + 32)
 #endif
 
 #define SPARC_INTREG_SIZE (REGISTER_RAW_SIZE (G0_REGNUM))
@@ -607,6 +612,22 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
     *optimized = 0;
 
   addr = 0;
+
+  /* FIXME This code extracted from infcmd.c; should put elsewhere! */
+  if (frame == NULL)
+    {
+      /* error ("No selected frame."); */
+      if (!target_has_registers)
+        error ("The program has no registers now.");
+      if (selected_frame == NULL) 
+        error ("No selected frame.");
+      /* Try to use selected frame */
+      frame = get_prev_frame (selected_frame);  
+      if (frame == 0)
+        error ("Cmd not meaningful in the outermost frame."); 
+    }
+
+
   frame1 = frame->next;
   while (frame1 != NULL)
     {
@@ -614,20 +635,36 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
                         read_register (SP_REGNUM))
          && frame1->pc <= FRAME_FP (frame1))
        {
-         /* Dummy frame.  All but the window regs are in there somewhere. */
-         /* FIXME: The offsets are wrong for sparc64 (eg: 0xa0).  */
+         /* Dummy frame.  All but the window regs are in there somewhere.
+            The window registers are saved on the stack, just like in a
+            normal frame.  */
          if (regnum >= G1_REGNUM && regnum < G1_REGNUM + 7)
            addr = frame1->frame + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
-             - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE);
+             - (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE);
          else if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8)
-           addr = frame1->frame + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
-             - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE);
-         else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + NUM_SPARC_FPREGS)
+           addr = (frame1->prev->bottom
+                   + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+                   + FRAME_SAVED_I0);
+         else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8)
+           addr = (frame1->prev->bottom
+                   + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
+                   + FRAME_SAVED_L0);
+         else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8)
+           addr = frame1->frame + (regnum - O0_REGNUM) * SPARC_INTREG_SIZE
+             - (FP_REGISTER_BYTES + 16 * SPARC_INTREG_SIZE);
+#ifdef FP0_REGNUM
+         else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + 32)
            addr = frame1->frame + (regnum - FP0_REGNUM) * 4
-             - (NUM_SPARC_FPREGS * 4);
+             - (FP_REGISTER_BYTES);
+#ifdef GDB_TARGET_IS_SPARC64
+         else if (regnum >= FP0_REGNUM + 32 && regnum < FP_MAX_REGNUM)
+           addr = frame1->frame + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
+             - (FP_REGISTER_BYTES);
+#endif
+#endif /* FP0_REGNUM */
          else if (regnum >= Y_REGNUM && regnum < NUM_REGS)
            addr = frame1->frame + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
-             - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE);
+             - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE);
        }
       else if (frame1->flat)
        {
@@ -715,8 +752,13 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
 #endif
 
 /* See tm-sparc.h for how this is calculated.  */
+#ifdef FP0_REGNUM
 #define DUMMY_STACK_REG_BUF_SIZE \
 (((8+8+8) * SPARC_INTREG_SIZE) + (32 * REGISTER_RAW_SIZE (FP0_REGNUM)))
+#else
+#define DUMMY_STACK_REG_BUF_SIZE \
+(((8+8+8) * SPARC_INTREG_SIZE) )
+#endif /* FP0_REGNUM */
 #define DUMMY_STACK_SIZE (DUMMY_STACK_REG_BUF_SIZE + DUMMY_REG_SAVE_OFFSET)
 
 void
@@ -743,11 +785,11 @@ sparc_push_dummy_frame ()
                       &register_temp[16 * SPARC_INTREG_SIZE],
                       SPARC_INTREG_SIZE * 8);
 
-  /* ??? The 32 here should be NUM_SPARC_FPREGS, but until we decide what
-     REGISTER_RAW_SIZE should be for fp regs, it's left as is.  */
+#ifdef FP0_REGNUM
   read_register_bytes (REGISTER_BYTE (FP0_REGNUM),
                       &register_temp[24 * SPARC_INTREG_SIZE],
-                      REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+                      FP_REGISTER_BYTES);
+#endif /* FP0_REGNUM */
 
   sp -= DUMMY_STACK_SIZE;
 
@@ -820,19 +862,27 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
       for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++)
        saved_regs_addr->regs[regnum] =
          frame_addr + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
-           - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE);
+           - (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE);
       for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
        saved_regs_addr->regs[regnum] =
          frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
-           - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE);
+           - (FP_REGISTER_BYTES + 16 * SPARC_INTREG_SIZE);
+#ifdef FP0_REGNUM
       for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++)
        saved_regs_addr->regs[regnum] =
          frame_addr + (regnum - FP0_REGNUM) * 4
-           - (NUM_SPARC_FPREGS * 4);
+           - (FP_REGISTER_BYTES);
+#ifdef GDB_TARGET_IS_SPARC64
+      for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++)
+       saved_regs_addr->regs[regnum] =
+         frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
+           - (FP_REGISTER_BYTES);
+#endif
+#endif /* FP0_REGNUM */
       for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
        saved_regs_addr->regs[regnum] =
          frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE - 0xe0;
-           - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE);
+           - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE);
       frame_addr = fi->bottom ?
        fi->bottom : read_register (SP_REGNUM);
     }
@@ -908,11 +958,12 @@ sparc_pop_frame ()
   int regnum;
 
   sparc_frame_find_saved_regs (frame, &fsr);
+#ifdef FP0_REGNUM
   if (fsr.regs[FP0_REGNUM])
     {
-      read_memory (fsr.regs[FP0_REGNUM], raw_buffer, NUM_SPARC_FPREGS * 4);
+      read_memory (fsr.regs[FP0_REGNUM], raw_buffer, FP_REGISTER_BYTES);
       write_register_bytes (REGISTER_BYTE (FP0_REGNUM),
-                           raw_buffer, NUM_SPARC_FPREGS * 4);
+                           raw_buffer, FP_REGISTER_BYTES);
     }
 #ifndef GDB_TARGET_IS_SPARC64
   if (fsr.regs[FPS_REGNUM])
@@ -926,6 +977,7 @@ sparc_pop_frame ()
       write_register_bytes (REGISTER_BYTE (CPS_REGNUM), raw_buffer, 4);
     }
 #endif
+#endif /* FP0_REGNUM */
   if (fsr.regs[G1_REGNUM])
     {
       read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * SPARC_INTREG_SIZE);
@@ -1205,7 +1257,7 @@ prfpregset_t *fpregsetp;
   register int regi;
   char *from;
   
-  for (regi = FP0_REGNUM ; regi < FP0_REGNUM+32 ; regi++)
+  for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
     {
       from = (char *) &fpregsetp->pr_fr.pr_regs[regi-FP0_REGNUM];
       supply_register (regi, from);
@@ -1228,9 +1280,7 @@ int regno;
   char *to;
   char *from;
 
-  /* ??? The 32 should probably be NUM_SPARC_FPREGS, but again we're
-     waiting on what REGISTER_RAW_SIZE should be for fp regs.  */
-  for (regi = FP0_REGNUM ; regi < FP0_REGNUM + 32 ; regi++)
+  for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
     {
       if ((regno == -1) || (regno == regi))
        {
@@ -1360,17 +1410,50 @@ sparc_print_register_hook (regno)
 {
   unsigned LONGEST val;
 
-  if (((unsigned) (regno) - FP0_REGNUM < FP_MAX_REGNUM - FP0_REGNUM)
-       && ((regno) & 1) == 0)
+  /* Handle double/quad versions of lower 32 fp regs.  */
+  if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32
+      && (regno & 1) == 0)
+    {
+      char value[16];
+
+      if (!read_relative_register_raw_bytes (regno, value)
+         && !read_relative_register_raw_bytes (regno + 1, value + 4))
+       {
+         printf_unfiltered ("\t");
+         print_floating (value, builtin_type_double, gdb_stdout);
+       }
+#if 0 /* FIXME: gdb doesn't handle long doubles */
+      if ((regno & 3) == 0)
+       {
+         if (!read_relative_register_raw_bytes (regno + 2, value + 8)
+             && !read_relative_register_raw_bytes (regno + 3, value + 12))
+           {
+             printf_unfiltered ("\t");
+             print_floating (value, builtin_type_long_double, gdb_stdout);
+           }
+       }
+#endif
+      return;
+    }
+
+#if 0 /* FIXME: gdb doesn't handle long doubles */
+  /* Print upper fp regs as long double if appropriate.  */
+  if (regno >= FP0_REGNUM + 32 && regno < FP_MAX_REGNUM
+      /* We test for even numbered regs and not a multiple of 4 because
+        the upper fp regs are recorded as doubles.  */
+      && (regno & 1) == 0)
     {
-      char doublereg[8];               /* two float regs */
-      if (!read_relative_register_raw_bytes ((regno), doublereg))
+      char value[16];
+
+      if (!read_relative_register_raw_bytes (regno, value)
+         && !read_relative_register_raw_bytes (regno + 1, value + 8))
        {
-         printf_unfiltered("\t");
-         print_floating (doublereg, builtin_type_double, gdb_stdout);
+         printf_unfiltered ("\t");
+         print_floating (value, builtin_type_long_double, gdb_stdout);
        }
       return;
     }
+#endif
 
   /* FIXME: Some of these are priviledged registers.
      Not sure how they should be handled.  */
diff --git a/gdb/sparclet-rom.c b/gdb/sparclet-rom.c
new file mode 100644 (file)
index 0000000..98bc27b
--- /dev/null
@@ -0,0 +1,279 @@
+/* Remote target glue for the SPARC Sparclet ROM monitor.
+   Copyright 1995, 1996 Free Software Foundation, Inc.
+
+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.  */
+
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "srec.h"
+#include "symtab.h"
+#include "symfile.h" /* for generic_load */
+
+#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
+#define HAVE_SGTTY
+#endif
+
+#ifdef HAVE_SGTTY
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/types.h> /* Needed by file.h on Sys V */
+#include <sys/file.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+#define USE_GENERIC_LOAD
+#define USE_SW_BREAKS
+
+static struct target_ops sparclet_ops;
+
+static void sparclet_open PARAMS ((char *args, int from_tty));
+
+#ifdef USE_GENERIC_LOAD
+
+static void
+sparclet_load_gen (filename, from_tty) 
+    char *filename;
+    int from_tty;
+{
+  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 */
+}
+
+#else
+
+static void
+sparclet_xmodem_load (desc, file, hashmark)
+     serial_t desc;
+     char *file;
+     int hashmark;
+{
+  bfd *abfd;
+  asection *s;
+  char *buffer;
+  int i;
+
+  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;
+    }
+  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);
+       section_size = bfd_section_size (abfd, s);
+       for (i = 0; i < section_size; i += XMODEM_DATASIZE)
+         {
+           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);
+           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 */
+  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".  */
+
+/*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 */
+
+/* is wim part of psr?? */
+/* monitor wants lower case */
+static char *sparclet_regnames[NUM_REGS] = REGISTER_NAMES;
+
+/* Define the monitor command strings. Since these are passed directly
+   through to a printf style function, we may include formatting
+   strings. We also need a CR or LF on the end.  */
+
+/* need to pause the monitor for timing reasons, so slow it down */
+
+static char *sparclet_inits[] = {"\n\r\r\n", NULL};
+
+static struct monitor_ops sparclet_cmds =
+{
+  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 */
+  /* 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 */
+};
+
+static void
+sparclet_open (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  monitor_open (args, &sparclet_cmds, from_tty);
+}
+
+void
+_initialize_sparclet ()
+{
+  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\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+
+  sparclet_ops.to_open = sparclet_open;
+  add_target (&sparclet_ops);
+}
+
index e95d1db..f9a99ae 100644 (file)
@@ -657,6 +657,8 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow)
 
   new_symfile_objfile (objfile, mainline, from_tty);
 
+  target_new_objfile (objfile);
+
   return (objfile);
 }
 
@@ -920,6 +922,16 @@ generic_load (filename, from_tty)
   bfd *loadfile_bfd;
   time_t start_time, end_time; /* Start and end times of download */
   unsigned long data_count = 0;        /* Number of bytes transferred to memory */
+  int n; 
+  unsigned long load_offset = 0;       /* offset to add to vma for each section */
+  char buf[128];
+
+  /* enable user to specify address for downloading as 2nd arg to load */
+  n = sscanf(filename, "%s 0x%x", buf, &load_offset);
+  if (n > 1 ) 
+    filename = buf;
+  else
+    load_offset = 0;
 
   loadfile_bfd = bfd_openr (filename, gnutarget);
   if (loadfile_bfd == NULL)
@@ -959,6 +971,7 @@ generic_load (filename, from_tty)
              old_chain = make_cleanup (free, buffer);
 
              vma = bfd_get_section_vma (loadfile_bfd, s);
+                 vma += load_offset;
 
              /* Is this really necessary?  I guess it gives the user something
                 to look at during a long download.  */
@@ -979,6 +992,8 @@ generic_load (filename, from_tty)
 
   end_time = time (NULL);
 
+  printf_filtered ("Start address 0x%lx\n", loadfile_bfd->start_address);
+
   /* We were doing this in remote-mips.c, I suspect it is right
      for other targets too.  */
   write_pc (loadfile_bfd->start_address);
@@ -1424,6 +1439,7 @@ clear_symtab_users ()
   current_source_symtab = 0;
   current_source_line = 0;
   clear_pc_function_cache ();
+  target_new_objfile (NULL);
 }
 
 /* clear_symtab_users_once:
@@ -1654,76 +1670,42 @@ start_psymtab_common (objfile, section_offsets,
   return (psymtab);
 }
 \f
-/* Debugging versions of functions that are usually inline macros
-   (see symfile.h).  */
-
-#if !INLINE_ADD_PSYMBOL
-
 /* Add a symbol with a long value to a psymtab.
    Since one arg is a struct, we pass in a ptr and deref it (sigh).  */
 
 void
-add_psymbol_to_list (name, namelength, namespace, class, list, val, language,
-                    objfile)
+add_psymbol_to_list (name, namelength, namespace, class, list, val, coreaddr,
+                    language, objfile)
      char *name;
      int namelength;
      namespace_enum namespace;
      enum address_class class;
      struct psymbol_allocation_list *list;
-     long val;
+     long val;                                 /* Value as a long */
+     CORE_ADDR coreaddr;                       /* Value as a CORE_ADDR */
      enum language language;
      struct objfile *objfile;
 {
   register struct partial_symbol *psym;
   char *buf = alloca (namelength + 1);
-  struct partial_symbol psymbol;
+  /* psymbol is static so that there will be no uninitialized gaps in the
+     structure which might contain random data, causing cache misses in
+     bcache. */
+  static struct partial_symbol psymbol;
 
   /* Create local copy of the partial symbol */
   memcpy (buf, name, namelength);
   buf[namelength] = '\0';
   SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
-  SYMBOL_VALUE (&psymbol) = val;
-  SYMBOL_SECTION (&psymbol) = 0;
-  SYMBOL_LANGUAGE (&psymbol) = language;
-  PSYMBOL_NAMESPACE (&psymbol) = namespace;
-  PSYMBOL_CLASS (&psymbol) = class;
-  SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
-
-  /* Stash the partial symbol away in the cache */
-  psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
-
-  /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
-  if (list->next >= list->list + list->size)
+  /* val and coreaddr are mutually exclusive, one of them *will* be zero */
+  if (val != 0)
     {
-      extend_psymbol_list (list, objfile);
+      SYMBOL_VALUE (&psymbol) = val;
+    }
+  else
+    {
+      SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
     }
-  *list->next++ = psym;
-  OBJSTAT (objfile, n_psyms++);
-}
-
-/* Add a symbol with a CORE_ADDR value to a psymtab. */
-
-void
-add_psymbol_addr_to_list (name, namelength, namespace, class, list, val,
-                         language, objfile)
-     char *name;
-     int namelength;
-     namespace_enum namespace;
-     enum address_class class;
-     struct psymbol_allocation_list *list;
-     CORE_ADDR val;
-     enum language language;
-     struct objfile *objfile;
-{
-  register struct partial_symbol *psym;
-  char *buf = alloca (namelength + 1);
-  struct partial_symbol psymbol;
-
-  /* Create local copy of the partial symbol */
-  memcpy (buf, name, namelength);
-  buf[namelength] = '\0';
-  SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
-  SYMBOL_VALUE_ADDRESS (&psymbol) = val;
   SYMBOL_SECTION (&psymbol) = 0;
   SYMBOL_LANGUAGE (&psymbol) = language;
   PSYMBOL_NAMESPACE (&psymbol) = namespace;
@@ -1742,8 +1724,6 @@ add_psymbol_addr_to_list (name, namelength, namespace, class, list, val,
   OBJSTAT (objfile, n_psyms++);
 }
 
-#endif /* !INLINE_ADD_PSYMBOL */
-
 /* Initialize storage for partial symbols.  */
 
 void