aboutsummaryrefslogtreecommitdiff
path: root/gdb/arc-tdep.c
diff options
context:
space:
mode:
authorYuriy Kolerov <kolerov93@gmail.com>2024-02-14 18:16:16 +0000
committerShahab Vahedi <shahab@synopsys.com>2024-02-21 14:15:09 +0100
commit33283d91d94e205ba34306cd1c253b9faceb4dd9 (patch)
treee1b95cde3748e56e0c51fa28e4f349efde2fd360 /gdb/arc-tdep.c
parentf96127310144d360eac93444c1b6efe80497d163 (diff)
downloadgdb-33283d91d94e205ba34306cd1c253b9faceb4dd9.zip
gdb-33283d91d94e205ba34306cd1c253b9faceb4dd9.tar.gz
gdb-33283d91d94e205ba34306cd1c253b9faceb4dd9.tar.bz2
arc: Determine a branch target of DBNZ correctly
DBNZ instruction was moved from BRANCH class to a separate one - DBNZ. Thus, it must be processed separately in arc_insn_get_branch_target to correctly determine an offset for a possible branch. The testsuite for DBNZ instruction verifies these cases: 1. Check that dbnz does not branch and falls through if its source register is 0 after decrementing. GDB must successfully break on the following instruction after stepping over. 2. Check that dbnz branches to the target correctly if its source register is not 0 after decrementing - GDB must successfully break on the target instruction if a forward branch is performed after stepping over. 3. The same as point 2 but for a backward branching case. Signed-off-by: Yuriy Kolerov <kolerov93@gmail.com>
Diffstat (limited to 'gdb/arc-tdep.c')
-rw-r--r--gdb/arc-tdep.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 12d8aee..7dd43cc 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -466,6 +466,16 @@ arc_insn_get_branch_target (const struct arc_instruction &insn)
instruction, hence last two bits should be truncated. */
return pcrel_addr + align_down (insn.address, 4);
}
+ /* DBNZ is the only branch instruction that keeps a branch address in
+ the second operand. It must be intercepted and treated differently. */
+ else if (insn.insn_class == DBNZ)
+ {
+ CORE_ADDR pcrel_addr = arc_insn_get_operand_value_signed (insn, 1);
+
+ /* Offset is relative to the 4-byte aligned address of the current
+ instruction, hence last two bits should be truncated. */
+ return pcrel_addr + align_down (insn.address, 4);
+ }
/* B, Bcc, BL, BLcc, LP, LPcc: PC = currentPC + operand. */
else if (insn.insn_class == BRANCH || insn.insn_class == LOOP)
{