diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index c848dc2..fe8d38d 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -715,9 +715,7 @@ static const gdb_byte arc_brk_s_le[] = { 0xff, 0x7f };
 static const gdb_byte arc_brk_be[] = { 0x25, 0x6f, 0x00, 0x3f };
 static const gdb_byte arc_brk_le[] = { 0x6f, 0x25, 0x3f, 0x00 };
 
-/* Implement the "breakpoint_from_pc" gdbarch method.
-
-   For ARC ELF, breakpoint uses the 16-bit BRK_S instruction, which is 0x7fff
+/* For ARC ELF, breakpoint uses the 16-bit BRK_S instruction, which is 0x7fff
    (little endian) or 0xff7f (big endian).  We used to insert BRK_S even
    instead of 32-bit instructions, which works mostly ok, unless breakpoint is
    inserted into delay slot instruction.  In this case if branch is taken
@@ -734,15 +732,12 @@ static const gdb_byte arc_brk_le[] = { 0x6f, 0x25, 0x3f, 0x00 };
    NB: Baremetal GDB uses BRK[_S], while user-space GDB uses TRAP_S.  BRK[_S]
    is much better because it doesn't commit unlike TRAP_S, so it can be set in
    delay slots; however it cannot be used in user-mode, hence usage of TRAP_S
-   in GDB for user-space.
+   in GDB for user-space.  */
 
-   PCPTR is a pointer to the PC where we want to place a breakpoint.  LENPTR
-   is a number of bytes used by the breakpoint.  Returns the byte sequence of
-   a breakpoint instruction.  */
+/* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
 
-static const gdb_byte *
-arc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-			int *lenptr)
+static int
+arc_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   size_t length_with_limm = gdb_insn_length (gdbarch, *pcptr);
 
@@ -751,21 +746,34 @@ arc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
      bytes for 32-bit instructions.  */
   if ((length_with_limm == 4 || length_with_limm == 8)
       && !arc_mach_is_arc600 (gdbarch))
+    return sizeof (arc_brk_le);
+  else
+    return sizeof (arc_brk_s_le);
+}
+
+/* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
+
+static const gdb_byte *
+arc_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  *size = kind;
+
+  if (kind == sizeof (arc_brk_le))
     {
-      *lenptr = sizeof (arc_brk_le);
       return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
 	      ? arc_brk_be
 	      : arc_brk_le);
     }
   else
     {
-      *lenptr = sizeof (arc_brk_s_le);
       return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
 	      ? arc_brk_s_be
 	      : arc_brk_s_le);
     }
 }
 
+GDBARCH_BREAKPOINT_FROM_PC (arc)
+
 /* Implement the "unwind_pc" gdbarch method.  */
 
 static CORE_ADDR
@@ -1229,7 +1237,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_skip_prologue (gdbarch, arc_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, arc_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (arc);
 
   /* On ARC 600 BRK_S instruction advances PC, unlike other ARC cores.  */
   if (!arc_mach_is_arc600 (gdbarch))
diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 5bf6da5..2ccf191 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 645825f..183c365 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -7843,16 +7843,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);
@@ -7866,38 +7858,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
@@ -9407,7 +9422,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 8e1d79e..2ca8940 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 627b9c0..aaf7872 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -7035,113 +7035,105 @@ 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)
+static int
+mips_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
 {
   CORE_ADDR pc = *pcptr;
 
-  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+  if (mips_pc_is_mips16 (gdbarch, pc))
     {
-      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
-	{
-	  static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
+      *pcptr = unmake_compact_addr (pc);
+      return MIPS_BP_KIND_MIPS16;
+    }
+  else if (mips_pc_is_micromips (gdbarch, pc))
+    {
+      ULONGEST insn;
+      int status;
 
-	  *lenptr = sizeof (big_breakpoint);
-	  return big_breakpoint;
-	}
+      *pcptr = unmake_compact_addr (pc);
+      insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
+      if (status || (mips_insn_size (ISA_MICROMIPS, insn) == 2))
+	return MIPS_BP_KIND_MICROMIPS16;
+      else
+	return MIPS_BP_KIND_MICROMIPS32;
     }
   else
+    return MIPS_BP_KIND_MIPS32;
+}
+
+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)
     {
-      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);
+    case MIPS_BP_KIND_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;
-	}
-      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 };
+      }
+    case MIPS_BP_KIND_MICROMIPS16:
+      {
+	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_MICROMIPS32:
+      {
+	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_MIPS32:
+      {
+	static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
+	static gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 };
 
-	  *lenptr = sizeof (little_breakpoint);
+	*size = 4;
+	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)
 {
-  CORE_ADDR pc = *pcptr;
-
-  if (mips_pc_is_mips16 (gdbarch, pc))
-    {
-      *pcptr = unmake_compact_addr (pc);
-      *kindptr = MIPS_BP_KIND_MIPS16;
-    }
-  else if (mips_pc_is_micromips (gdbarch, pc))
-    {
-      ULONGEST insn;
-      int status;
-
-      insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
-      if (status || (mips_insn_size (ISA_MICROMIPS, insn) == 2))
-	*kindptr = MIPS_BP_KIND_MICROMIPS16;
-      else
-	*kindptr = MIPS_BP_KIND_MICROMIPS32;
-
-      *pcptr = unmake_compact_addr (pc);
-    }
-  else
-    *kindptr = MIPS_BP_KIND_MIPS32;
+  *kindptr = mips_breakpoint_kind_from_pc (gdbarch, pcptr);
 }
 
 /* Return non-zero if the standard MIPS instruction INST has a branch
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 3ff325fe0..57fd331 100644
--- a/gdb/nios2-tdep.c
+++ b/gdb/nios2-tdep.c
@@ -1694,9 +1694,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)."
@@ -1704,54 +1725,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
@@ -2316,7 +2336,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 ca4d668..7cb7a9e 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -967,18 +967,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
@@ -6486,7 +6479,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 12aedbb..6100d92 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -418,11 +418,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)
@@ -431,21 +436,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
@@ -2274,7 +2280,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 f51186a..97e5a58 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -253,11 +253,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 */
@@ -267,44 +280,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]
@@ -2410,7 +2413,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 adb7f50..9957947 100644
--- a/gdb/tic6x-tdep.c
+++ b/gdb/tic6x-tdep.c
@@ -318,15 +318,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)
     {
@@ -339,6 +342,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
@@ -1295,7 +1302,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 aafb175..90da611 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -1959,6 +1959,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
@@ -1969,45 +1977,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".  */ 
@@ -3239,7 +3238,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.  */
