Tue Nov 5 10:21:02 1996 Michael Snyder <msnyder@cleaver.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / findvar.c
index 8f28b90c12a39ec7ab39fa834b49b87c8c1063ca..6cb7d37cab82e215ee33ef220f107809c0cb04c1 100644 (file)
@@ -1,5 +1,5 @@
 /* Find a variable's value in memory, for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -15,7 +15,7 @@ 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "symtab.h"
@@ -25,6 +25,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcore.h"
 #include "inferior.h"
 #include "target.h"
+#include "gdb_string.h"
+#include "floatformat.h"
+
+/* This is used to indicate that we don't know the format of the floating point
+   number.  Typically, this is useful for native ports, where the actual format
+   is irrelevant, since no conversions will be taking place.  */
+
+const struct floatformat floatformat_unknown;
+
+/* Registers we shouldn't try to store.  */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+static void write_register_pid PARAMS ((int regno, LONGEST val, int pid));
 
 /* Basic byte-swapping routines.  GDB has needed these for a long time...
    All extract a target-format integer at ADDR which is LEN bytes long.  */
@@ -47,27 +62,28 @@ extract_signed_integer (addr, len)
   unsigned char *startaddr = (unsigned char *)addr;
   unsigned char *endaddr = startaddr + len;
 
-  if (len > sizeof (LONGEST))
+  if (len > (int) sizeof (LONGEST))
     error ("\
 That operation is not available on integers of more than %d bytes.",
           sizeof (LONGEST));
 
   /* Start at the most significant end of the integer, and work towards
      the least significant.  */
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-  p = startaddr;
-#else
-  p = endaddr - 1;
-#endif
-  /* Do the sign extension once at the start.  */
-  retval = ((LONGEST)*p ^ 0x80) - 0x80;
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-  for (++p; p < endaddr; ++p)
-#else
-  for (--p; p >= startaddr; --p)
-#endif
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
     {
-      retval = (retval << 8) | *p;
+      p = startaddr;
+      /* Do the sign extension once at the start.  */
+      retval = ((LONGEST)*p ^ 0x80) - 0x80;
+      for (++p; p < endaddr; ++p)
+       retval = (retval << 8) | *p;
+    }
+  else
+    {
+      p = endaddr - 1;
+      /* Do the sign extension once at the start.  */
+      retval = ((LONGEST)*p ^ 0x80) - 0x80;
+      for (--p; p >= startaddr; --p)
+       retval = (retval << 8) | *p;
     }
   return retval;
 }
@@ -82,7 +98,7 @@ extract_unsigned_integer (addr, len)
   unsigned char *startaddr = (unsigned char *)addr;
   unsigned char *endaddr = startaddr + len;
 
-  if (len > sizeof (unsigned LONGEST))
+  if (len > (int) sizeof (unsigned LONGEST))
     error ("\
 That operation is not available on integers of more than %d bytes.",
           sizeof (unsigned LONGEST));
@@ -90,17 +106,71 @@ That operation is not available on integers of more than %d bytes.",
   /* Start at the most significant end of the integer, and work towards
      the least significant.  */
   retval = 0;
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-  for (p = startaddr; p < endaddr; ++p)
-#else
-  for (p = endaddr - 1; p >= startaddr; --p)
-#endif
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
     {
-      retval = (retval << 8) | *p;
+      for (p = startaddr; p < endaddr; ++p)
+       retval = (retval << 8) | *p;
+    }
+  else
+    {
+      for (p = endaddr - 1; p >= startaddr; --p)
+       retval = (retval << 8) | *p;
     }
   return retval;
 }
 
+/* Sometimes a long long unsigned integer can be extracted as a
+   LONGEST value.  This is done so that we can print these values
+   better.  If this integer can be converted to a LONGEST, this
+   function returns 1 and sets *PVAL.  Otherwise it returns 0.  */
+
+int
+extract_long_unsigned_integer (addr, orig_len, pval)
+     PTR addr;
+     int orig_len;
+     LONGEST *pval;
+{
+  char *p, *first_addr;
+  int len;
+
+  len = orig_len;
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+    {
+      for (p = (char *) addr;
+          len > (int) sizeof (LONGEST) && p < (char *) addr + orig_len;
+          p++)
+       {
+         if (*p == 0)
+           len--;
+         else
+           break;
+       }
+      first_addr = p;
+    }
+  else
+    {
+      first_addr = (char *) addr;
+      for (p = (char *) addr + orig_len - 1;
+          len > (int) sizeof (LONGEST) && p >= (char *) addr;
+          p--)
+       {
+         if (*p == 0)
+           len--;
+         else
+           break;
+       }
+    }
+
+  if (len <= (int) sizeof (LONGEST))
+    {
+      *pval = (LONGEST) extract_unsigned_integer (first_addr,
+                                                 sizeof (LONGEST));
+      return 1;
+    }
+
+  return 0;
+}
+
 CORE_ADDR
 extract_address (addr, len)
      PTR addr;
@@ -123,14 +193,21 @@ store_signed_integer (addr, len, val)
 
   /* Start at the least significant end of the integer, and work towards
      the most significant.  */
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-  for (p = endaddr - 1; p >= startaddr; --p)
-#else
-  for (p = startaddr; p < endaddr; ++p)
-#endif
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
     {
-      *p = val & 0xff;
-      val >>= 8;
+      for (p = endaddr - 1; p >= startaddr; --p)
+       {
+         *p = val & 0xff;
+         val >>= 8;
+       }
+    }
+  else
+    {
+      for (p = startaddr; p < endaddr; ++p)
+       {
+         *p = val & 0xff;
+         val >>= 8;
+       }
     }
 }
 
@@ -146,14 +223,21 @@ store_unsigned_integer (addr, len, val)
 
   /* Start at the least significant end of the integer, and work towards
      the most significant.  */
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-  for (p = endaddr - 1; p >= startaddr; --p)
-#else
-  for (p = startaddr; p < endaddr; ++p)
-#endif
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
     {
-      *p = val & 0xff;
-      val >>= 8;
+      for (p = endaddr - 1; p >= startaddr; --p)
+       {
+         *p = val & 0xff;
+         val >>= 8;
+       }
+    }
+  else
+    {
+      for (p = startaddr; p < endaddr; ++p)
+       {
+         *p = val & 0xff;
+         val >>= 8;
+       }
     }
 }
 
@@ -168,36 +252,34 @@ store_address (addr, len, val)
   store_unsigned_integer (addr, len, (LONGEST)val);
 }
 \f
-/* Swap LEN bytes at BUFFER between target and host byte-order.  This is
-   the wrong way to do byte-swapping because it assumes that you have a way
-   to have a host variable of exactly the right size.  Once extract_floating
-   and store_floating have been fixed, this can go away.  */
-#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
-#define SWAP_TARGET_AND_HOST(buffer,len)
-#else /* Target and host byte order differ.  */
-#define SWAP_TARGET_AND_HOST(buffer,len) \
-  {                                                                     \
-    char tmp;                                                           \
-    char *p = (char *)(buffer);                                                 \
-    char *q = ((char *)(buffer)) + len - 1;                             \
-    for (; p < q; p++, q--)                                             \
-      {                                                                         \
-        tmp = *q;                                                       \
-        *q = *p;                                                        \
-        *p = tmp;                                                       \
-      }                                                                         \
-  }
-#endif /* Target and host byte order differ.  */
-
-/* There are many problems with floating point cross-debugging.
+/* Swap LEN bytes at BUFFER between target and host byte-order.  */
+#define SWAP_FLOATING(buffer,len) \
+  do                                                                    \
+    {                                                                   \
+      if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER)                         \
+        {                                                               \
+          char tmp;                                                     \
+          char *p = (char *)(buffer);                                   \
+          char *q = ((char *)(buffer)) + len - 1;                       \
+          for (; p < q; p++, q--)                                       \
+            {                                                           \
+              tmp = *q;                                                 \
+              *q = *p;                                                  \
+              *p = tmp;                                                 \
+            }                                                           \
+        }                                                               \
+    }                                                                   \
+  while (0)
+
+/* There are various problems with the extract_floating and store_floating
+   routines.
 
    1.  These routines only handle byte-swapping, not conversion of
    formats.  So if host is IEEE floating and target is VAX floating,
    or vice-versa, it loses.  This means that we can't (yet) use these
    routines for extendeds.  Extendeds are handled by
-   REGISTER_CONVERTIBLE.  What we want is a fixed version of
-   ieee-float.c (the current version can't deal with single or double,
-   and I suspect it is probably broken for some extendeds too).
+   REGISTER_CONVERTIBLE.  What we want is to use floatformat.h, but that
+   doesn't yet handle VAX floating at all.
 
    2.  We can't deal with it if there is more than one floating point
    format in use.  This has to be fixed at the unpack_double level.
@@ -205,47 +287,91 @@ store_address (addr, len, val)
    3.  We probably should have a LONGEST_DOUBLE or DOUBLEST or whatever
    we want to call it which is long double where available.  */
 
-double
+DOUBLEST
 extract_floating (addr, len)
      PTR addr;
      int len;
 {
+  DOUBLEST dretval;
+
   if (len == sizeof (float))
     {
-      float retval;
-      memcpy (&retval, addr, sizeof (retval));
-      SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
-      return retval;
+      if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
+       {
+         float retval;
+
+         memcpy (&retval, addr, sizeof (retval));
+         return retval;
+       }
+      else
+       FLOATFORMAT_TO_DOUBLEST (TARGET_FLOAT_FORMAT, addr, &dretval);
     }
   else if (len == sizeof (double))
     {
-      double retval;
-      memcpy (&retval, addr, sizeof (retval));
-      SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
-      return retval;
+      if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
+       {
+         double retval;
+
+         memcpy (&retval, addr, sizeof (retval));
+         return retval;
+       }
+      else
+       FLOATFORMAT_TO_DOUBLEST (TARGET_DOUBLE_FORMAT, addr, &dretval);
+    }
+  else if (len == sizeof (DOUBLEST))
+    {
+      if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
+       {
+         DOUBLEST retval;
+
+         memcpy (&retval, addr, sizeof (retval));
+         return retval;
+       }
+      else
+       FLOATFORMAT_TO_DOUBLEST (TARGET_LONG_DOUBLE_FORMAT, addr, &dretval);
     }
   else
     {
       error ("Can't deal with a floating point number of %d bytes.", len);
     }
+
+  return dretval;
 }
 
 void
 store_floating (addr, len, val)
      PTR addr;
      int len;
-     double val;
+     DOUBLEST val;
 {
   if (len == sizeof (float))
     {
-      float floatval = val;
-      SWAP_TARGET_AND_HOST (&floatval, sizeof (floatval));
-      memcpy (addr, &floatval, sizeof (floatval));
+      if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
+       {
+         float floatval = val;
+
+         memcpy (addr, &floatval, sizeof (floatval));
+       }
+      else
+       FLOATFORMAT_FROM_DOUBLEST (TARGET_FLOAT_FORMAT, &val, addr);
     }
   else if (len == sizeof (double))
     {
-      SWAP_TARGET_AND_HOST (&val, sizeof (val));
-      memcpy (addr, &val, sizeof (val));
+      if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
+       {
+         double doubleval = val;
+
+         memcpy (addr, &doubleval, sizeof (doubleval));
+       }
+      else
+       FLOATFORMAT_FROM_DOUBLEST (TARGET_DOUBLE_FORMAT, &val, addr);
+    }
+  else if (len == sizeof (DOUBLEST))
+    {
+      if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
+       memcpy (addr, &val, sizeof (val));
+      else
+       FLOATFORMAT_FROM_DOUBLEST (TARGET_LONG_DOUBLE_FORMAT, &val, addr);
     }
   else
     {
@@ -262,16 +388,15 @@ store_floating (addr, len, val)
 
 CORE_ADDR
 find_saved_register (frame, regnum)
-     FRAME frame;
+     struct frame_info *frame;
      int regnum;
 {
-  struct frame_info *fi;
   struct frame_saved_regs saved_regs;
 
-  register FRAME frame1 = 0;
+  register struct frame_info *frame1 = NULL;
   register CORE_ADDR addr = 0;
 
-  if (frame == 0)              /* No regs saved if want current frame */
+  if (frame == NULL)           /* No regs saved if want current frame */
     return 0;
 
 #ifdef HAVE_REGISTER_WINDOWS
@@ -291,20 +416,17 @@ find_saved_register (frame, regnum)
      stack pointer saved for *this* frame; this is returned from the
      next frame.  */
      
-
   if (REGISTER_IN_WINDOW_P(regnum))
     {
       frame1 = get_next_frame (frame);
-      if (!frame1) return 0;   /* Registers of this frame are
-                                  active.  */
+      if (!frame1) return 0;   /* Registers of this frame are active.  */
       
       /* Get the SP from the next frame in; it will be this
         current frame.  */
       if (regnum != SP_REGNUM)
        frame1 = frame; 
          
-      fi = get_frame_info (frame1);
-      get_frame_saved_regs (fi, &saved_regs);
+      get_frame_saved_regs (frame1, &saved_regs);
       return saved_regs.regs[regnum];  /* ... which might be zero */
     }
 #endif /* HAVE_REGISTER_WINDOWS */
@@ -319,8 +441,7 @@ find_saved_register (frame, regnum)
       frame1 = get_prev_frame (frame1);
       if (frame1 == 0 || frame1 == frame)
        break;
-      fi = get_frame_info (frame1);
-      get_frame_saved_regs (fi, &saved_regs);
+      get_frame_saved_regs (frame1, &saved_regs);
       if (saved_regs.regs[regnum])
        addr = saved_regs.regs[regnum];
     }
@@ -348,11 +469,15 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
      char *raw_buffer;
      int *optimized;
      CORE_ADDR *addrp;
-     FRAME frame;
+     struct frame_info *frame;
      int regnum;
      enum lval_type *lval;
 {
   CORE_ADDR addr;
+
+  if (!target_has_registers)
+    error ("No registers.");
+
   /* Normal systems don't optimize out things with register numbers.  */
   if (optimized != NULL)
     *optimized = 0;
@@ -417,20 +542,20 @@ read_relative_register_raw_bytes (regnum, myaddr)
    in its virtual format, with the type specified by
    REGISTER_VIRTUAL_TYPE.  */
 
-value
+value_ptr
 value_of_register (regnum)
      int regnum;
 {
   CORE_ADDR addr;
   int optim;
-  register value val;
+  register value_ptr reg_val;
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
   enum lval_type lval;
 
   get_saved_register (raw_buffer, &optim, &addr,
                      selected_frame, regnum, &lval);
 
-  val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+  reg_val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
 
   /* Convert raw data to virtual format if necessary.  */
 
@@ -438,17 +563,17 @@ value_of_register (regnum)
   if (REGISTER_CONVERTIBLE (regnum))
     {
       REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
-                                  raw_buffer, VALUE_CONTENTS_RAW (val));
+                                  raw_buffer, VALUE_CONTENTS_RAW (reg_val));
     }
   else
 #endif
-    memcpy (VALUE_CONTENTS_RAW (val), raw_buffer,
+    memcpy (VALUE_CONTENTS_RAW (reg_val), raw_buffer,
            REGISTER_RAW_SIZE (regnum));
-  VALUE_LVAL (val) = lval;
-  VALUE_ADDRESS (val) = addr;
-  VALUE_REGNO (val) = regnum;
-  VALUE_OPTIMIZED_OUT (val) = optim;
-  return val;
+  VALUE_LVAL (reg_val) = lval;
+  VALUE_ADDRESS (reg_val) = addr;
+  VALUE_REGNO (reg_val) = regnum;
+  VALUE_OPTIMIZED_OUT (reg_val) = optim;
+  return reg_val;
 }
 \f
 /* Low level examining and depositing of registers.
@@ -466,13 +591,25 @@ char registers[REGISTER_BYTES + /* SLOP */ 256];
 /* Nonzero if that register has been fetched.  */
 char register_valid[NUM_REGS];
 
+/* The thread/process associated with the current set of registers.  For now,
+   -1 is special, and means `no current process'.  */
+int registers_pid = -1;
+
 /* Indicate that registers may have changed, so invalidate the cache.  */
+
 void
 registers_changed ()
 {
   int i;
-  for (i = 0; i < NUM_REGS; i++)
+  int numregs = ARCH_NUM_REGS;
+
+  registers_pid = -1;
+
+  for (i = 0; i < numregs; i++)
     register_valid[i] = 0;
+
+  if (registers_changed_hook)
+    registers_changed_hook ();
 }
 
 /* Indicate that all registers have been fetched, so mark them all valid.  */
@@ -480,30 +617,76 @@ void
 registers_fetched ()
 {
   int i;
-  for (i = 0; i < NUM_REGS; i++)
+  int numregs = ARCH_NUM_REGS;
+  for (i = 0; i < numregs; i++)
     register_valid[i] = 1;
 }
 
-/* Copy LEN bytes of consecutive data from registers
-   starting with the REGBYTE'th byte of register data
+/* read_register_bytes and write_register_bytes are generally a *BAD* idea.
+   They are inefficient because they need to check for partial updates, which
+   can only be done by scanning through all of the registers and seeing if the
+   bytes that are being read/written fall inside of an invalid register.  [The
+    main reason this is necessary is that register sizes can vary, so a simple
+    index won't suffice.]  It is far better to call read_register_gen if you
+   want to get at the raw register contents, as it only takes a regno as an
+   argument, and therefore can't do a partial register update.  It would also
+   be good to have a write_register_gen for similar reasons.
+
+   Prior to the recent fixes to check for partial updates, both read and
+   write_register_bytes always checked to see if any registers were stale, and
+   then called target_fetch_registers (-1) to update the whole set.  This
+   caused really slowed things down for remote targets.  */
+
+/* Copy INLEN bytes of consecutive data from registers
+   starting with the INREGBYTE'th byte of register data
    into memory at MYADDR.  */
 
 void
-read_register_bytes (regbyte, myaddr, len)
-     int regbyte;
+read_register_bytes (inregbyte, myaddr, inlen)
+     int inregbyte;
      char *myaddr;
-     int len;
+     int inlen;
 {
-  /* Fetch all registers.  */
-  int i;
-  for (i = 0; i < NUM_REGS; i++)
-    if (!register_valid[i])
-      {
-       target_fetch_registers (-1);
-       break;
-      }
+  int inregend = inregbyte + inlen;
+  int regno;
+
+  if (registers_pid != inferior_pid)
+    {
+      registers_changed ();
+      registers_pid = inferior_pid;
+    }
+
+  /* See if we are trying to read bytes from out-of-date registers.  If so,
+     update just those registers.  */
+
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      int regstart, regend;
+      int startin, endin;
+
+      if (register_valid[regno])
+       continue;
+
+      regstart = REGISTER_BYTE (regno);
+      regend = regstart + REGISTER_RAW_SIZE (regno);
+
+      startin = regstart >= inregbyte && regstart < inregend;
+      endin = regend > inregbyte && regend <= inregend;
+
+      if (!startin && !endin)
+       continue;
+
+      /* We've found an invalid register where at least one byte will be read.
+        Update it from the target.  */
+
+      target_fetch_registers (regno);
+
+      if (!register_valid[regno])
+       error ("read_register_bytes:  Couldn't update register %d.", regno);
+    }
+
   if (myaddr != NULL)
-    memcpy (myaddr, &registers[regbyte], len);
+    memcpy (myaddr, &registers[inregbyte], inlen);
 }
 
 /* Read register REGNO into memory at MYADDR, which must be large enough
@@ -515,25 +698,111 @@ read_register_gen (regno, myaddr)
      int regno;
      char *myaddr;
 {
+  if (registers_pid != inferior_pid)
+    {
+      registers_changed ();
+      registers_pid = inferior_pid;
+    }
+
   if (!register_valid[regno])
     target_fetch_registers (regno);
   memcpy (myaddr, &registers[REGISTER_BYTE (regno)],
          REGISTER_RAW_SIZE (regno));
 }
 
-/* Copy LEN bytes of consecutive data from memory at MYADDR
-   into registers starting with the REGBYTE'th byte of register data.  */
+/* Write register REGNO at MYADDR to the target.  MYADDR points at
+   REGISTER_RAW_BYTES(REGNO), which must be in target byte-order.  */
 
 void
-write_register_bytes (regbyte, myaddr, len)
-     int regbyte;
+write_register_gen (regno, myaddr)
+     int regno;
      char *myaddr;
-     int len;
 {
-  /* Make sure the entire registers array is valid.  */
-  read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
-  memcpy (&registers[regbyte], myaddr, len);
-  target_store_registers (-1);
+  int size;
+
+  /* On the sparc, writing %g0 is a no-op, so we don't even want to change
+     the registers array if something writes to this register.  */
+  if (CANNOT_STORE_REGISTER (regno))
+    return;
+
+  if (registers_pid != inferior_pid)
+    {
+      registers_changed ();
+      registers_pid = inferior_pid;
+    }
+
+  size = REGISTER_RAW_SIZE(regno);
+
+  /* If we have a valid copy of the register, and new value == old value,
+     then don't bother doing the actual store. */
+
+  if (register_valid [regno]
+      && memcmp (&registers[REGISTER_BYTE (regno)], myaddr, size) == 0)
+    return;
+  
+  target_prepare_to_store ();
+
+  memcpy (&registers[REGISTER_BYTE (regno)], myaddr, size);
+
+  register_valid [regno] = 1;
+
+  target_store_registers (regno);
+}
+
+/* Copy INLEN bytes of consecutive data from memory at MYADDR
+   into registers starting with the MYREGSTART'th byte of register data.  */
+
+void
+write_register_bytes (myregstart, myaddr, inlen)
+     int myregstart;
+     char *myaddr;
+     int inlen;
+{
+  int myregend = myregstart + inlen;
+  int regno;
+
+  target_prepare_to_store ();
+
+  /* Scan through the registers updating any that are covered by the range
+     myregstart<=>myregend using write_register_gen, which does nice things
+     like handling threads, and avoiding updates when the new and old contents
+     are the same.  */
+
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      int regstart, regend;
+      int startin, endin;
+      char regbuf[MAX_REGISTER_RAW_SIZE];
+
+      regstart = REGISTER_BYTE (regno);
+      regend = regstart + REGISTER_RAW_SIZE (regno);
+
+      startin = regstart >= myregstart && regstart < myregend;
+      endin = regend > myregstart && regend <= myregend;
+
+      if (!startin && !endin)
+       continue;               /* Register is completely out of range */
+
+      if (startin && endin)    /* register is completely in range */
+       {
+         write_register_gen (regno, myaddr + (regstart - myregstart));
+         continue;
+       }
+
+      /* We may be doing a partial update of an invalid register.  Update it
+        from the target before scribbling on it.  */
+      read_register_gen (regno, regbuf);
+
+      if (startin)
+       memcpy (registers + regstart,
+               myaddr + regstart - myregstart,
+               myregend - regstart);
+      else                     /* endin */
+       memcpy (registers + myregstart,
+               myaddr,
+               regend - myregstart);
+      target_store_registers (regno);
+    }
 }
 
 /* Return the raw contents of register REGNO, regarding it as an integer.  */
@@ -543,6 +812,12 @@ CORE_ADDR
 read_register (regno)
      int regno;
 {
+  if (registers_pid != inferior_pid)
+    {
+      registers_changed ();
+      registers_pid = inferior_pid;
+    }
+
   if (!register_valid[regno])
     target_fetch_registers (regno);
 
@@ -550,13 +825,28 @@ read_register (regno)
                          REGISTER_RAW_SIZE(regno));
 }
 
-/* Registers we shouldn't try to store.  */
-#if !defined (CANNOT_STORE_REGISTER)
-#define CANNOT_STORE_REGISTER(regno) 0
-#endif
+CORE_ADDR
+read_register_pid (regno, pid)
+     int regno, pid;
+{
+  int save_pid;
+  CORE_ADDR retval;
+
+  if (pid == inferior_pid)
+    return read_register (regno);
+
+  save_pid = inferior_pid;
+
+  inferior_pid = pid;
+
+  retval = read_register (regno);
+
+  inferior_pid = save_pid;
+
+  return retval;
+}
 
 /* Store VALUE, into the raw contents of register number REGNO.  */
-/* FIXME: The val arg should probably be a LONGEST.  */
 
 void
 write_register (regno, val)
@@ -571,6 +861,12 @@ write_register (regno, val)
   if (CANNOT_STORE_REGISTER (regno))
     return;
 
+  if (registers_pid != inferior_pid)
+    {
+      registers_changed ();
+      registers_pid = inferior_pid;
+    }
+
   size = REGISTER_RAW_SIZE(regno);
   buf = alloca (size);
   store_signed_integer (buf, size, (LONGEST) val);
@@ -578,11 +874,9 @@ write_register (regno, val)
   /* If we have a valid copy of the register, and new value == old value,
      then don't bother doing the actual store. */
 
-  if (register_valid [regno]) 
-    {
-      if (memcmp (&registers[REGISTER_BYTE (regno)], buf, size) == 0)
-       return;
-    }
+  if (register_valid [regno]
+      && memcmp (&registers[REGISTER_BYTE (regno)], buf, size) == 0)
+    return;
   
   target_prepare_to_store ();
 
@@ -593,6 +887,29 @@ write_register (regno, val)
   target_store_registers (regno);
 }
 
+static void
+write_register_pid (regno, val, pid)
+     int regno;
+     LONGEST val;
+     int pid;
+{
+  int save_pid;
+
+  if (pid == inferior_pid)
+    {
+      write_register (regno, val);
+      return;
+    }
+
+  save_pid = inferior_pid;
+
+  inferior_pid = pid;
+
+  write_register (regno, val);
+
+  inferior_pid = save_pid;
+}
+
 /* Record that register REGNO contains VAL.
    This is used when the value is obtained from the inferior or core dump,
    so there is no need to store the value there.  */
@@ -602,6 +919,12 @@ supply_register (regno, val)
      int regno;
      char *val;
 {
+  if (registers_pid != inferior_pid)
+    {
+      registers_changed ();
+      registers_pid = inferior_pid;
+    }
+
   register_valid[regno] = 1;
   memcpy (&registers[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
 
@@ -611,6 +934,111 @@ supply_register (regno, val)
   CLEAN_UP_REGISTER_VALUE(regno, &registers[REGISTER_BYTE(regno)]);
 #endif
 }
+
+
+/* This routine is getting awfully cluttered with #if's.  It's probably
+   time to turn this into READ_PC and define it in the tm.h file.
+   Ditto for write_pc.  */
+
+CORE_ADDR
+read_pc ()
+{
+#ifdef TARGET_READ_PC
+  return TARGET_READ_PC (inferior_pid);
+#else
+  return ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, inferior_pid));
+#endif
+}
+
+CORE_ADDR
+read_pc_pid (pid)
+     int pid;
+{
+#ifdef TARGET_READ_PC
+  return TARGET_READ_PC (pid);
+#else
+  return ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, pid));
+#endif
+}
+
+void
+write_pc (val)
+     CORE_ADDR val;
+{
+#ifdef TARGET_WRITE_PC
+  TARGET_WRITE_PC (val, inferior_pid);
+#else
+  write_register_pid (PC_REGNUM, val, inferior_pid);
+#ifdef NPC_REGNUM
+  write_register_pid (NPC_REGNUM, val + 4, inferior_pid);
+#ifdef NNPC_REGNUM
+  write_register_pid (NNPC_REGNUM, val + 8, inferior_pid);
+#endif
+#endif
+#endif
+}
+
+void
+write_pc_pid (val, pid)
+     CORE_ADDR val;
+     int pid;
+{
+#ifdef TARGET_WRITE_PC
+  TARGET_WRITE_PC (val, pid);
+#else
+  write_register_pid (PC_REGNUM, val, pid);
+#ifdef NPC_REGNUM
+  write_register_pid (NPC_REGNUM, val + 4, pid);
+#ifdef NNPC_REGNUM
+  write_register_pid (NNPC_REGNUM, val + 8, pid);
+#endif
+#endif
+#endif
+}
+
+/* Cope with strage ways of getting to the stack and frame pointers */
+
+CORE_ADDR
+read_sp ()
+{
+#ifdef TARGET_READ_SP
+  return TARGET_READ_SP ();
+#else
+  return read_register (SP_REGNUM);
+#endif
+}
+
+void
+write_sp (val)
+     CORE_ADDR val;
+{
+#ifdef TARGET_WRITE_SP
+  TARGET_WRITE_SP (val);
+#else
+  write_register (SP_REGNUM, val);
+#endif
+}
+
+CORE_ADDR
+read_fp ()
+{
+#ifdef TARGET_READ_FP
+  return TARGET_READ_FP ();
+#else
+  return read_register (FP_REGNUM);
+#endif
+}
+
+void
+write_fp (val)
+     CORE_ADDR val;
+{
+#ifdef TARGET_WRITE_FP
+  TARGET_WRITE_FP (val);
+#else
+  write_register (FP_REGNUM, val);
+#endif
+}
 \f
 /* Will calling read_var_value or locate_var_value on SYM end
    up caring what frame it is being evaluated relative to?  SYM must
@@ -646,6 +1074,7 @@ symbol_read_needs_frame (sym)
 
     case LOC_BLOCK:
     case LOC_CONST_BYTES:
+    case LOC_UNRESOLVED:
     case LOC_OPTIMIZED_OUT:
       return 0;
     }
@@ -658,13 +1087,12 @@ symbol_read_needs_frame (sym)
    If the variable cannot be found, return a zero pointer.
    If FRAME is NULL, use the selected_frame.  */
 
-value
+value_ptr
 read_var_value (var, frame)
      register struct symbol *var;
-     FRAME frame;
+     struct frame_info *frame;
 {
-  register value v;
-  struct frame_info *fi;
+  register value_ptr v;
   struct type *type = SYMBOL_TYPE (var);
   CORE_ADDR addr;
   register int len;
@@ -673,7 +1101,7 @@ read_var_value (var, frame)
   VALUE_LVAL (v) = lval_memory;        /* The most likely possibility.  */
   len = TYPE_LENGTH (type);
 
-  if (frame == 0) frame = selected_frame;
+  if (frame == NULL) frame = selected_frame;
 
   switch (SYMBOL_CLASS (var))
     {
@@ -704,26 +1132,20 @@ read_var_value (var, frame)
       break;
 
     case LOC_ARG:
-      fi = get_frame_info (frame);
-      if (fi == NULL)
+      if (frame == NULL)
        return 0;
-      addr = FRAME_ARGS_ADDRESS (fi);
+      addr = FRAME_ARGS_ADDRESS (frame);
       if (!addr)
-       {
-         return 0;
-       }
+       return 0;
       addr += SYMBOL_VALUE (var);
       break;
 
     case LOC_REF_ARG:
-      fi = get_frame_info (frame);
-      if (fi == NULL)
+      if (frame == NULL)
        return 0;
-      addr = FRAME_ARGS_ADDRESS (fi);
+      addr = FRAME_ARGS_ADDRESS (frame);
       if (!addr)
-       {
-         return 0;
-       }
+       return 0;
       addr += SYMBOL_VALUE (var);
       addr = read_memory_unsigned_integer
        (addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
@@ -731,10 +1153,9 @@ read_var_value (var, frame)
 
     case LOC_LOCAL:
     case LOC_LOCAL_ARG:
-      fi = get_frame_info (frame);
-      if (fi == NULL)
+      if (frame == NULL)
        return 0;
-      addr = FRAME_LOCALS_ADDRESS (fi);
+      addr = FRAME_LOCALS_ADDRESS (frame);
       addr += SYMBOL_VALUE (var);
       break;
 
@@ -767,15 +1188,28 @@ read_var_value (var, frame)
          return 0;
        b = get_frame_block (frame);
        
-       v = value_from_register (type, SYMBOL_VALUE (var), frame);
 
        if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
          {
-           addr = *(CORE_ADDR *)VALUE_CONTENTS (v);
+           addr =
+             value_as_pointer (value_from_register (lookup_pointer_type (type),
+                                                    SYMBOL_VALUE (var),
+                                                    frame));
            VALUE_LVAL (v) = lval_memory;
          }
        else
-         return v;
+         return value_from_register (type, SYMBOL_VALUE (var), frame);
+      }
+      break;
+
+    case LOC_UNRESOLVED:
+      {
+       struct minimal_symbol *msym;
+
+       msym = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
+       if (msym == NULL)
+         return 0;
+       addr = SYMBOL_VALUE_ADDRESS (msym);
       }
       break;
 
@@ -797,21 +1231,24 @@ read_var_value (var, frame)
 /* Return a value of type TYPE, stored in register REGNUM, in frame
    FRAME. */
 
-value
+value_ptr
 value_from_register (type, regnum, frame)
      struct type *type;
      int regnum;
-     FRAME frame;
+     struct frame_info *frame;
 {
   char raw_buffer [MAX_REGISTER_RAW_SIZE];
   CORE_ADDR addr;
   int optim;
-  value v = allocate_value (type);
-  int len = TYPE_LENGTH (type);
+  value_ptr v = allocate_value (type);
   char *value_bytes = 0;
   int value_bytes_copied = 0;
   int num_storage_locs;
   enum lval_type lval;
+  int len;
+
+  CHECK_TYPEDEF (type);
+  len = TYPE_LENGTH (type);
 
   VALUE_REGNO (v) = regnum;
 
@@ -986,13 +1423,11 @@ value_from_register (type, regnum, frame)
     {
       /* Raw and virtual formats are the same for this register.  */
 
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
-      if (len < REGISTER_RAW_SIZE (regnum))
+      if (TARGET_BYTE_ORDER == BIG_ENDIAN && len < REGISTER_RAW_SIZE (regnum))
        {
          /* Big-endian, and we want less than full size.  */
          VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
        }
-#endif
 
       memcpy (VALUE_CONTENTS_RAW (v), raw_buffer + VALUE_OFFSET (v), len);
     }
@@ -1005,14 +1440,14 @@ value_from_register (type, regnum, frame)
    return a (pointer to a) struct value containing the properly typed
    address.  */
 
-value
+value_ptr
 locate_var_value (var, frame)
      register struct symbol *var;
-     FRAME frame;
+     struct frame_info *frame;
 {
   CORE_ADDR addr = 0;
   struct type *type = SYMBOL_TYPE (var);
-  value lazy_value;
+  value_ptr lazy_value;
 
   /* Evaluate it first; if the result is a memory address, we're fine.
      Lazy evaluation pays off here. */
This page took 0.035026 seconds and 4 git commands to generate.