aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorGopi Kumar Bulusu <gopi@sankhya.com>2025-09-08 12:26:06 +0530
committerGopi Kumar Bulusu <gopi@sankhya.com>2025-09-08 12:26:06 +0530
commit96b9a160734f34d6644cae7c2dec02a98e07f66e (patch)
tree3ffdbc0228aae166908d16c506bf4814c4ed059c /gdb
parent79b2b564fecc5c00347892ac4b9ac4ec3c729a3b (diff)
downloadbinutils-96b9a160734f34d6644cae7c2dec02a98e07f66e.zip
binutils-96b9a160734f34d6644cae7c2dec02a98e07f66e.tar.gz
binutils-96b9a160734f34d6644cae7c2dec02a98e07f66e.tar.bz2
MicroBlaze: Add microblaze_get_next_pcs
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>
Diffstat (limited to 'gdb')
-rw-r--r--gdb/microblaze-tdep.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c
index 7b58220..404e4cd 100644
--- a/gdb/microblaze-tdep.c
+++ b/gdb/microblaze-tdep.c
@@ -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;
+}
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);