2002-11-06 Andrew Cagney <ac131313@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Thu, 7 Nov 2002 02:45:27 +0000 (02:45 +0000)
committerAndrew Cagney <cagney@redhat.com>
Thu, 7 Nov 2002 02:45:27 +0000 (02:45 +0000)
* valops.c (value_assign): Merge lval_register case into
lval_reg_frame_relative.  Use frame_register and
regcache_cooked_write instead of get_saved_register and
write_register_bytes.  After flushing the register cache, try to
re-select the selected frame.

gdb/ChangeLog
gdb/valops.c

index 7f6838188f69f09ad50ca007d2a877e471d372c3..006522662f44999c74cfba9ff7a922aac527d208 100644 (file)
@@ -1,3 +1,11 @@
+2002-11-06  Andrew Cagney  <ac131313@redhat.com>
+
+       * valops.c (value_assign): Merge lval_register case into
+       lval_reg_frame_relative.  Use frame_register and
+       regcache_cooked_write instead of get_saved_register and
+       write_register_bytes.  After flushing the register cache, try to
+       re-select the selected frame.
+
 2002-11-06  Andrew Cagney  <ac131313@redhat.com>
 
        * regcache.h (deprecated_register_valid): Rename register_valid.
index 6fcd8243248c472b1e8e136b7a05bd3017016188..2249e8a15d74b1efa88afde41ad9baa93d0317c5 100644 (file)
@@ -630,132 +630,120 @@ value_assign (struct value *toval, struct value *fromval)
       }
       break;
 
-    case lval_register:
-      if (VALUE_BITSIZE (toval))
-       {
-         char buffer[sizeof (LONGEST)];
-         int len =
-               REGISTER_RAW_SIZE (VALUE_REGNO (toval)) - VALUE_OFFSET (toval);
-
-         if (len > (int) sizeof (LONGEST))
-           error ("Can't handle bitfields in registers larger than %d bits.",
-                  (int) sizeof (LONGEST) * HOST_CHAR_BIT);
-
-         if (VALUE_BITPOS (toval) + VALUE_BITSIZE (toval)
-             > len * HOST_CHAR_BIT)
-           /* Getting this right would involve being very careful about
-              byte order.  */
-           error ("Can't assign to bitfields that cross register "
-                  "boundaries.");
-
-         read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
-                              buffer, len);
-         modify_field (buffer, value_as_long (fromval),
-                       VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
-         write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
-                               buffer, len);
-       }
-      else if (use_buffer)
-       write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
-                             raw_buffer, use_buffer);
-      else
-       {
-         /* Do any conversion necessary when storing this type to more
-            than one register.  */
-#ifdef REGISTER_CONVERT_FROM_TYPE
-         memcpy (raw_buffer, VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
-         REGISTER_CONVERT_FROM_TYPE (VALUE_REGNO (toval), type, raw_buffer);
-         write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
-                               raw_buffer, TYPE_LENGTH (type));
-#else
-         write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
-                             VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
-#endif
-       }
-
-      target_changed_event ();
-
-      /* Assigning to the stack pointer, frame pointer, and other
-         (architecture and calling convention specific) registers may
-         cause the frame cache to be out of date.  We just do this
-         on all assignments to registers for simplicity; I doubt the slowdown
-         matters.  */
-      reinit_frame_cache ();
-      break;
-
     case lval_reg_frame_relative:
+    case lval_register:
       {
+       struct frame_id old_frame;
        /* value is stored in a series of registers in the frame
           specified by the structure.  Copy that value out, modify
           it, and copy it back in.  */
-       int amount_to_copy = (VALUE_BITSIZE (toval) ? 1 : TYPE_LENGTH (type));
-       int reg_size = REGISTER_RAW_SIZE (VALUE_FRAME_REGNUM (toval));
-       int byte_offset = VALUE_OFFSET (toval) % reg_size;
-       int reg_offset = VALUE_OFFSET (toval) / reg_size;
        int amount_copied;
-
-       /* Make the buffer large enough in all cases.  */
-       /* FIXME (alloca): Not safe for very large data types. */
-       char *buffer = (char *) alloca (amount_to_copy
-                                       + sizeof (LONGEST)
-                                       + MAX_REGISTER_RAW_SIZE);
-
+       int amount_to_copy;
+       char *buffer;
+       int value_reg;
+       int reg_offset;
+       int byte_offset;
        int regno;
        struct frame_info *frame;
 
+       /* Since modifying a register can trash the frame chain, we
+           save the old frame and then restore the new frame
+           afterwards.  */
+       get_frame_id (selected_frame, &old_frame);
+
        /* Figure out which frame this is in currently.  */
-       for (frame = get_current_frame ();
-            frame && FRAME_FP (frame) != VALUE_FRAME (toval);
-            frame = get_prev_frame (frame))
-         ;
+       if (VALUE_LVAL (toval) == lval_register)
+         {
+           frame = get_current_frame ();
+           value_reg = VALUE_REGNO (toval);
+         }
+       else
+         {
+           for (frame = get_current_frame ();
+                frame && FRAME_FP (frame) != VALUE_FRAME (toval);
+                frame = get_prev_frame (frame))
+             ;
+           value_reg = VALUE_FRAME_REGNUM (toval);
+         }
 
        if (!frame)
          error ("Value being assigned to is no longer active.");
 
-       amount_to_copy += (reg_size - amount_to_copy % reg_size);
+       /* Locate the first register that falls in the value that
+           needs to be transfered.  Compute the offset of the value in
+           that register.  */
+       {
+         int offset;
+         for (reg_offset = value_reg, offset = 0;
+              offset + REGISTER_RAW_SIZE (reg_offset) <= VALUE_OFFSET (toval);
+              reg_offset++);
+         byte_offset = VALUE_OFFSET (toval) - offset;
+       }
 
-       /* Copy it out.  */
-       for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
-             amount_copied = 0);
+       /* Compute the number of register aligned values that need to
+           be copied.  */
+       if (VALUE_BITSIZE (toval))
+         amount_to_copy = byte_offset + 1;
+       else
+         amount_to_copy = byte_offset + TYPE_LENGTH (type);
+
+       /* And a bounce buffer.  Be slightly over generous.  */
+       buffer = (char *) alloca (amount_to_copy
+                                 + MAX_REGISTER_RAW_SIZE);
+
+       /* Copy it in.  */
+       for (regno = reg_offset, amount_copied = 0;
             amount_copied < amount_to_copy;
-            amount_copied += reg_size, regno++)
+            amount_copied += REGISTER_RAW_SIZE (regno), regno++)
          {
-           get_saved_register (buffer + amount_copied,
-                               (int *) NULL, (CORE_ADDR *) NULL,
-                               frame, regno, (enum lval_type *) NULL);
+           frame_register_read (frame, regno, buffer + amount_copied);
          }
-
+       
        /* Modify what needs to be modified.  */
        if (VALUE_BITSIZE (toval))
-         modify_field (buffer + byte_offset,
-                       value_as_long (fromval),
-                       VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+         {
+           modify_field (buffer + byte_offset,
+                         value_as_long (fromval),
+                         VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+         }
        else if (use_buffer)
-         memcpy (buffer + byte_offset, raw_buffer, use_buffer);
+         {
+           memcpy (buffer + VALUE_OFFSET (toval), raw_buffer, use_buffer);
+         }
        else
-         memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval),
-                 TYPE_LENGTH (type));
+         {
+           memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval),
+                   TYPE_LENGTH (type));
+           /* Do any conversion necessary when storing this type to
+              more than one register.  */
+#ifdef REGISTER_CONVERT_FROM_TYPE
+           REGISTER_CONVERT_FROM_TYPE (value_reg, type,
+                                       (buffer + byte_offset));
+#endif
+         }
 
-       /* Copy it back.  */
-       for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
-             amount_copied = 0);
+       /* Copy it out.  */
+       for (regno = reg_offset, amount_copied = 0;
             amount_copied < amount_to_copy;
-            amount_copied += reg_size, regno++)
+            amount_copied += REGISTER_RAW_SIZE (regno), regno++)
          {
            enum lval_type lval;
            CORE_ADDR addr;
            int optim;
-
+           int realnum;
+           
            /* Just find out where to put it.  */
-           get_saved_register ((char *) NULL,
-                               &optim, &addr, frame, regno, &lval);
-
+           frame_register (frame, regno, &optim, &lval, &addr, &realnum,
+                           NULL);
+           
            if (optim)
              error ("Attempt to assign to a value that was optimized out.");
            if (lval == lval_memory)
-             write_memory (addr, buffer + amount_copied, reg_size);
+             write_memory (addr, buffer + amount_copied,
+                           REGISTER_RAW_SIZE (regno));
            else if (lval == lval_register)
-             write_register_bytes (addr, buffer + amount_copied, reg_size);
+             regcache_cooked_write (current_regcache, realnum,
+                                    (buffer + amount_copied));
            else
              error ("Attempt to assign to an unmodifiable value.");
          }
@@ -763,10 +751,31 @@ value_assign (struct value *toval, struct value *fromval)
        if (register_changed_hook)
          register_changed_hook (-1);
        target_changed_event ();
+
+       /* Assigning to the stack pointer, frame pointer, and other
+          (architecture and calling convention specific) registers
+          may cause the frame cache to be out of date.  We just do
+          this on all assignments to registers for simplicity; I
+          doubt the slowdown matters.  */
+       reinit_frame_cache ();
+
+       /* Having destoroyed the frame cache, restore the selected
+           frame.  */
+       /* FIXME: cagney/2002-11-02: There has to be a better way of
+           doing this.  Instead of constantly saving/restoring the
+           frame.  Why not create a get_selected_frame() function
+           that, having saved the selected frame's ID can
+           automatically re-find the previously selected frame
+           automatically.  */
+       {
+         struct frame_info *fi = frame_find_by_id (old_frame);
+         if (fi != NULL)
+           select_frame (fi);
+       }
       }
       break;
-
-
+      
+      
     default:
       error ("Left operand of assignment is not an lvalue.");
     }