diff options
author | Gopi Kumar Bulusu <gopi@sankhya.com> | 2025-09-08 12:26:06 +0530 |
---|---|---|
committer | Gopi Kumar Bulusu <gopi@sankhya.com> | 2025-09-08 12:26:06 +0530 |
commit | 96b9a160734f34d6644cae7c2dec02a98e07f66e (patch) | |
tree | 3ffdbc0228aae166908d16c506bf4814c4ed059c /gdb | |
parent | 79b2b564fecc5c00347892ac4b9ac4ec3c729a3b (diff) | |
download | binutils-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.c | 94 |
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); |