This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] Update software_single_step arguments


Daniel Jacobowitz wrote:
> On Thu, Apr 12, 2007 at 10:09:10PM +0200, Ulrich Weigand wrote:
> > I thought "resume" (where this is called) too low-level for
> > a frame to make sense.  You cannot single-step anywhere but
> > in the innermost frame, so a regcache seemed more appropriate.
> > (How would I actually get hold of a frame in resume?)
> 
> I guess you'd just use the current one, but a regcache is fine too.

The following patch implements this change.  It should be strictly mechanical
and have no impact on the behaviour of any target.

Tested on spu-elf, and by running gdb_mbuild.sh.
Committed to mainline.

Bye,
Ulrich


ChangeLog:

	* gdbarch.sh (software_single_step): Remove "insert_breakpoints_p" and
	"sig" arguments, add "regcache" argument.
	* gdbarch.c, gdbarch.h: Regenerate.

	* infrun.c (resume): Update SOFTWARE_SINGLE_STEP call arguments.
	(handle_inferior_event): Call remove_single_step_breakpoints directly
	instead of calling SOFTWARE_SINGLE_STEP to remove breakpoints.

	* alpha-tdep.c (alpha_software_single_step): Update argument list.
	Remove handling of !insert_breakpoints_p case.
	* arm-tdep.c (arm_software_single_step): Likewise.
	* cris-tdep.c (cris_software_single_step): Likewise.
	* mips-tdep.c (mips_software_single_step): Likewise.
	* rs6000-tdep.c (rs6000_software_single_step): Likewise.
	* sparc-tdep.c (sparc_software_single_step): Likewise.
	* spu-tdep.c (spu_software_single_step): Likewise.

	* alpha-tdep.h (alpha_software_single_step): Update prototype.
	* mips-tdep.h (mips_software_single_step): Likewise.
	* rs6000-tdep.h (rs6000_software_single_step): Likewise.
	* sparc-tdep.h (sparc_software_single_step): Likewise.


diff -urNp gdb-orig/gdb/alpha-tdep.c gdb-head/gdb/alpha-tdep.c
--- gdb-orig/gdb/alpha-tdep.c	2007-04-12 22:31:33.120201000 +0200
+++ gdb-head/gdb/alpha-tdep.c	2007-04-13 00:09:42.503230088 +0200
@@ -1391,10 +1391,7 @@ fp_register_sign_bit (LONGEST reg)
 /* alpha_software_single_step() is called just before we want to resume
    the inferior, if we want to single-step it but there is no hardware
    or kernel single-step support (NetBSD on Alpha, for example).  We find
-   the target of the coming instruction and breakpoint it.
-
-   single_step is also called just after the inferior stops.  If we had
-   set up a simulated single-step, we undo our damage.  */
+   the target of the coming instruction and breakpoint it.  */
 
 static CORE_ADDR
 alpha_next_pc (CORE_ADDR pc)
@@ -1519,22 +1516,14 @@ alpha_next_pc (CORE_ADDR pc)
 }
 
 int
-alpha_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+alpha_software_single_step (struct regcache *regcache)
 {
-  CORE_ADDR next_pc;
-  CORE_ADDR pc;
+  CORE_ADDR pc, next_pc;
 
-  if (insert_breakpoints_p)
-    {
-      pc = read_pc ();
-      next_pc = alpha_next_pc (pc);
+  pc = read_pc ();
+  next_pc = alpha_next_pc (pc);
 
-      insert_single_step_breakpoint (next_pc);
-    }
-  else
-    {
-      remove_single_step_breakpoints ();
-    }
+  insert_single_step_breakpoint (next_pc);
   return 1;
 }
 
diff -urNp gdb-orig/gdb/alpha-tdep.h gdb-head/gdb/alpha-tdep.h
--- gdb-orig/gdb/alpha-tdep.h	2007-04-12 16:26:43.507223000 +0200
+++ gdb-head/gdb/alpha-tdep.h	2007-04-13 00:14:17.918173176 +0200
@@ -107,7 +107,7 @@ struct gdbarch_tdep
 };
 
 extern unsigned int alpha_read_insn (CORE_ADDR pc);
-extern int alpha_software_single_step (enum target_signal, int);
+extern int alpha_software_single_step (struct regcache *regcache);
 extern CORE_ADDR alpha_after_prologue (CORE_ADDR pc);
 
 extern void alpha_mdebug_init_abi (struct gdbarch_info, struct gdbarch *);
diff -urNp gdb-orig/gdb/arm-tdep.c gdb-head/gdb/arm-tdep.c
--- gdb-orig/gdb/arm-tdep.c	2007-04-12 16:26:43.532219000 +0200
+++ gdb-head/gdb/arm-tdep.c	2007-04-13 00:05:27.326141168 +0200
@@ -1902,26 +1902,17 @@ arm_get_next_pc (CORE_ADDR pc)
 /* single_step() is called just before we want to resume the inferior,
    if we want to single-step it but there is no hardware or kernel
    single-step support.  We find the target of the coming instruction
-   and breakpoint it.
-
-   single_step() is also called just after the inferior stops.  If we
-   had set up a simulated single-step, we undo our damage.  */
+   and breakpoint it.  */
 
 static int
-arm_software_single_step (enum target_signal sig, int insert_bpt)
+arm_software_single_step (struct regcache *regcache)
 {
   /* NOTE: This may insert the wrong breakpoint instruction when
      single-stepping over a mode-changing instruction, if the
      CPSR heuristics are used.  */
 
-  if (insert_bpt)
-    {
-      CORE_ADDR next_pc = arm_get_next_pc (read_register (ARM_PC_REGNUM));
-
-      insert_single_step_breakpoint (next_pc);
-    }
-  else
-    remove_single_step_breakpoints ();
+  CORE_ADDR next_pc = arm_get_next_pc (read_register (ARM_PC_REGNUM));
+  insert_single_step_breakpoint (next_pc);
 
   return 1;
 }
diff -urNp gdb-orig/gdb/cris-tdep.c gdb-head/gdb/cris-tdep.c
--- gdb-orig/gdb/cris-tdep.c	2007-04-12 16:26:43.568213000 +0200
+++ gdb-head/gdb/cris-tdep.c	2007-04-13 00:08:37.860203488 +0200
@@ -2120,38 +2120,33 @@ find_step_target (inst_env_type *inst_en
    Either one ordinary target or two targets for branches may be found.  */
 
 static int
-cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
+cris_software_single_step (struct regcache *regcache)
 {
   inst_env_type inst_env;
 
-  if (insert_breakpoints)
-    {
-      /* Analyse the present instruction environment and insert 
-         breakpoints.  */
-      int status = find_step_target (&inst_env);
-      if (status == -1)
-        {
-          /* Could not find a target.  Things are likely to go downhill 
-	     from here.  */
-	  warning (_("CRIS software single step could not find a step target."));
-        }
-      else
-        {
-          /* Insert at most two breakpoints.  One for the next PC content
-             and possibly another one for a branch, jump, etc.  */
-          CORE_ADDR next_pc = (CORE_ADDR) inst_env.reg[PC_REGNUM];
-          insert_single_step_breakpoint (next_pc);
-          if (inst_env.branch_found 
-              && (CORE_ADDR) inst_env.branch_break_address != next_pc)
-            {
-              CORE_ADDR branch_target_address
-                = (CORE_ADDR) inst_env.branch_break_address;
-              insert_single_step_breakpoint (branch_target_address);
-            }
-        }
+  /* Analyse the present instruction environment and insert 
+     breakpoints.  */
+  int status = find_step_target (&inst_env);
+  if (status == -1)
+    {
+      /* Could not find a target.  Things are likely to go downhill 
+	 from here.  */
+      warning (_("CRIS software single step could not find a step target."));
     }
   else
-    remove_single_step_breakpoints ();
+    {
+      /* Insert at most two breakpoints.  One for the next PC content
+         and possibly another one for a branch, jump, etc.  */
+      CORE_ADDR next_pc = (CORE_ADDR) inst_env.reg[PC_REGNUM];
+      insert_single_step_breakpoint (next_pc);
+      if (inst_env.branch_found 
+	  && (CORE_ADDR) inst_env.branch_break_address != next_pc)
+	{
+	  CORE_ADDR branch_target_address
+		= (CORE_ADDR) inst_env.branch_break_address;
+	  insert_single_step_breakpoint (branch_target_address);
+	}
+    }
 
   return 1;
 }
diff -urNp gdb-orig/gdb/gdbarch.c gdb-head/gdb/gdbarch.c
--- gdb-orig/gdb/gdbarch.c	2007-04-12 16:26:43.581211000 +0200
+++ gdb-head/gdb/gdbarch.c	2007-04-13 00:02:56.327194976 +0200
@@ -1522,8 +1522,8 @@ gdbarch_dump (struct gdbarch *current_gd
 #ifdef SOFTWARE_SINGLE_STEP
   fprintf_unfiltered (file,
                       "gdbarch_dump: %s # %s\n",
-                      "SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p)",
-                      XSTRING (SOFTWARE_SINGLE_STEP (sig, insert_breakpoints_p)));
+                      "SOFTWARE_SINGLE_STEP(regcache)",
+                      XSTRING (SOFTWARE_SINGLE_STEP (regcache)));
 #endif
   fprintf_unfiltered (file,
                       "gdbarch_dump: software_single_step = <0x%lx>\n",
@@ -3290,13 +3290,13 @@ gdbarch_software_single_step_p (struct g
 }
 
 int
-gdbarch_software_single_step (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p)
+gdbarch_software_single_step (struct gdbarch *gdbarch, struct regcache *regcache)
 {
   gdb_assert (gdbarch != NULL);
   gdb_assert (gdbarch->software_single_step != NULL);
   if (gdbarch_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "gdbarch_software_single_step called\n");
-  return gdbarch->software_single_step (sig, insert_breakpoints_p);
+  return gdbarch->software_single_step (regcache);
 }
 
 void
diff -urNp gdb-orig/gdb/gdbarch.h gdb-head/gdb/gdbarch.h
--- gdb-orig/gdb/gdbarch.h	2007-04-12 16:26:43.590210000 +0200
+++ gdb-head/gdb/gdbarch.h	2007-04-13 00:02:49.271202424 +0200
@@ -1173,14 +1173,14 @@ extern int gdbarch_software_single_step_
 #define SOFTWARE_SINGLE_STEP_P() (gdbarch_software_single_step_p (current_gdbarch))
 #endif
 
-typedef int (gdbarch_software_single_step_ftype) (enum target_signal sig, int insert_breakpoints_p);
-extern int gdbarch_software_single_step (struct gdbarch *gdbarch, enum target_signal sig, int insert_breakpoints_p);
+typedef int (gdbarch_software_single_step_ftype) (struct regcache *regcache);
+extern int gdbarch_software_single_step (struct gdbarch *gdbarch, struct regcache *regcache);
 extern void set_gdbarch_software_single_step (struct gdbarch *gdbarch, gdbarch_software_single_step_ftype *software_single_step);
 #if !defined (GDB_TM_FILE) && defined (SOFTWARE_SINGLE_STEP)
 #error "Non multi-arch definition of SOFTWARE_SINGLE_STEP"
 #endif
 #if !defined (SOFTWARE_SINGLE_STEP)
-#define SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p) (gdbarch_software_single_step (current_gdbarch, sig, insert_breakpoints_p))
+#define SOFTWARE_SINGLE_STEP(regcache) (gdbarch_software_single_step (current_gdbarch, regcache))
 #endif
 
 /* Return non-zero if the processor is executing a delay slot and a
diff -urNp gdb-orig/gdb/gdbarch.sh gdb-head/gdb/gdbarch.sh
--- gdb-orig/gdb/gdbarch.sh	2007-04-12 16:26:43.610207000 +0200
+++ gdb-head/gdb/gdbarch.sh	2007-04-13 00:02:11.913156520 +0200
@@ -628,7 +628,7 @@ f:=:CORE_ADDR:smash_text_address:CORE_AD
 #
 # A return value of 1 means that the software_single_step breakpoints 
 # were inserted; 0 means they were not.
-F:=:int:software_single_step:enum target_signal sig, int insert_breakpoints_p:sig, insert_breakpoints_p
+F:=:int:software_single_step:struct regcache *regcache:regcache
 
 # Return non-zero if the processor is executing a delay slot and a
 # further single-step is needed before the instruction finishes.
diff -urNp gdb-orig/gdb/infrun.c gdb-head/gdb/infrun.c
--- gdb-orig/gdb/infrun.c	2007-04-12 16:26:43.622205000 +0200
+++ gdb-head/gdb/infrun.c	2007-04-13 00:18:33.741163272 +0200
@@ -548,7 +548,7 @@ resume (int step, enum target_signal sig
   if (SOFTWARE_SINGLE_STEP_P () && step)
     {
       /* Do it the hard way, w/temp breakpoints */
-      if (SOFTWARE_SINGLE_STEP (sig, 1 /*insert-breakpoints */ ))
+      if (SOFTWARE_SINGLE_STEP (current_regcache))
         {
           /* ...and don't ask hardware to do it.  */
           step = 0;
@@ -1571,7 +1571,7 @@ handle_inferior_event (struct execution_
 	  if (debug_infrun)
 	    fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n");
 	  /* Pull the single step breakpoints out of the target.  */
-	  (void) SOFTWARE_SINGLE_STEP (0, 0);
+	  remove_single_step_breakpoints ();
 	  singlestep_breakpoints_inserted_p = 0;
 
 	  ecs->random_signal = 0;
@@ -1680,7 +1680,7 @@ handle_inferior_event (struct execution_
 	  if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
 	    {
 	      /* Pull the single step breakpoints out of the target. */
-	      (void) SOFTWARE_SINGLE_STEP (0, 0);
+	      remove_single_step_breakpoints ();
 	      singlestep_breakpoints_inserted_p = 0;
 	    }
 
@@ -1751,7 +1751,7 @@ handle_inferior_event (struct execution_
   if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
     {
       /* Pull the single step breakpoints out of the target. */
-      (void) SOFTWARE_SINGLE_STEP (0, 0);
+      remove_single_step_breakpoints ();
       singlestep_breakpoints_inserted_p = 0;
     }
 
diff -urNp gdb-orig/gdb/mips-tdep.c gdb-head/gdb/mips-tdep.c
--- gdb-orig/gdb/mips-tdep.c	2007-04-12 16:26:43.652201000 +0200
+++ gdb-head/gdb/mips-tdep.c	2007-04-13 00:09:23.118247720 +0200
@@ -2199,26 +2199,17 @@ mips_addr_bits_remove (CORE_ADDR addr)
 /* mips_software_single_step() is called just before we want to resume
    the inferior, if we want to single-step it but there is no hardware
    or kernel single-step support (MIPS on GNU/Linux for example).  We find
-   the target of the coming instruction and breakpoint it.
-
-   single_step is also called just after the inferior stops.  If we had
-   set up a simulated single-step, we undo our damage.  */
+   the target of the coming instruction and breakpoint it.  */
 
 int
-mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+mips_software_single_step (struct regcache *regcache)
 {
   CORE_ADDR pc, next_pc;
 
-  if (insert_breakpoints_p)
-    {
-      pc = read_register (mips_regnum (current_gdbarch)->pc);
-      next_pc = mips_next_pc (pc);
-
-      insert_single_step_breakpoint (next_pc);
-    }
-  else
-    remove_single_step_breakpoints ();
+  pc = read_register (mips_regnum (current_gdbarch)->pc);
+  next_pc = mips_next_pc (pc);
 
+  insert_single_step_breakpoint (next_pc);
   return 1;
 }
 
diff -urNp gdb-orig/gdb/mips-tdep.h gdb-head/gdb/mips-tdep.h
--- gdb-orig/gdb/mips-tdep.h	2007-04-12 16:26:43.657200000 +0200
+++ gdb-head/gdb/mips-tdep.h	2007-04-13 00:14:07.262194368 +0200
@@ -100,7 +100,7 @@ enum
 };
 
 /* Single step based on where the current instruction will take us.  */
-extern int mips_software_single_step (enum target_signal, int);
+extern int mips_software_single_step (struct regcache *regcache);
 
 /* Tell if the program counter value in MEMADDR is in a MIPS16
    function.  */
diff -urNp gdb-orig/gdb/rs6000-tdep.c gdb-head/gdb/rs6000-tdep.c
--- gdb-orig/gdb/rs6000-tdep.c	2007-04-12 16:26:43.702193000 +0200
+++ gdb-head/gdb/rs6000-tdep.c	2007-04-13 00:11:55.894192088 +0200
@@ -723,8 +723,7 @@ rs6000_breakpoint_from_pc (CORE_ADDR *bp
 /* AIX does not support PT_STEP. Simulate it. */
 
 int
-rs6000_software_single_step (enum target_signal signal,
-			     int insert_breakpoints_p)
+rs6000_software_single_step (struct regcache *regcache)
 {
   CORE_ADDR dummy;
   int breakp_sz;
@@ -734,30 +733,25 @@ rs6000_software_single_step (enum target
   CORE_ADDR breaks[2];
   int opcode;
 
-  if (insert_breakpoints_p)
-    {
-      loc = read_pc ();
+  loc = read_pc ();
 
-      insn = read_memory_integer (loc, 4);
+  insn = read_memory_integer (loc, 4);
 
-      breaks[0] = loc + breakp_sz;
-      opcode = insn >> 26;
-      breaks[1] = branch_dest (opcode, insn, loc, breaks[0]);
+  breaks[0] = loc + breakp_sz;
+  opcode = insn >> 26;
+  breaks[1] = branch_dest (opcode, insn, loc, breaks[0]);
 
-      /* Don't put two breakpoints on the same address. */
-      if (breaks[1] == breaks[0])
-	breaks[1] = -1;
+  /* Don't put two breakpoints on the same address. */
+  if (breaks[1] == breaks[0])
+    breaks[1] = -1;
 
-      for (ii = 0; ii < 2; ++ii)
-	{
-	  /* ignore invalid breakpoint. */
-	  if (breaks[ii] == -1)
-	    continue;
-	  insert_single_step_breakpoint (breaks[ii]);
-	}
+  for (ii = 0; ii < 2; ++ii)
+    {
+      /* ignore invalid breakpoint. */
+      if (breaks[ii] == -1)
+	continue;
+      insert_single_step_breakpoint (breaks[ii]);
     }
-  else
-    remove_single_step_breakpoints ();
 
   errno = 0;			/* FIXME, don't ignore errors! */
   /* What errors?  {read,write}_memory call error().  */
diff -urNp gdb-orig/gdb/rs6000-tdep.h gdb-head/gdb/rs6000-tdep.h
--- gdb-orig/gdb/rs6000-tdep.h	2007-04-12 16:26:43.661199000 +0200
+++ gdb-head/gdb/rs6000-tdep.h	2007-04-13 00:13:59.057243312 +0200
@@ -21,8 +21,7 @@
 
 #include "defs.h"
 
-extern int rs6000_software_single_step (enum target_signal signal,
-                                        int insert_breakpoints_p);
+extern int rs6000_software_single_step (struct regcache *regcache);
 
 /* Hook in rs6000-tdep.c for determining the TOC address when
    calling functions in the inferior.  */
diff -urNp gdb-orig/gdb/sparc-tdep.c gdb-head/gdb/sparc-tdep.c
--- gdb-orig/gdb/sparc-tdep.c	2007-04-12 16:26:43.680196000 +0200
+++ gdb-head/gdb/sparc-tdep.c	2007-04-13 00:13:27.494247568 +0200
@@ -1330,35 +1330,30 @@ sparc_step_trap (unsigned long insn)
 }
 
 int
-sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+sparc_software_single_step (struct regcache *regcache)
 {
   struct gdbarch *arch = current_gdbarch;
   struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
   CORE_ADDR npc, nnpc;
 
-  if (insert_breakpoints_p)
-    {
-      CORE_ADDR pc, orig_npc;
+  CORE_ADDR pc, orig_npc;
 
-      pc = sparc_address_from_register (tdep->pc_regnum);
-      orig_npc = npc = sparc_address_from_register (tdep->npc_regnum);
+  pc = sparc_address_from_register (tdep->pc_regnum);
+  orig_npc = npc = sparc_address_from_register (tdep->npc_regnum);
 
-      /* Analyze the instruction at PC.  */
-      nnpc = sparc_analyze_control_transfer (arch, pc, &npc);
-      if (npc != 0)
-	insert_single_step_breakpoint (npc);
-
-      if (nnpc != 0)
-	insert_single_step_breakpoint (nnpc);
-
-      /* Assert that we have set at least one breakpoint, and that
-	 they're not set at the same spot - unless we're going
-	 from here straight to NULL, i.e. a call or jump to 0.  */
-      gdb_assert (npc != 0 || nnpc != 0 || orig_npc == 0);
-      gdb_assert (nnpc != npc || orig_npc == 0);
-    }
-  else
-    remove_single_step_breakpoints ();
+  /* Analyze the instruction at PC.  */
+  nnpc = sparc_analyze_control_transfer (arch, pc, &npc);
+  if (npc != 0)
+    insert_single_step_breakpoint (npc);
+
+  if (nnpc != 0)
+    insert_single_step_breakpoint (nnpc);
+
+  /* Assert that we have set at least one breakpoint, and that
+     they're not set at the same spot - unless we're going
+     from here straight to NULL, i.e. a call or jump to 0.  */
+  gdb_assert (npc != 0 || nnpc != 0 || orig_npc == 0);
+  gdb_assert (nnpc != npc || orig_npc == 0);
 
   return 1;
 }
diff -urNp gdb-orig/gdb/sparc-tdep.h gdb-head/gdb/sparc-tdep.h
--- gdb-orig/gdb/sparc-tdep.h	2007-04-12 16:26:43.690195000 +0200
+++ gdb-head/gdb/sparc-tdep.h	2007-04-13 00:13:47.893209264 +0200
@@ -167,8 +167,7 @@ extern struct sparc_frame_cache *
 
 
 
-extern int sparc_software_single_step (enum target_signal sig,
-                                       int insert_breakpoints_p);
+extern int sparc_software_single_step (struct regcache *regcache);
 
 extern void sparc_supply_rwindow (struct regcache *regcache,
 				  CORE_ADDR sp, int regnum);
diff -urNp gdb-orig/gdb/spu-tdep.c gdb-head/gdb/spu-tdep.c
--- gdb-orig/gdb/spu-tdep.c	2007-04-12 16:26:43.709192000 +0200
+++ gdb-head/gdb/spu-tdep.c	2007-04-13 00:16:21.341184944 +0200
@@ -1079,52 +1079,47 @@ spu_breakpoint_from_pc (CORE_ADDR * pcpt
 /* Software single-stepping support.  */
 
 int
-spu_software_single_step (enum target_signal signal, int insert_breakpoints_p)
+spu_software_single_step (struct regcache *regcache)
 {
-  if (insert_breakpoints_p)
-    {
-      CORE_ADDR pc, next_pc;
-      unsigned int insn;
-      int offset, reg;
-      gdb_byte buf[4];
-
-      regcache_cooked_read (current_regcache, SPU_PC_REGNUM, buf);
-      /* Mask off interrupt enable bit.  */
-      pc = extract_unsigned_integer (buf, 4) & -4;
-
-      if (target_read_memory (pc, buf, 4))
-	return 1;
-      insn = extract_unsigned_integer (buf, 4);
-
-       /* Next sequential instruction is at PC + 4, except if the current
-	  instruction is a PPE-assisted call, in which case it is at PC + 8.
-	  Wrap around LS limit to be on the safe side.  */
-      if ((insn & 0xffffff00) == 0x00002100)
-	next_pc = (pc + 8) & (SPU_LS_SIZE - 1);
-      else
-	next_pc = (pc + 4) & (SPU_LS_SIZE - 1);
+  CORE_ADDR pc, next_pc;
+  unsigned int insn;
+  int offset, reg;
+  gdb_byte buf[4];
+
+  regcache_cooked_read (regcache, SPU_PC_REGNUM, buf);
+  /* Mask off interrupt enable bit.  */
+  pc = extract_unsigned_integer (buf, 4) & -4;
+
+  if (target_read_memory (pc, buf, 4))
+    return 1;
+  insn = extract_unsigned_integer (buf, 4);
+
+  /* Next sequential instruction is at PC + 4, except if the current
+     instruction is a PPE-assisted call, in which case it is at PC + 8.
+     Wrap around LS limit to be on the safe side.  */
+  if ((insn & 0xffffff00) == 0x00002100)
+    next_pc = (pc + 8) & (SPU_LS_SIZE - 1);
+  else
+    next_pc = (pc + 4) & (SPU_LS_SIZE - 1);
 
-      insert_single_step_breakpoint (next_pc);
+  insert_single_step_breakpoint (next_pc);
 
-      if (is_branch (insn, &offset, &reg))
-	{
-	  CORE_ADDR target = offset;
+  if (is_branch (insn, &offset, &reg))
+    {
+      CORE_ADDR target = offset;
 
-	  if (reg == SPU_PC_REGNUM)
-	    target += pc;
-	  else if (reg != -1)
-	    {
-	      regcache_cooked_read_part (current_regcache, reg, 0, 4, buf);
-	      target += extract_unsigned_integer (buf, 4) & -4;
-	    }
-
-	  target = target & (SPU_LS_SIZE - 1);
-	  if (target != next_pc)
-	    insert_single_step_breakpoint (target);
+      if (reg == SPU_PC_REGNUM)
+	target += pc;
+      else if (reg != -1)
+	{
+	  regcache_cooked_read_part (regcache, reg, 0, 4, buf);
+	  target += extract_unsigned_integer (buf, 4) & -4;
 	}
+
+      target = target & (SPU_LS_SIZE - 1);
+      if (target != next_pc)
+	insert_single_step_breakpoint (target);
     }
-  else
-    remove_single_step_breakpoints ();
 
   return 1;
 }

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]