* configure.tgt (hppa*-*-bsd*, hppa*-*-osf*, m68*-*-sunos4*,
[deliverable/binutils-gdb.git] / gdb / regcache.c
index 3cfafa82d6e8de146a9d752f6231f50ac6b76bb5..104bff7b179d2e7938572bbe18058f27a48a2f8b 100644 (file)
@@ -24,6 +24,7 @@
 #include "inferior.h"
 #include "target.h"
 #include "gdbarch.h"
+#include "gdbcmd.h"
 
 /*
  * DATA STRUCTURE
@@ -68,6 +69,15 @@ register_cached (int regnum)
   return register_valid[regnum];
 }
 
+/* REGISTER_CHANGED
+
+   invalidate a single register REGNUM in the cache */
+void
+register_changed (int regnum)
+{
+  register_valid[regnum] = 0;
+}
+
 /* FIND_SAVED_REGISTER ()
 
    Return the address in which frame FRAME's value of register REGNUM
@@ -282,7 +292,6 @@ void
 registers_changed (void)
 {
   int i;
-  int numregs = ARCH_NUM_REGS;
 
   registers_pid = -1;
 
@@ -293,7 +302,12 @@ registers_changed (void)
      gdb gives control to the user (ie watchpoints).  */
   alloca (0);
 
-  for (i = 0; i < numregs; i++)
+  for (i = 0; i < ARCH_NUM_REGS; i++)
+    register_valid[i] = 0;
+
+  /* Assume that if all the hardware regs have changed, 
+     then so have the pseudo-registers.  */
+  for (i = NUM_REGS; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
     register_valid[i] = 0;
 
   if (registers_changed_hook)
@@ -309,10 +323,11 @@ void
 registers_fetched (void)
 {
   int i;
-  int numregs = ARCH_NUM_REGS;
 
-  for (i = 0; i < numregs; i++)
+  for (i = 0; i < ARCH_NUM_REGS; i++)
     register_valid[i] = 1;
+  /* Do not assume that the pseudo-regs have also been fetched.
+     Fetching all real regs might not account for all pseudo-regs.  */
 }
 
 /* read_register_bytes and write_register_bytes are generally a *BAD*
@@ -351,7 +366,7 @@ read_register_bytes (int inregbyte, char *myaddr, int inlen)
   /* 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++)
+  for (regno = 0; regno < NUM_REGS + NUM_PSEUDO_REGS; regno++)
     {
       int regstart, regend;
 
@@ -368,12 +383,22 @@ read_register_bytes (int inregbyte, char *myaddr, int inlen)
        /* The range the user wants to read doesn't overlap with regno.  */
        continue;
 
-      /* We've found an invalid register where at least one byte will be read.
+      /* We've found an uncached register where at least one byte will be read.
          Update it from the target.  */
-      target_fetch_registers (regno);
+      if (regno < NUM_REGS)
+       target_fetch_registers (regno);
+      else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
+       FETCH_PSEUDO_REGISTER (regno);
 
       if (!register_valid[regno])
-       error ("read_register_bytes:  Couldn't update register %d.", regno);
+       {
+         /* Sometimes pseudoregs are never marked valid, so that they 
+            will be fetched every time (it can be complicated to know
+            if a pseudoreg is valid, while "fetching" them can be cheap). 
+            */
+         if (regno < NUM_REGS)
+           error ("read_register_bytes:  Couldn't update register %d.", regno);
+       }
     }
 
   if (myaddr != NULL)
@@ -395,7 +420,12 @@ read_register_gen (int regno, char *myaddr)
     }
 
   if (!register_valid[regno])
-    target_fetch_registers (regno);
+    {
+      if (regno < NUM_REGS)
+       target_fetch_registers (regno);
+      else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
+       FETCH_PSEUDO_REGISTER (regno);
+    }
   memcpy (myaddr, &registers[REGISTER_BYTE (regno)],
          REGISTER_RAW_SIZE (regno));
 }
@@ -433,13 +463,17 @@ write_register_gen (int regno, char *myaddr)
       && memcmp (&registers[REGISTER_BYTE (regno)], myaddr, size) == 0)
     return;
 
-  target_prepare_to_store ();
+  if (regno < NUM_REGS)
+    target_prepare_to_store ();
 
   memcpy (&registers[REGISTER_BYTE (regno)], myaddr, size);
 
   register_valid[regno] = 1;
 
-  target_store_registers (regno);
+  if (regno < NUM_REGS)
+    target_store_registers (regno);
+  else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
+    STORE_PSEUDO_REGISTER (regno);
 }
 
 /* Copy INLEN bytes of consecutive data from memory at MYADDR
@@ -458,7 +492,7 @@ write_register_bytes (int myregstart, char *myaddr, int inlen)
      nice things like handling threads, and avoiding updates when the
      new and old contents are the same.  */
 
-  for (regno = 0; regno < NUM_REGS; regno++)
+  for (regno = 0; regno < NUM_REGS + NUM_PSEUDO_REGS; regno++)
     {
       int regstart, regend;
 
@@ -490,17 +524,19 @@ write_register_bytes (int myregstart, char *myaddr, int inlen)
                  myaddr + (overlapstart - myregstart),
                  overlapend - overlapstart);
 
-         target_store_registers (regno);
+         if (regno < NUM_REGS)
+           target_store_registers (regno);
+         else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
+           STORE_PSEUDO_REGISTER (regno);
        }
     }
 }
 
 
 /* Return the raw contents of register REGNO, regarding it as an
-   integer.  This probably should be returning LONGEST rather than
-   CORE_ADDR.  */
+   UNSIGNED integer. */
 
-CORE_ADDR
+ULONGEST
 read_register (int regno)
 {
   if (registers_pid != inferior_pid)
@@ -510,14 +546,18 @@ read_register (int regno)
     }
 
   if (!register_valid[regno])
-    target_fetch_registers (regno);
+    {
+      if (regno < NUM_REGS)
+       target_fetch_registers (regno);
+      else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
+       FETCH_PSEUDO_REGISTER (regno);
+    }
 
-  return ((CORE_ADDR)
-         extract_unsigned_integer (&registers[REGISTER_BYTE (regno)],
+  return (extract_unsigned_integer (&registers[REGISTER_BYTE (regno)],
                                    REGISTER_RAW_SIZE (regno)));
 }
 
-CORE_ADDR
+ULONGEST
 read_register_pid (int regno, int pid)
 {
   int save_pid;
@@ -537,6 +577,45 @@ read_register_pid (int regno, int pid)
   return retval;
 }
 
+/* Return the raw contents of register REGNO, regarding it a SIGNED
+   integer. */
+
+LONGEST
+read_signed_register (int regno)
+{
+  if (registers_pid != inferior_pid)
+    {
+      registers_changed ();
+      registers_pid = inferior_pid;
+    }
+
+  if (!register_valid[regno])
+    target_fetch_registers (regno);
+
+  return (extract_signed_integer (&registers[REGISTER_BYTE (regno)],
+                                 REGISTER_RAW_SIZE (regno)));
+}
+
+LONGEST
+read_signed_register_pid (int regno, int pid)
+{
+  int save_pid;
+  LONGEST retval;
+
+  if (pid == inferior_pid)
+    return read_signed_register (regno);
+
+  save_pid = inferior_pid;
+
+  inferior_pid = pid;
+
+  retval = read_signed_register (regno);
+
+  inferior_pid = save_pid;
+
+  return retval;
+}
+
 /* Store VALUE, into the raw contents of register number REGNO.  */
 
 void
@@ -567,13 +646,17 @@ write_register (int regno, LONGEST val)
       && memcmp (&registers[REGISTER_BYTE (regno)], buf, size) == 0)
     return;
 
-  target_prepare_to_store ();
+  if (regno < NUM_REGS)
+    target_prepare_to_store ();
 
   memcpy (&registers[REGISTER_BYTE (regno)], buf, size);
 
   register_valid[regno] = 1;
 
-  target_store_registers (regno);
+  if (regno < NUM_REGS)
+    target_store_registers (regno);
+  else if (regno < NUM_REGS + NUM_PSEUDO_REGS)
+    STORE_PSEUDO_REGISTER (regno);
 }
 
 void
@@ -641,7 +724,7 @@ supply_register (int regno, char *val)
    Ditto for write_pc.
 
    1999-06-08: The following were re-written so that it assumes the
-   existance of a TARGET_READ_PC et.al. macro.  A default generic
+   existence of a TARGET_READ_PC et.al. macro.  A default generic
    version of that macro is made available where needed.
 
    Since the ``TARGET_READ_PC'' et.al. macro is going to be controlled
@@ -649,10 +732,6 @@ supply_register (int regno, char *val)
    eliminate the intermediate read_pc_pid().  The client would call
    TARGET_READ_PC directly. (cagney). */
 
-#ifndef TARGET_READ_PC
-#define TARGET_READ_PC generic_target_read_pc
-#endif
-
 CORE_ADDR
 generic_target_read_pc (int pid)
 {
@@ -689,10 +768,6 @@ read_pc (void)
   return read_pc_pid (inferior_pid);
 }
 
-#ifndef TARGET_WRITE_PC
-#define TARGET_WRITE_PC generic_target_write_pc
-#endif
-
 void
 generic_target_write_pc (CORE_ADDR pc, int pid)
 {
@@ -730,10 +805,6 @@ write_pc (CORE_ADDR pc)
 
 /* Cope with strage ways of getting to the stack and frame pointers */
 
-#ifndef TARGET_READ_SP
-#define TARGET_READ_SP generic_target_read_sp
-#endif
-
 CORE_ADDR
 generic_target_read_sp (void)
 {
@@ -750,10 +821,6 @@ read_sp (void)
   return TARGET_READ_SP ();
 }
 
-#ifndef TARGET_WRITE_SP
-#define TARGET_WRITE_SP generic_target_write_sp
-#endif
-
 void
 generic_target_write_sp (CORE_ADDR val)
 {
@@ -773,10 +840,6 @@ write_sp (CORE_ADDR val)
   TARGET_WRITE_SP (val);
 }
 
-#ifndef TARGET_READ_FP
-#define TARGET_READ_FP generic_target_read_fp
-#endif
-
 CORE_ADDR
 generic_target_read_fp (void)
 {
@@ -793,10 +856,6 @@ read_fp (void)
   return TARGET_READ_FP ();
 }
 
-#ifndef TARGET_WRITE_FP
-#define TARGET_WRITE_FP generic_target_write_fp
-#endif
-
 void
 generic_target_write_fp (CORE_ADDR val)
 {
@@ -816,13 +875,25 @@ write_fp (CORE_ADDR val)
   TARGET_WRITE_FP (val);
 }
 
+/* ARGSUSED */
+static void
+reg_flush_command (char *command, int from_tty)
+{
+  /* Force-flush the register cache.  */
+  registers_changed ();
+  if (from_tty)
+    printf_filtered ("Register cache flushed.\n");
+}
+
+
 static void
 build_regcache (void)
 {
   /* We allocate some extra slop since we do a lot of memcpy's around
      `registers', and failing-soft is better than failing hard.  */
   int sizeof_registers = REGISTER_BYTES + /* SLOP */ 256;
-  int sizeof_register_valid = NUM_REGS * sizeof (*register_valid);
+  int sizeof_register_valid = 
+    (NUM_REGS + NUM_PSEUDO_REGS) * sizeof (*register_valid);
   registers = xmalloc (sizeof_registers);
   memset (registers, 0, sizeof_registers);
   register_valid = xmalloc (sizeof_register_valid);
@@ -837,4 +908,7 @@ _initialize_regcache (void)
   register_gdbarch_swap (&registers, sizeof (registers), NULL);
   register_gdbarch_swap (&register_valid, sizeof (register_valid), NULL);
   register_gdbarch_swap (NULL, 0, build_regcache);
+
+  add_com ("flushregs", class_maintenance, reg_flush_command,
+          "Force gdb to flush its register cache (maintainer command)");
 }
This page took 0.028353 seconds and 4 git commands to generate.