diff options
author | Yuriy Kolerov <kolerov93@gmail.com> | 2024-02-14 18:16:16 +0000 |
---|---|---|
committer | Shahab Vahedi <shahab@synopsys.com> | 2024-02-21 14:15:09 +0100 |
commit | 33283d91d94e205ba34306cd1c253b9faceb4dd9 (patch) | |
tree | e1b95cde3748e56e0c51fa28e4f349efde2fd360 /gdb/arc-tdep.c | |
parent | f96127310144d360eac93444c1b6efe80497d163 (diff) | |
download | gdb-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.c | 10 |
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) { |