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]

[PATCH 07/13] Split brekapoint_from_pc to breakpoint_kind_from_pc and sw_breakpoint_from_kind


We convert each ARCH_brekapoint_from_pc to ARCH_breakpoint_kind_from_pc
and ARCH_sw_breakpoint_from_kind.  Note that gdbarch doesn't have methods
breakpoint_kind_from_pc and sw_breakpoint_from_kind so far.

gdb:

2016-08-31  Yao Qi  <yao.qi@linaro.org>

	* arch-utils.h (GDBARCH_BREAKPOINT_FROM_PC): New macro.
	(GDBARCH_BREAKPOINT_MANIPULATION_ENDIAN): New macro.
	* arm-tdep.c (arm_breakpoint_from_pc): Remove.
	(arm_breakpoint_kind_from_pc): New function.
	(arm_sw_breakpoint_from_kind): New function.
	(arm_breakpoint_from_pc): Call arm_breakpoint_kind_from_pc
	and arm_sw_breakpoint_from_kind.
	Use GDBARCH_BREAKPOINT_FROM_PC.
	(arm_remote_breakpoint_from_pc): Call
	arm_breakpoint_kind_from_pc.
	(arm_gdbarch_init): Replace set_gdbarch_breakpoint_from_pc
	with SET_GDBARCH_BREAKPOINT_MANIPULATION.
	* bfin-tdep.c: Likewise.
	* cris-tdep.c: Likewise.
	* iq2000-tdep.c: Likewise.
	* m32r-tdep.c: Likewise.
	* mips-tdep.c: Likewise.
	* mt-tdep.c: Likewise.
	* nios2-tdep.c: Likewise.
	* rs6000-tdep.c: Likewise.
	* score-tdep.c: Likewise.
	* sh-tdep.c: Likewise.
	* sh64-tdep.c: Likewise.
	* tic6x-tdep.c: Likewise.
	* v850-tdep.c: Likewise.
	* xtensa-tdep.c: Likewise.
---
 gdb/arch-utils.h  |  28 +++++++
 gdb/arm-tdep.c    |  61 ++++++++------
 gdb/bfin-tdep.c   |  36 +++++----
 gdb/cris-tdep.c   |  28 ++++---
 gdb/iq2000-tdep.c |  23 ++++--
 gdb/m32r-tdep.c   |  45 +++++------
 gdb/mips-tdep.c   | 234 +++++++++++++++++++++++++++---------------------------
 gdb/mt-tdep.c     |  27 ++++---
 gdb/nios2-tdep.c  |  98 ++++++++++++++---------
 gdb/rs6000-tdep.c |  19 ++---
 gdb/score-tdep.c  | 115 ++++++++++++++-------------
 gdb/sh-tdep.c     |  36 +++++----
 gdb/sh64-tdep.c   |  71 +++++++++--------
 gdb/tic6x-tdep.c  |  17 ++--
 gdb/v850-tdep.c   |  19 +++--
 gdb/xtensa-tdep.c |  53 ++++++-------
 16 files changed, 506 insertions(+), 404 deletions(-)

diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 77d4fb5..8efc4a8 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -26,6 +26,17 @@ struct minimal_symbol;
 struct type;
 struct gdbarch_info;
 
+#define GDBARCH_BREAKPOINT_FROM_PC(ARCH)			       \
+  static const gdb_byte *					       \
+  ARCH##_breakpoint_from_pc (struct gdbarch *gdbarch,		       \
+			     CORE_ADDR *pcptr,				\
+			     int *lenptr)				\
+  {									\
+    int kind = ARCH##_breakpoint_kind_from_pc (gdbarch, pcptr);	\
+								     \
+    return ARCH##_sw_breakpoint_from_kind (gdbarch, kind, lenptr);   \
+  }
+
 #define GDBARCH_BREAKPOINT_MANIPULATION(ARCH,BREAK_INSN)	      \
   static const gdb_byte *					      \
   ARCH##_breakpoint_from_pc (struct gdbarch *gdbarch,		      \
@@ -39,6 +50,23 @@ struct gdbarch_info;
 #define SET_GDBARCH_BREAKPOINT_MANIPULATION(ARCH)	\
   set_gdbarch_breakpoint_from_pc (gdbarch, ARCH##_breakpoint_from_pc)
 
+#define GDBARCH_BREAKPOINT_MANIPULATION_ENDIAN(ARCH, \
+					       LITTLE_BREAK_INSN,	\
+					       BIG_BREAK_INSN)		\
+  static const gdb_byte *						\
+  ARCH##_breakpoint_from_pc (struct gdbarch *gdbarch,			\
+			     CORE_ADDR *pcptr,				\
+			     int *lenptr)				\
+  {									\
+    gdb_static_assert (ARRAY_SIZE (LITTLE_BREAK_INSN)			\
+		       == ARRAY_SIZE (BIG_BREAK_INSN));		\
+    *lenptr = sizeof (LITTLE_BREAK_INSN);				\
+    if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)		\
+      return BIG_BREAK_INSN;						\
+    else								\
+      return LITTLE_BREAK_INSN;					\
+  }
+
 /* An implementation of gdbarch_displaced_step_copy_insn for
    processors that don't need to modify the instruction before
    single-stepping the displaced copy.
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 16dc574..2513707 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -7795,16 +7795,8 @@ static const gdb_byte arm_default_arm_be_breakpoint[] = ARM_BE_BREAKPOINT;
 static const gdb_byte arm_default_thumb_le_breakpoint[] = THUMB_LE_BREAKPOINT;
 static const gdb_byte arm_default_thumb_be_breakpoint[] = THUMB_BE_BREAKPOINT;
 
-/* Determine the type and size of breakpoint to insert at PCPTR.  Uses
-   the program counter value to determine whether a 16-bit or 32-bit
-   breakpoint should be used.  It returns a pointer to a string of
-   bytes that encode a breakpoint instruction, stores the length of
-   the string to *lenptr, and adjusts the program counter (if
-   necessary) to point to the actual memory location where the
-   breakpoint should be inserted.  */
-
-static const unsigned char *
-arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+static int
+arm_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
@@ -7818,38 +7810,61 @@ arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
       if (tdep->thumb2_breakpoint != NULL)
 	{
 	  gdb_byte buf[2];
+
 	  if (target_read_memory (*pcptr, buf, 2) == 0)
 	    {
 	      unsigned short inst1;
+
 	      inst1 = extract_unsigned_integer (buf, 2, byte_order_for_code);
 	      if (thumb_insn_size (inst1) == 4)
-		{
-		  *lenptr = tdep->thumb2_breakpoint_size;
-		  return tdep->thumb2_breakpoint;
-		}
+		return ARM_BP_KIND_THUMB2;
 	    }
 	}
 
-      *lenptr = tdep->thumb_breakpoint_size;
-      return tdep->thumb_breakpoint;
+      return ARM_BP_KIND_THUMB;
     }
   else
+    return ARM_BP_KIND_ARM;
+
+}
+
+static const gdb_byte *
+arm_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  switch (kind)
     {
-      *lenptr = tdep->arm_breakpoint_size;
+    case ARM_BP_KIND_ARM:
+      *size = tdep->arm_breakpoint_size;
       return tdep->arm_breakpoint;
+    case ARM_BP_KIND_THUMB:
+      *size = tdep->thumb_breakpoint_size;
+      return tdep->thumb_breakpoint;
+    case ARM_BP_KIND_THUMB2:
+      *size = tdep->thumb2_breakpoint_size;
+      return tdep->thumb2_breakpoint;
+    default:
+      gdb_assert_not_reached ("unexpected arm breakpoint kind");
     }
 }
 
+/* Determine the type and size of breakpoint to insert at PCPTR.  Uses
+   the program counter value to determine whether a 16-bit or 32-bit
+   breakpoint should be used.  It returns a pointer to a string of
+   bytes that encode a breakpoint instruction, stores the length of
+   the string to *lenptr, and adjusts the program counter (if
+   necessary) to point to the actual memory location where the
+   breakpoint should be inserted.  */
+
+GDBARCH_BREAKPOINT_FROM_PC (arm)
+
 static void
 arm_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
 			       int *kindptr)
 {
-  arm_breakpoint_from_pc (gdbarch, pcptr, kindptr);
 
-  if (arm_pc_is_thumb (gdbarch, *pcptr) && *kindptr == 4)
-    /* The documented magic value for a 32-bit Thumb-2 breakpoint, so
-       that this is not confused with a 32-bit ARM breakpoint.  */
-    *kindptr = ARM_BP_KIND_THUMB2;
+  *kindptr = arm_breakpoint_kind_from_pc (gdbarch, pcptr);
 }
 
 /* Extract from an array REGBUF containing the (raw) register state a
@@ -9359,7 +9374,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
   /* Breakpoint manipulation.  */
-  set_gdbarch_breakpoint_from_pc (gdbarch, arm_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (arm);
   set_gdbarch_remote_breakpoint_from_pc (gdbarch,
 					 arm_remote_breakpoint_from_pc);
 
diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c
index d07bf6e..d895997 100644
--- a/gdb/bfin-tdep.c
+++ b/gdb/bfin-tdep.c
@@ -568,28 +568,28 @@ bfin_reg_to_regnum (struct gdbarch *gdbarch, int reg)
   return map_gcc_gdb[reg];
 }
 
-/* This function implements the 'breakpoint_from_pc' gdbarch method.
-   It returns a pointer to a string of bytes that encode a breakpoint
-   instruction, stores the length of the string to *lenptr, and
-   adjusts the program counter (if necessary) to point to the actual
-   memory location where the breakpoint should be inserted.  */
-
-static const unsigned char *
-bfin_breakpoint_from_pc (struct gdbarch *gdbarch,
-			 CORE_ADDR *pcptr, int *lenptr)
+static int
+bfin_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   unsigned short iw;
-  static unsigned char bfin_breakpoint[] = {0xa1, 0x00, 0x00, 0x00};
-  static unsigned char bfin_sim_breakpoint[] = {0x25, 0x00, 0x00, 0x00};
 
   iw = read_memory_unsigned_integer (*pcptr, 2, byte_order);
 
   if ((iw & 0xf000) >= 0xc000)
     /* 32-bit instruction.  */
-    *lenptr = 4;
+    return 4;
   else
-    *lenptr = 2;
+    return 2;
+}
+
+static const gdb_byte *
+bfin_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  static unsigned char bfin_breakpoint[] = {0xa1, 0x00, 0x00, 0x00};
+  static unsigned char bfin_sim_breakpoint[] = {0x25, 0x00, 0x00, 0x00};
+
+  *size = kind;
 
   if (strcmp (target_shortname, "sim") == 0)
     return bfin_sim_breakpoint;
@@ -597,6 +597,14 @@ bfin_breakpoint_from_pc (struct gdbarch *gdbarch,
     return bfin_breakpoint;
 }
 
+/* This function implements the 'breakpoint_from_pc' gdbarch method.
+   It returns a pointer to a string of bytes that encode a breakpoint
+   instruction, stores the length of the string to *lenptr, and
+   adjusts the program counter (if necessary) to point to the actual
+   memory location where the breakpoint should be inserted.  */
+
+GDBARCH_BREAKPOINT_FROM_PC (bfin)
+
 static void
 bfin_extract_return_value (struct type *type,
 			   struct regcache *regs,
@@ -826,7 +834,7 @@ bfin_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_return_value (gdbarch, bfin_return_value);
   set_gdbarch_skip_prologue (gdbarch, bfin_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  set_gdbarch_breakpoint_from_pc (gdbarch, bfin_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (bfin);
   set_gdbarch_decr_pc_after_break (gdbarch, 2);
   set_gdbarch_frame_args_skip (gdbarch, 8);
   set_gdbarch_unwind_pc (gdbarch, bfin_unwind_pc);
diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c
index 1d29524..bee95cf 100644
--- a/gdb/cris-tdep.c
+++ b/gdb/cris-tdep.c
@@ -1391,20 +1391,20 @@ cris_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return sp;
 }
 
-/* Use the program counter to determine the contents and size of a breakpoint
-   instruction.  It returns a pointer to a string of bytes that encode a
-   breakpoint instruction, stores the length of the string to *lenptr, and
-   adjusts pcptr (if necessary) to point to the actual memory location where
-   the breakpoint should be inserted.  */
+static int
+cris_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return 2;
+}
 
-static const unsigned char *
-cris_breakpoint_from_pc (struct gdbarch *gdbarch,
-			 CORE_ADDR *pcptr, int *lenptr)
+static const gdb_byte *
+cris_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   static unsigned char break8_insn[] = {0x38, 0xe9};
   static unsigned char break15_insn[] = {0x3f, 0xe9};
-  *lenptr = 2;
+
+  *size = kind;
 
   if (tdep->cris_mode == cris_mode_guru)
     return break15_insn;
@@ -1412,6 +1412,14 @@ cris_breakpoint_from_pc (struct gdbarch *gdbarch,
     return break8_insn;
 }
 
+/* Use the program counter to determine the contents and size of a breakpoint
+   instruction.  It returns a pointer to a string of bytes that encode a
+   breakpoint instruction, stores the length of the string to *lenptr, and
+   adjusts pcptr (if necessary) to point to the actual memory location where
+   the breakpoint should be inserted.  */
+
+GDBARCH_BREAKPOINT_FROM_PC (cris)
+
 /* Returns 1 if spec_reg is applicable to the current gdbarch's CRIS version,
    0 otherwise.  */
 
@@ -4123,7 +4131,7 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* The stack grows downward.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, cris_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (cris);
   
   set_gdbarch_unwind_pc (gdbarch, cris_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, cris_unwind_sp);
diff --git a/gdb/iq2000-tdep.c b/gdb/iq2000-tdep.c
index 600d70a..ecd9074 100644
--- a/gdb/iq2000-tdep.c
+++ b/gdb/iq2000-tdep.c
@@ -469,22 +469,29 @@ static const struct frame_base iq2000_frame_base = {
   iq2000_frame_base_address
 };
 
-static const unsigned char *
-iq2000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-			   int *lenptr)
+static int
+iq2000_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
-  static const unsigned char big_breakpoint[] = { 0x00, 0x00, 0x00, 0x0d };
-  static const unsigned char little_breakpoint[] = { 0x0d, 0x00, 0x00, 0x00 };
-
   if ((*pcptr & 3) != 0)
     error (_("breakpoint_from_pc: invalid breakpoint address 0x%lx"),
 	   (long) *pcptr);
 
-  *lenptr = 4;
+  return 4;
+}
+
+static const gdb_byte *
+iq2000_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  static const unsigned char big_breakpoint[] = { 0x00, 0x00, 0x00, 0x0d };
+  static const unsigned char little_breakpoint[] = { 0x0d, 0x00, 0x00, 0x00 };
+  *size = kind;
+
   return (gdbarch_byte_order (gdbarch)
 	  == BFD_ENDIAN_BIG) ? big_breakpoint : little_breakpoint;
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (iq2000)
+
 /* Target function return value methods: */
 
 /* Function: store_return_value
@@ -826,7 +833,7 @@ iq2000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_double_format        (gdbarch, floatformats_ieee_double);
   set_gdbarch_long_double_format   (gdbarch, floatformats_ieee_double);
   set_gdbarch_return_value	   (gdbarch, iq2000_return_value);
-  set_gdbarch_breakpoint_from_pc   (gdbarch, iq2000_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (iq2000);
   set_gdbarch_frame_args_skip      (gdbarch, 0);
   set_gdbarch_skip_prologue        (gdbarch, iq2000_skip_prologue);
   set_gdbarch_inner_than           (gdbarch, core_addr_lessthan);
diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c
index bc4b2d2..105fb9e 100644
--- a/gdb/m32r-tdep.c
+++ b/gdb/m32r-tdep.c
@@ -165,9 +165,17 @@ m32r_memory_remove_breakpoint (struct gdbarch *gdbarch,
   return val;
 }
 
+static int
+m32r_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  if ((*pcptr & 3) == 0)
+    return 4;
+  else
+    return 2;
+}
+
 static const gdb_byte *
-m32r_breakpoint_from_pc (struct gdbarch *gdbarch,
-			 CORE_ADDR *pcptr, int *lenptr)
+m32r_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
 {
   static gdb_byte be_bp_entry[] = {
     0x10, 0xf1, 0x70, 0x00
@@ -175,39 +183,22 @@ m32r_breakpoint_from_pc (struct gdbarch *gdbarch,
   static gdb_byte le_bp_entry[] = {
     0x00, 0x70, 0xf1, 0x10
   };	/* dpt -> nop */
-  gdb_byte *bp;
+
+  *size = kind;
 
   /* Determine appropriate breakpoint.  */
   if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-    {
-      if ((*pcptr & 3) == 0)
-	{
-	  bp = be_bp_entry;
-	  *lenptr = 4;
-	}
-      else
-	{
-	  bp = be_bp_entry;
-	  *lenptr = 2;
-	}
-    }
+    return be_bp_entry;
   else
     {
-      if ((*pcptr & 3) == 0)
-	{
-	  bp = le_bp_entry;
-	  *lenptr = 4;
-	}
+      if (kind == 4)
+	return le_bp_entry;
       else
-	{
-	  bp = le_bp_entry + 2;
-	  *lenptr = 2;
-	}
+	return le_bp_entry + 2;
     }
-
-  return bp;
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (m32r)
 
 char *m32r_register_names[] = {
   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -929,7 +920,7 @@ m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_skip_prologue (gdbarch, m32r_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  set_gdbarch_breakpoint_from_pc (gdbarch, m32r_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (m32r);
   set_gdbarch_memory_insert_breakpoint (gdbarch,
 					m32r_memory_insert_breakpoint);
   set_gdbarch_memory_remove_breakpoint (gdbarch,
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 34df8d0..1a9cfa5 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -7050,141 +7050,137 @@ gdb_print_insn_mips_n64 (bfd_vma memaddr, struct disassemble_info *info)
   return gdb_print_insn_mips (memaddr, info);
 }
 
-/* This function implements gdbarch_breakpoint_from_pc.  It uses the
-   program counter value to determine whether a 16- or 32-bit breakpoint
-   should be used.  It returns a pointer to a string of bytes that encode a
-   breakpoint instruction, stores the length of the string to *lenptr, and
-   adjusts pc (if necessary) to point to the actual memory location where
-   the breakpoint should be inserted.  */
-
-static const gdb_byte *
-mips_breakpoint_from_pc (struct gdbarch *gdbarch,
-			 CORE_ADDR *pcptr, int *lenptr)
-{
-  CORE_ADDR pc = *pcptr;
-
-  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-    {
-      if (mips_pc_is_mips16 (gdbarch, pc))
-	{
-	  static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 };
-	  *pcptr = unmake_compact_addr (pc);
-	  *lenptr = sizeof (mips16_big_breakpoint);
-	  return mips16_big_breakpoint;
-	}
-      else if (mips_pc_is_micromips (gdbarch, pc))
-	{
-	  static gdb_byte micromips16_big_breakpoint[] = { 0x46, 0x85 };
-	  static gdb_byte micromips32_big_breakpoint[] = { 0, 0x5, 0, 0x7 };
-	  ULONGEST insn;
-	  int err;
-	  int size;
-
-	  insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &err);
-	  size = err ? 2 : mips_insn_size (ISA_MICROMIPS, insn);
-	  *pcptr = unmake_compact_addr (pc);
-	  *lenptr = size;
-	  return (size == 2) ? micromips16_big_breakpoint
-			     : micromips32_big_breakpoint;
-	}
-      else
-	{
-	  /* The IDT board uses an unusual breakpoint value, and
-	     sometimes gets confused when it sees the usual MIPS
-	     breakpoint instruction.  */
-	  static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
-	  static gdb_byte pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
-	  static gdb_byte idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
-	  /* Likewise, IRIX appears to expect a different breakpoint,
-	     although this is not apparent until you try to use pthreads.  */
-	  static gdb_byte irix_big_breakpoint[] = { 0, 0, 0, 0xd };
-
-	  *lenptr = sizeof (big_breakpoint);
-
-	  if (strcmp (target_shortname, "mips") == 0)
-	    return idt_big_breakpoint;
-	  else if (strcmp (target_shortname, "ddb") == 0
-		   || strcmp (target_shortname, "pmon") == 0
-		   || strcmp (target_shortname, "lsi") == 0)
-	    return pmon_big_breakpoint;
-	  else if (gdbarch_osabi (gdbarch) == GDB_OSABI_IRIX)
-	    return irix_big_breakpoint;
-	  else
-	    return big_breakpoint;
-	}
-    }
-  else
-    {
-      if (mips_pc_is_mips16 (gdbarch, pc))
-	{
-	  static gdb_byte mips16_little_breakpoint[] = { 0xa5, 0xe8 };
-	  *pcptr = unmake_compact_addr (pc);
-	  *lenptr = sizeof (mips16_little_breakpoint);
-	  return mips16_little_breakpoint;
-	}
-      else if (mips_pc_is_micromips (gdbarch, pc))
-	{
-	  static gdb_byte micromips16_little_breakpoint[] = { 0x85, 0x46 };
-	  static gdb_byte micromips32_little_breakpoint[] = { 0x5, 0, 0x7, 0 };
-	  ULONGEST insn;
-	  int err;
-	  int size;
-
-	  insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &err);
-	  size = err ? 2 : mips_insn_size (ISA_MICROMIPS, insn);
-	  *pcptr = unmake_compact_addr (pc);
-	  *lenptr = size;
-	  return (size == 2) ? micromips16_little_breakpoint
-			     : micromips32_little_breakpoint;
-	}
-      else
-	{
-	  static gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 };
-	  static gdb_byte pmon_little_breakpoint[] = { 0xd, 0, 0, 0 };
-	  static gdb_byte idt_little_breakpoint[] = { 0xd, 0x0a, 0, 0 };
-
-	  *lenptr = sizeof (little_breakpoint);
-
-	  if (strcmp (target_shortname, "mips") == 0)
-	    return idt_little_breakpoint;
-	  else if (strcmp (target_shortname, "ddb") == 0
-		   || strcmp (target_shortname, "pmon") == 0
-		   || strcmp (target_shortname, "lsi") == 0)
-	    return pmon_little_breakpoint;
-	  else
-	    return little_breakpoint;
-	}
-    }
-}
-
-/* Determine the remote breakpoint kind suitable for the PC.  */
-
-static void
-mips_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-				int *kindptr)
+static int
+mips_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   CORE_ADDR pc = *pcptr;
 
   if (mips_pc_is_mips16 (gdbarch, pc))
     {
       *pcptr = unmake_compact_addr (pc);
-      *kindptr = MIPS_BP_KIND_16BIT_MIPS16;
+      return MIPS_BP_KIND_16BIT_MIPS16;
     }
   else if (mips_pc_is_micromips (gdbarch, pc))
     {
       ULONGEST insn;
       int status;
 
+      *pcptr = unmake_compact_addr (pc);
       insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
       if (status || (mips_insn_size (ISA_MICROMIPS, insn) == 2))
-	*kindptr = MIPS_BP_KIND_16BIT_MICROMIPS;
+	return MIPS_BP_KIND_16BIT_MICROMIPS;
       else
-	*kindptr = MIPS_BP_KIND_32BIT_MICROMIPS;
-
-      *pcptr = unmake_compact_addr (pc);
+	return MIPS_BP_KIND_32BIT_MICROMIPS;
     }
   else
-    *kindptr = MIPS_BP_KIND_32BIT;
+    return MIPS_BP_KIND_32BIT;
+}
+
+static const gdb_byte *
+mips_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+
+  switch (kind)
+    {
+    case MIPS_BP_KIND_16BIT_MIPS16:
+      {
+	static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 };
+	static gdb_byte mips16_little_breakpoint[] = { 0xa5, 0xe8 };
+
+	*size = 2;
+	if (byte_order_for_code == BFD_ENDIAN_BIG)
+	  return mips16_big_breakpoint;
+	else
+	  return mips16_little_breakpoint;
+      }
+    case MIPS_BP_KIND_16BIT_MICROMIPS:
+      {
+	static gdb_byte micromips16_big_breakpoint[] = { 0x46, 0x85 };
+	static gdb_byte micromips16_little_breakpoint[] = { 0x85, 0x46 };
+
+	*size = 2;
+
+	if (byte_order_for_code == BFD_ENDIAN_BIG)
+	  return micromips16_big_breakpoint;
+	else
+	  return micromips16_little_breakpoint;
+      }
+    case MIPS_BP_KIND_32BIT_MICROMIPS:
+      {
+	static gdb_byte micromips32_big_breakpoint[] = { 0, 0x5, 0, 0x7 };
+	static gdb_byte micromips32_little_breakpoint[] = { 0x5, 0, 0x7, 0 };
+
+	*size = 4;
+	if (byte_order_for_code == BFD_ENDIAN_BIG)
+	  return micromips32_big_breakpoint;
+	else
+	  return micromips32_little_breakpoint;
+      }
+    case MIPS_BP_KIND_32BIT:
+      {
+	/* The IDT board uses an unusual breakpoint value, and
+	   sometimes gets confused when it sees the usual MIPS
+	   breakpoint instruction.  */
+	static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
+	static gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 };
+	static gdb_byte pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
+	static gdb_byte pmon_little_breakpoint[] = { 0xd, 0, 0, 0 };
+	static gdb_byte idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
+	static gdb_byte idt_little_breakpoint[] = { 0xd, 0x0a, 0, 0 };
+	/* Likewise, IRIX appears to expect a different breakpoint,
+	   although this is not apparent until you try to use pthreads.  */
+	static gdb_byte irix_big_breakpoint[] = { 0, 0, 0, 0xd };
+
+	*size = 4;
+
+	if (strcmp (target_shortname, "mips") == 0)
+	  {
+	    if (byte_order_for_code == BFD_ENDIAN_BIG)
+	      return idt_big_breakpoint;
+	    else
+	      return idt_little_breakpoint;
+	  }
+	else if (strcmp (target_shortname, "ddb") == 0
+		 || strcmp (target_shortname, "pmon") == 0
+		 || strcmp (target_shortname, "lsi") == 0)
+	  {
+	    if (byte_order_for_code == BFD_ENDIAN_BIG)
+	      return pmon_big_breakpoint;
+	    else
+	      return pmon_little_breakpoint;
+	  }
+	else if (gdbarch_osabi (gdbarch) == GDB_OSABI_IRIX)
+	  return irix_big_breakpoint;
+	else
+	  {
+	    if (byte_order_for_code == BFD_ENDIAN_BIG)
+	      return big_breakpoint;
+	    else
+	      return little_breakpoint;
+	  }
+      }
+    default:
+      gdb_assert_not_reached ("unexpected mips breakpoint kind");
+    };
+}
+
+/* This function implements gdbarch_breakpoint_from_pc.  It uses the
+   program counter value to determine whether a 16- or 32-bit breakpoint
+   should be used.  It returns a pointer to a string of bytes that encode a
+   breakpoint instruction, stores the length of the string to *lenptr, and
+   adjusts pc (if necessary) to point to the actual memory location where
+   the breakpoint should be inserted.  */
+
+GDBARCH_BREAKPOINT_FROM_PC (mips)
+
+/* Determine the remote breakpoint kind suitable for the PC.  */
+
+static void
+mips_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+				int *kindptr)
+{
+  *kindptr = mips_breakpoint_kind_from_pc (gdbarch, pcptr);
 }
 
 /* Return non-zero if the standard MIPS instruction INST has a branch
@@ -8797,7 +8793,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_value_to_register (gdbarch, mips_value_to_register);
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (mips);
   set_gdbarch_remote_breakpoint_from_pc (gdbarch,
 					 mips_remote_breakpoint_from_pc);
   set_gdbarch_adjust_breakpoint_address (gdbarch,
diff --git a/gdb/mt-tdep.c b/gdb/mt-tdep.c
index 5d7f31c..0adf413 100644
--- a/gdb/mt-tdep.c
+++ b/gdb/mt-tdep.c
@@ -449,26 +449,33 @@ mt_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   return pc;
 }
 
-/* The breakpoint instruction must be the same size as the smallest
-   instruction in the instruction set.
-
-   The BP for ms1 is defined as 0x68000000 (BREAK).
-   The BP for ms2 is defined as 0x69000000 (illegal).  */
+static int
+mt_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return 4;
+}
 
 static const gdb_byte *
-mt_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
-		       int *bp_size)
+mt_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
 {
+  /* The breakpoint instruction must be the same size as the smallest
+     instruction in the instruction set.
+
+     The BP for ms1 is defined as 0x68000000 (BREAK).
+     The BP for ms2 is defined as 0x69000000 (illegal).  */
   static gdb_byte ms1_breakpoint[] = { 0x68, 0, 0, 0 };
   static gdb_byte ms2_breakpoint[] = { 0x69, 0, 0, 0 };
 
-  *bp_size = 4;
+  *size = kind;
+
   if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_ms2)
     return ms2_breakpoint;
-  
+
   return ms1_breakpoint;
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (mt)
+
 /* Select the correct coprocessor register bank.  Return the pseudo
    regnum we really want to read.  */
 
@@ -1162,7 +1169,7 @@ mt_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_pseudo_register_write (gdbarch, mt_pseudo_register_write);
   set_gdbarch_skip_prologue (gdbarch, mt_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  set_gdbarch_breakpoint_from_pc (gdbarch, mt_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (mt);
   set_gdbarch_decr_pc_after_break (gdbarch, 0);
   set_gdbarch_frame_args_skip (gdbarch, 0);
   set_gdbarch_print_insn (gdbarch, print_insn_mt);
diff --git a/gdb/nios2-tdep.c b/gdb/nios2-tdep.c
index 8bfd8b3..d48e156 100644
--- a/gdb/nios2-tdep.c
+++ b/gdb/nios2-tdep.c
@@ -1693,9 +1693,30 @@ nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
   return nios2_analyze_prologue (gdbarch, start_pc, start_pc, &cache, NULL);
 }
 
-/* Implement the breakpoint_from_pc gdbarch hook.
+static int
+nios2_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+
+  if (mach == bfd_mach_nios2r2)
+    {
+      unsigned int insn;
+      const struct nios2_opcode *op
+	= nios2_fetch_insn (gdbarch, *pcptr, &insn);
+
+      if (op && op->size == NIOS2_CDX_OPCODE_SIZE)
+	return NIOS2_CDX_OPCODE_SIZE;
+      else
+	return NIOS2_OPCODE_SIZE;
+    }
+  else
+    return NIOS2_OPCODE_SIZE;
+}
 
-   The Nios II ABI for Linux says: "Userspace programs should not use
+static const gdb_byte *
+nios2_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+/* The Nios II ABI for Linux says: "Userspace programs should not use
    the break instruction and userspace debuggers should not insert
    one." and "Userspace breakpoints are accomplished using the trap
    instruction with immediate operand 31 (all ones)."
@@ -1703,54 +1724,53 @@ nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
    So, we use "trap 31" consistently as the breakpoint on bare-metal
    as well as Linux targets.  */
 
-static const gdb_byte*
-nios2_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
-			  int *bp_size)
-{
-  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
-  unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+  /* R2 trap encoding:
+     ((0x2d << 26) | (0x1f << 21) | (0x1d << 16) | (0x20 << 0))
+     0xb7fd0020
+     CDX trap.n encoding:
+     ((0xd << 12) | (0x1f << 6) | (0x9 << 0))
+     0xd7c9
+     Note that code is always little-endian on R2.  */
+  *size = kind;
 
-  if (mach == bfd_mach_nios2r2)
+  if (kind == NIOS2_CDX_OPCODE_SIZE)
     {
-      /* R2 trap encoding:
-	   ((0x2d << 26) | (0x1f << 21) | (0x1d << 16) | (0x20 << 0))
-	   0xb7fd0020
-	 CDX trap.n encoding:
-	   ((0xd << 12) | (0x1f << 6) | (0x9 << 0))
-	   0xd7c9
-         Note that code is always little-endian on R2.  */
-      static const gdb_byte r2_breakpoint_le[] = {0x20, 0x00, 0xfd, 0xb7};
       static const gdb_byte cdx_breakpoint_le[] = {0xc9, 0xd7};
-      unsigned int insn;
-      const struct nios2_opcode *op
-	= nios2_fetch_insn (gdbarch, *bp_addr, &insn);
 
-      if (op && op->size == NIOS2_CDX_OPCODE_SIZE)
+      return cdx_breakpoint_le;
+    }
+  else
+    {
+      unsigned long mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+
+      if (mach == bfd_mach_nios2r2)
 	{
-	  *bp_size = NIOS2_CDX_OPCODE_SIZE;
-	  return cdx_breakpoint_le;
+	  static const gdb_byte r2_breakpoint_le[] = {0x20, 0x00, 0xfd, 0xb7};
+
+	  return r2_breakpoint_le;
 	}
       else
 	{
-	  *bp_size = NIOS2_OPCODE_SIZE;
-	  return r2_breakpoint_le;
+	  enum bfd_endian byte_order_for_code
+	    = gdbarch_byte_order_for_code (gdbarch);
+	  /* R1 trap encoding:
+	     ((0x1d << 17) | (0x2d << 11) | (0x1f << 6) | (0x3a << 0))
+	     0x003b6ffa */
+	  static const gdb_byte r1_breakpoint_le[] = {0xfa, 0x6f, 0x3b, 0x0};
+	  static const gdb_byte r1_breakpoint_be[] = {0x0, 0x3b, 0x6f, 0xfa};
+
+	  if (byte_order_for_code == BFD_ENDIAN_BIG)
+	    return r1_breakpoint_be;
+	  else
+	    return r1_breakpoint_le;
 	}
     }
-  else
-    {
-      /* R1 trap encoding:
-	 ((0x1d << 17) | (0x2d << 11) | (0x1f << 6) | (0x3a << 0))
-	 0x003b6ffa */
-      static const gdb_byte r1_breakpoint_le[] = {0xfa, 0x6f, 0x3b, 0x0};
-      static const gdb_byte r1_breakpoint_be[] = {0x0, 0x3b, 0x6f, 0xfa};
-      *bp_size = NIOS2_OPCODE_SIZE;
-      if (byte_order_for_code == BFD_ENDIAN_BIG)
-	return r1_breakpoint_be;
-      else
-	return r1_breakpoint_le;
-    }
 }
 
+/* Implement the breakpoint_from_pc gdbarch hook.  */
+
+GDBARCH_BREAKPOINT_FROM_PC (nios2)
+
 /* Implement the print_insn gdbarch method.  */
 
 static int
@@ -2315,7 +2335,7 @@ nios2_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_skip_prologue (gdbarch, nios2_skip_prologue);
   set_gdbarch_stack_frame_destroyed_p (gdbarch, nios2_stack_frame_destroyed_p);
-  set_gdbarch_breakpoint_from_pc (gdbarch, nios2_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (nios2);
 
   set_gdbarch_dummy_id (gdbarch, nios2_dummy_id);
   set_gdbarch_unwind_pc (gdbarch, nios2_unwind_pc);
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index e180641..9f19ad2 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -966,18 +966,11 @@ rs6000_fetch_pointer_argument (struct frame_info *frame, int argi,
 
 /* Sequence of bytes for breakpoint instruction.  */
 
-static const unsigned char *
-rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
-			   int *bp_size)
-{
-  static unsigned char big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
-  static unsigned char little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
-  *bp_size = 4;
-  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-    return big_breakpoint;
-  else
-    return little_breakpoint;
-}
+static unsigned char big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
+static unsigned char little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
+
+GDBARCH_BREAKPOINT_MANIPULATION_ENDIAN (rs6000, little_breakpoint,
+					big_breakpoint)
 
 /* Instruction masks for displaced stepping.  */
 #define BRANCH_MASK 0xfc000000
@@ -6039,7 +6032,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_skip_main_prologue (gdbarch, rs6000_skip_main_prologue);
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (rs6000);
 
   /* The value of symbols of type N_SO and N_FUN maybe null when
      it shouldn't be.  */
diff --git a/gdb/score-tdep.c b/gdb/score-tdep.c
index 8e08d05..c325d48 100644
--- a/gdb/score-tdep.c
+++ b/gdb/score-tdep.c
@@ -306,69 +306,82 @@ score3_adjust_pc_and_fetch_inst (CORE_ADDR *pcptr, int *lenptr,
   return &inst;
 }
 
-static const gdb_byte *
-score7_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-			   int *lenptr)
+static int
+score7_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  gdb_byte buf[SCORE_INSTLEN] = { 0 };
   int ret;
   unsigned int raw;
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[SCORE_INSTLEN] = { 0 };
 
   if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0)
     {
       error (_("Error: target_read_memory in file:%s, line:%d!"),
-             __FILE__, __LINE__);
+	     __FILE__, __LINE__);
     }
   raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order);
 
-  if (byte_order == BFD_ENDIAN_BIG)
+  if (!(raw & 0x80008000))
     {
-      if (!(raw & 0x80008000))
-        {
-          /* 16bits instruction.  */
-          static gdb_byte big_breakpoint16[] = { 0x60, 0x02 };
-          *pcptr &= ~0x1;
-          *lenptr = sizeof (big_breakpoint16);
-          return big_breakpoint16;
-        }
+      /* 16bits instruction.  */
+      *pcptr &= ~0x1;
+      return 2;
+    }
+  else
+    {
+      /* 32bits instruction.  */
+      *pcptr &= ~0x3;
+      return 4;
+    }
+}
+
+static const gdb_byte *
+score7_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+  *size = kind;
+
+  if (kind == 4)
+    {
+      static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 };
+      static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 };
+
+      if (byte_order == BFD_ENDIAN_BIG)
+	return big_breakpoint32;
       else
-        {
-          /* 32bits instruction.  */
-          static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 };
-          *pcptr &= ~0x3;
-          *lenptr = sizeof (big_breakpoint32);
-          return big_breakpoint32;
-        }
+	return little_breakpoint32;
     }
   else
     {
-      if (!(raw & 0x80008000))
-        {
-          /* 16bits instruction.  */
-          static gdb_byte little_breakpoint16[] = { 0x02, 0x60 };
-          *pcptr &= ~0x1;
-          *lenptr = sizeof (little_breakpoint16);
-          return little_breakpoint16;
-        }
+      static gdb_byte big_breakpoint16[] = { 0x60, 0x02 };
+      static gdb_byte little_breakpoint16[] = { 0x02, 0x60 };
+
+      if (byte_order == BFD_ENDIAN_BIG)
+	return big_breakpoint16;
       else
-        {
-          /* 32bits instruction.  */
-          static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 };
-          *pcptr &= ~0x3;
-          *lenptr = sizeof (little_breakpoint32);
-          return little_breakpoint32;
-        }
+	return little_breakpoint16;
     }
 }
 
-static const gdb_byte *
-score3_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-			   int *lenptr)
+GDBARCH_BREAKPOINT_FROM_PC (score7)
+
+static int
+score3_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  CORE_ADDR adjust_pc = *pcptr; 
   int len;
+
+  score3_adjust_pc_and_fetch_inst (pcptr, &len, byte_order);
+
+  return len;
+}
+
+static const gdb_byte *
+score3_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  int index = 0;
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   static gdb_byte score_break_insns[6][6] = {
     /* The following three instructions are big endian.  */
     { 0x00, 0x20 },
@@ -379,20 +392,14 @@ score3_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
     { 0x00, 0x80, 0x06, 0x00 },
     { 0x00, 0x80, 0x00, 0x80, 0x00, 0x00 }};
 
-  gdb_byte *p = NULL;
-  int index = 0;
-
-  score3_adjust_pc_and_fetch_inst (&adjust_pc, &len, byte_order);
-
-  index = ((byte_order == BFD_ENDIAN_BIG) ? 0 : 3) + (len / 2 - 1);
-  p = score_break_insns[index];
+  *size = kind;
 
-  *pcptr = adjust_pc;
-  *lenptr = len;
-
-  return p;
+  index = ((byte_order == BFD_ENDIAN_BIG) ? 0 : 3) + (kind / 2 - 1);
+  return score_break_insns[index];
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (score3)
+
 static CORE_ADDR
 score_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
 {
@@ -1485,7 +1492,7 @@ score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   switch (target_mach)
     {
     case bfd_mach_score7:
-      set_gdbarch_breakpoint_from_pc (gdbarch, score7_breakpoint_from_pc);
+      SET_GDBARCH_BREAKPOINT_MANIPULATION (score7);
       set_gdbarch_skip_prologue (gdbarch, score7_skip_prologue);
       set_gdbarch_stack_frame_destroyed_p (gdbarch,
 					   score7_stack_frame_destroyed_p);
@@ -1497,7 +1504,7 @@ score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       break;
 
     case bfd_mach_score3:
-      set_gdbarch_breakpoint_from_pc (gdbarch, score3_breakpoint_from_pc);
+      SET_GDBARCH_BREAKPOINT_MANIPULATION (score3);
       set_gdbarch_skip_prologue (gdbarch, score3_skip_prologue);
       set_gdbarch_stack_frame_destroyed_p (gdbarch,
 					   score3_stack_frame_destroyed_p);
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 694f5f7..0ea5716 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -417,11 +417,16 @@ sh_sh4al_dsp_register_name (struct gdbarch *gdbarch, int reg_nr)
   return register_names[reg_nr];
 }
 
-static const unsigned char *
-sh_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+static int
+sh_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
-  /* 0xc3c3 is trapa #c3, and it works in big and little endian modes.  */
-  static unsigned char breakpoint[] = { 0xc3, 0xc3 };
+  return 2;
+}
+
+static const gdb_byte *
+sh_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  *size = kind;
 
   /* For remote stub targets, trapa #20 is used.  */
   if (strcmp (target_shortname, "remote") == 0)
@@ -430,21 +435,22 @@ sh_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
       static unsigned char little_remote_breakpoint[] = { 0x20, 0xc3 };
 
       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-	{
-	  *lenptr = sizeof (big_remote_breakpoint);
-	  return big_remote_breakpoint;
-	}
+	return big_remote_breakpoint;
       else
-	{
-	  *lenptr = sizeof (little_remote_breakpoint);
-	  return little_remote_breakpoint;
-	}
+	return little_remote_breakpoint;
     }
+  else
+    {
+      /* 0xc3c3 is trapa #c3, and it works in big and little endian
+	 modes.  */
+      static unsigned char breakpoint[] = { 0xc3, 0xc3 };
 
-  *lenptr = sizeof (breakpoint);
-  return breakpoint;
+      return breakpoint;
+    }
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (sh)
+
 /* Prologue looks like
    mov.l	r14,@-r15
    sts.l	pr,@-r15
@@ -2273,7 +2279,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_register_type (gdbarch, sh_default_register_type);
   set_gdbarch_register_reggroup_p (gdbarch, sh_register_reggroup_p);
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, sh_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (sh);
 
   set_gdbarch_print_insn (gdbarch, print_insn_sh);
   set_gdbarch_register_sim_regno (gdbarch, legacy_register_sim_regno);
diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c
index ee8d19c..4f97223 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -252,11 +252,24 @@ pc_is_isa32 (bfd_vma memaddr)
     return 0;
 }
 
-static const unsigned char *
-sh64_breakpoint_from_pc (struct gdbarch *gdbarch,
-			 CORE_ADDR *pcptr, int *lenptr)
+static int
+sh64_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
-  /* The BRK instruction for shmedia is 
+  if (pc_is_isa32 (*pcptr))
+    {
+      *pcptr = UNMAKE_ISA32_ADDR (*pcptr);
+      return 4;
+    }
+  else
+    return 2;
+}
+
+static const gdb_byte *
+sh64_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  *size = kind;
+
+  /* The BRK instruction for shmedia is
      01101111 11110101 11111111 11110000
      which translates in big endian mode to 0x6f, 0xf5, 0xff, 0xf0
      and in little endian mode to 0xf0, 0xff, 0xf5, 0x6f */
@@ -266,44 +279,34 @@ sh64_breakpoint_from_pc (struct gdbarch *gdbarch,
      which translates in big endian mode to 0x0, 0x3b
      and in little endian mode to 0x3b, 0x0 */
 
-  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+  if (kind == 4)
     {
-      if (pc_is_isa32 (*pcptr))
-	{
-	  static unsigned char big_breakpoint_media[] = {
-	    0x6f, 0xf5, 0xff, 0xf0
-	  };
-	  *pcptr = UNMAKE_ISA32_ADDR (*pcptr);
-	  *lenptr = sizeof (big_breakpoint_media);
-	  return big_breakpoint_media;
-	}
+      static unsigned char big_breakpoint_media[] = {
+	0x6f, 0xf5, 0xff, 0xf0
+      };
+      static unsigned char little_breakpoint_media[] = {
+	0xf0, 0xff, 0xf5, 0x6f
+      };
+
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	return big_breakpoint_media;
       else
-	{
-	  static unsigned char big_breakpoint_compact[] = {0x0, 0x3b};
-	  *lenptr = sizeof (big_breakpoint_compact);
-	  return big_breakpoint_compact;
-	}
+	return little_breakpoint_media;
     }
   else
     {
-      if (pc_is_isa32 (*pcptr))
-	{
-	  static unsigned char little_breakpoint_media[] = {
-	    0xf0, 0xff, 0xf5, 0x6f
-	  };
-	  *pcptr = UNMAKE_ISA32_ADDR (*pcptr);
-	  *lenptr = sizeof (little_breakpoint_media);
-	  return little_breakpoint_media;
-	}
+      static unsigned char big_breakpoint_compact[] = {0x0, 0x3b};
+      static unsigned char little_breakpoint_compact[] = {0x3b, 0x0};
+
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	return big_breakpoint_compact;
       else
-	{
-	  static unsigned char little_breakpoint_compact[] = {0x3b, 0x0};
-	  *lenptr = sizeof (little_breakpoint_compact);
-	  return little_breakpoint_compact;
-	}
+	return little_breakpoint_compact;
     }
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (sh64)
+
 /* Prologue looks like
    [mov.l       <regs>,@-r15]...
    [sts.l       pr,@-r15]
@@ -2409,7 +2412,7 @@ sh64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_pseudo_register_read (gdbarch, sh64_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, sh64_pseudo_register_write);
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, sh64_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (sh64);
 
   set_gdbarch_print_insn (gdbarch, print_insn_sh);
   set_gdbarch_register_sim_regno (gdbarch, legacy_register_sim_regno);
diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c
index af53938..cf8a30f 100644
--- a/gdb/tic6x-tdep.c
+++ b/gdb/tic6x-tdep.c
@@ -317,15 +317,18 @@ tic6x_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 				 NULL);
 }
 
-/* This is the implementation of gdbarch method breakpiont_from_pc.  */
+static int
+tic6x_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  return 4;
+}
 
 static const gdb_byte *
-tic6x_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
-			  int *bp_size)
+tic6x_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  *bp_size = 4;
+  *size = kind;
 
   if (tdep == NULL || tdep->breakpoint == NULL)
     {
@@ -338,6 +341,10 @@ tic6x_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
     return tdep->breakpoint;
 }
 
+/* This is the implementation of gdbarch method breakpiont_from_pc.  */
+
+GDBARCH_BREAKPOINT_FROM_PC (tic6x)
+
 /* This is the implementation of gdbarch method print_insn.  */
 
 static int
@@ -1294,7 +1301,7 @@ tic6x_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
   set_gdbarch_skip_prologue (gdbarch, tic6x_skip_prologue);
-  set_gdbarch_breakpoint_from_pc (gdbarch, tic6x_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (tic6x);
 
   set_gdbarch_unwind_pc (gdbarch, tic6x_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, tic6x_unwind_sp);
diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c
index d03334e..9cc1b8b 100644
--- a/gdb/v850-tdep.c
+++ b/gdb/v850-tdep.c
@@ -1168,13 +1168,18 @@ v850_return_value (struct gdbarch *gdbarch, struct value *function,
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
-static const unsigned char *
-v850_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-			 int *lenptr)
+static int
+v850_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
-  *lenptr = 2;
+  return 2;
+}
 
-  switch (gdbarch_bfd_arch_info (gdbarch)->mach)
+static const gdb_byte *
+v850_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  *size = kind;
+
+    switch (gdbarch_bfd_arch_info (gdbarch)->mach)
     {
     case bfd_mach_v850e2:
     case bfd_mach_v850e2v3:
@@ -1199,6 +1204,8 @@ v850_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
     }
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (v850)
+
 static struct v850_frame_cache *
 v850_alloc_frame_cache (struct frame_info *this_frame)
 {
@@ -1448,7 +1455,7 @@ v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, v850_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (v850);
   set_gdbarch_return_value (gdbarch, v850_return_value);
   set_gdbarch_push_dummy_call (gdbarch, v850_push_dummy_call);
   set_gdbarch_skip_prologue (gdbarch, v850_skip_prologue);
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index 32beafd..213f343 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -1958,6 +1958,14 @@ xtensa_push_dummy_call (struct gdbarch *gdbarch,
   return sp + SP_ALIGNMENT;
 }
 
+static int
+xtensa_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  if (gdbarch_tdep (gdbarch)->isa_use_density_instructions)
+    return 2;
+  else
+    return 4;
+}
 
 /* Return a breakpoint for the current location of PC.  We always use
    the density version if we have density instructions (regardless of the
@@ -1968,45 +1976,36 @@ xtensa_push_dummy_call (struct gdbarch *gdbarch,
 #define DENSITY_BIG_BREAKPOINT { 0xd2, 0x0f }
 #define DENSITY_LITTLE_BREAKPOINT { 0x2d, 0xf0 }
 
-static const unsigned char *
-xtensa_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-			   int *lenptr)
+static const gdb_byte *
+xtensa_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
 {
-  static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
-  static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
-  static unsigned char density_big_breakpoint[] = DENSITY_BIG_BREAKPOINT;
-  static unsigned char density_little_breakpoint[] = DENSITY_LITTLE_BREAKPOINT;
+  *size = kind;
 
-  DEBUGTRACE ("xtensa_breakpoint_from_pc (pc = 0x%08x)\n", (int) *pcptr);
-
-  if (gdbarch_tdep (gdbarch)->isa_use_density_instructions)
+  if (kind == 4)
     {
+      static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
+      static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
+
       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-	{
-	  *lenptr = sizeof (density_big_breakpoint);
-	  return density_big_breakpoint;
-	}
+	return big_breakpoint;
       else
-	{
-	  *lenptr = sizeof (density_little_breakpoint);
-	  return density_little_breakpoint;
-	}
+	return little_breakpoint;
     }
   else
     {
+      static unsigned char density_big_breakpoint[] = DENSITY_BIG_BREAKPOINT;
+      static unsigned char density_little_breakpoint[]
+	= DENSITY_LITTLE_BREAKPOINT;
+
       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-	{
-	  *lenptr = sizeof (big_breakpoint);
-	  return big_breakpoint;
-	}
+	return density_big_breakpoint;
       else
-	{
-	  *lenptr = sizeof (little_breakpoint);
-	  return little_breakpoint;
-	}
+	return density_little_breakpoint;
     }
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (xtensa)
+
 /* Call0 ABI support routines.  */
 
 /* Return true, if PC points to "ret" or "ret.n".  */ 
@@ -3238,7 +3237,7 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
   /* Set breakpoints.  */
-  set_gdbarch_breakpoint_from_pc (gdbarch, xtensa_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (xtensa);
 
   /* After breakpoint instruction or illegal instruction, pc still
      points at break instruction, so don't decrement.  */
-- 
1.9.1


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