]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
MicroBlaze: Add microblaze_get_next_pcs
authorGopi Kumar Bulusu <gopi@sankhya.com>
Mon, 8 Sep 2025 06:56:06 +0000 (12:26 +0530)
committerGopi Kumar Bulusu <gopi@sankhya.com>
Mon, 8 Sep 2025 06:56:06 +0000 (12:26 +0530)
This patch enables software single stepping for gdbserver target
Includes fix for Bug 33381 using core_addr_to_string_nz

* gdb/microblaze-tdep.c: Add microblaze_get_next_pcs

Signed-off-by: David Holsgrove <david.holsgrove@petalogix.com>
Signed-off-by: Nathan Rossi <nathan.rossi@petalogix.com>
Signed-off-by: Mahesh Bodapati <mbodapat@xilinx.com>
Signed-off-by: Gopi Kumar Bulusu <gopi@sankhya.com>
Approved-By: Simon Marchi <simon.marchi@efficios.com>
gdb/microblaze-tdep.c

index 7b58220871c3c709d11262b9dc442f39e7d21de9..404e4cde2ad99b29349db6002135511b5a00e56d 100644 (file)
@@ -590,6 +590,98 @@ microblaze_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
   return (type->length () == 16);
 }
 
+/* Return next pc values : next in sequence and/or branch/return target.  */
+
+static std::vector<CORE_ADDR>
+microblaze_get_next_pcs (regcache *regcache)
+{
+  CORE_ADDR pc = regcache_read_pc (regcache);
+  unsigned long insn = microblaze_fetch_instruction (pc);
+
+  enum microblaze_instr_type insn_type;
+  short delay_slots;
+  bool isunsignednum;
+
+  /* If the current instruction is an imm, look at the inst after.  */
+
+  get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots);
+
+  int imm;
+  bool immfound = false;
+
+  if (insn_type == immediate_inst)
+    {
+      int rd, ra, rb;
+      immfound = true;
+      microblaze_decode_insn (insn, &rd, &ra, &rb, &imm);
+      pc += INST_WORD_SIZE;
+      insn = microblaze_fetch_instruction (pc);
+      get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots);
+    }
+
+  std::optional<CORE_ADDR> next_pc, branch_or_return_pc;
+
+  /* Compute next instruction address - skip delay slots if any.  */
+
+  if (insn_type != return_inst)
+    next_pc = pc + INST_WORD_SIZE + (delay_slots * INST_WORD_SIZE);
+
+  microblaze_debug ("single-step insn_type=0x%x pc=%s insn=0x%lx",
+                   insn_type, core_addr_to_string_nz (pc), insn);
+
+  /* Compute target instruction address for branch or return instruction.  */
+  if (insn_type == branch_inst || insn_type == return_inst)
+    {
+      int limm;
+      int lrd, lra, lrb;
+      bool targetvalid;
+      bool unconditionalbranch;
+
+      microblaze_decode_insn (insn, &lrd, &lra, &lrb, &limm);
+
+      ULONGEST ra = regcache_raw_get_unsigned (regcache, lra);
+      ULONGEST rb = regcache_raw_get_unsigned (regcache, lrb);
+
+      branch_or_return_pc
+       = microblaze_get_target_address (insn, immfound,
+                                        imm, pc, ra, rb, &targetvalid,
+                                        &unconditionalbranch);
+
+      microblaze_debug ("single-step uncondbr=%d targetvalid=%d target=%s",
+                       unconditionalbranch, targetvalid,
+                       core_addr_to_string_nz (*branch_or_return_pc));
+
+      /* Can't reach next address.  */
+      if (unconditionalbranch)
+       next_pc.reset ();
+
+      /* Can't reach a distinct (not here) target address.  */
+      if (!targetvalid
+         || branch_or_return_pc == pc
+         || (next_pc.has_value () && (branch_or_return_pc == next_pc)))
+       branch_or_return_pc.reset ();
+    } /* if (branch or return instruction).  */
+
+  /* Create next_pcs vector to return.  */
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  if (next_pc.has_value ())
+    {
+      next_pcs.push_back (*next_pc);
+      microblaze_debug ("push_back next_pc(%s)",
+                       core_addr_to_string_nz (*next_pc));
+    }
+
+  if (branch_or_return_pc.has_value ())
+    {
+      next_pcs.push_back (*branch_or_return_pc);
+      microblaze_debug ("push_back branch_or_return_pc(%s)",
+                       core_addr_to_string_nz (*branch_or_return_pc));
+    }
+
+  return next_pcs;
+}
 \f
 static int dwarf2_to_reg_map[78] =
 { 0  /* r0  */,   1  /* r1  */,   2  /* r2  */,   3  /* r3  */,  /*  0- 3 */
@@ -715,6 +807,8 @@ microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_sw_breakpoint_from_kind (gdbarch,
                                       microblaze_breakpoint::bp_from_kind);
 
+  set_gdbarch_get_next_pcs (gdbarch, microblaze_get_next_pcs);
+
   set_gdbarch_frame_args_skip (gdbarch, 8);
 
   set_gdbarch_unwind_pc (gdbarch, microblaze_unwind_pc);