From: Shahab Vahedi <list+gdb@vahedi.org>
To: gdb-patches@sourceware.org
Cc: Yuriy Kolerov <kolerov93@gmail.com>
Subject: [PUSHED] arc: Determine a branch target of DBNZ correctly
Date: Wed, 21 Feb 2024 14:17:21 +0100 [thread overview]
Message-ID: <20240221131721.15430-1-list+gdb@vahedi.org> (raw)
In-Reply-To: <20240214181616.36502-1-kolerov93@gmail.com>
From: Yuriy Kolerov <kolerov93@gmail.com>
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>
---
gdb/arc-tdep.c | 10 +++
gdb/testsuite/gdb.arch/arc-dbnz.S | 47 ++++++++++++++
gdb/testsuite/gdb.arch/arc-dbnz.exp | 97 +++++++++++++++++++++++++++++
3 files changed, 154 insertions(+)
create mode 100644 gdb/testsuite/gdb.arch/arc-dbnz.S
create mode 100644 gdb/testsuite/gdb.arch/arc-dbnz.exp
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 12d8aee949f..7dd43cc239f 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)
{
diff --git a/gdb/testsuite/gdb.arch/arc-dbnz.S b/gdb/testsuite/gdb.arch/arc-dbnz.S
new file mode 100644
index 00000000000..45e1dfe8305
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/arc-dbnz.S
@@ -0,0 +1,47 @@
+; This testcase is part of GDB, the GNU debugger.
+
+; Copyright 2024 Free Software Foundation, Inc.
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 3 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ .section .text
+ .align 4
+ .global main
+ .type main, @function
+
+main:
+ mov r0,1
+dbnz1:
+ ; r0 == 0 after decrementing. dbnz doesn't do branch.
+ dbnz r0,@end
+
+ mov r0,5
+dbnz2:
+ ; r0 == 3 after decrementing and delay slot. dbnz does branch.
+ dbnz.d r0,@dbnz3
+ sub r0,r0,1
+
+dbnz4:
+ ; r0 == 1 after decrementing. dbnz does branch.
+ dbnz r0,@end
+
+dbnz3:
+ ; r0 == 2 after decrementing. dbnz does branch.
+ dbnz r0,@dbnz4
+
+end:
+ mov r0,0
+ j [blink]
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/arc-dbnz.exp b/gdb/testsuite/gdb.arch/arc-dbnz.exp
new file mode 100644
index 00000000000..f1fce0e5a7f
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/arc-dbnz.exp
@@ -0,0 +1,97 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test dbnz instruction. It decrements its source register operand, and if
+# the result is non-zero it branches to the location defined by a signed
+# half-word displacement operand.
+#
+# It's necessary to verify 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.
+
+require {istarget "arc*-*-*"}
+
+standard_testfile .S
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
+ return -1
+}
+
+if ![runto_main] {
+ return 0
+}
+
+gdb_test "break dbnz1" \
+ "Breakpoint $decimal at .*" \
+ "set breakpoint on the 1st dbnz"
+
+gdb_test "break dbnz2" \
+ "Breakpoint $decimal at .*" \
+ "set breakpoint on the 2nd dbnz"
+
+gdb_test "break dbnz3" \
+ "Breakpoint $decimal at .*" \
+ "set breakpoint on the 3rd dbnz"
+
+gdb_test "break dbnz4" \
+ "Breakpoint $decimal at .*" \
+ "set breakpoint on the 4th dbnz"
+
+gdb_test "break end" \
+ "Breakpoint $decimal at .*" \
+ "set breakpoint at the end"
+
+gdb_test "continue" \
+ "Breakpoint $decimal, dbnz1.*dbnz r0,@end" \
+ "continue to the 1st dbnz"
+
+gdb_test "x /i \$pc" \
+ "$hex <.*>:\[ \t\]+dbnz\[ \t\]+r0,24.*" \
+ "stayng on the 1st dbnz instruction"
+
+gdb_test "stepi" \
+ "mov r0,5" \
+ "step over the 1st dbnz, branch is not taken"
+
+gdb_test "stepi" \
+ "Breakpoint $decimal, dbnz2.*dbnz\\.d r0,@dbnz3" \
+ "step over r0 initialization, staying on the 2nd dbnz"
+
+# Linux steps over delay slot after "stepi", but stubs with hardware stepping
+# like nSIM's stub may step right on delay slot. Thus use "continue" instead of
+# "stepi" to make this test work for all platforms.
+gdb_test "continue" \
+ "Breakpoint $decimal, dbnz3.*dbnz r0,@dbnz4" \
+ "step over the 2nd dbnz, branch is taken, staying on the 3rd dbnz"
+
+gdb_test "stepi" \
+ "Breakpoint $decimal, dbnz4.*dbnz r0,@end" \
+ "step over the 3rd dbnz, branch is taken, staying on the 4th dbnz"
+
+gdb_test "stepi" \
+ "Breakpoint $decimal, end.*mov r0,0" \
+ "step over the 4th dbnz, branch is taken, staying on the epilogue"
+
+gdb_test "info register r0" \
+ "r0\[ \t\]+0x1\[ \t\]+1" \
+ "r0 contains 1 after all dbnz instructions"
--
2.35.8
prev parent reply other threads:[~2024-02-21 13:17 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-14 18:16 [PATCH] " Yuriy Kolerov
2024-02-21 13:12 ` Shahab Vahedi
2024-02-21 13:17 ` Shahab Vahedi [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240221131721.15430-1-list+gdb@vahedi.org \
--to=list+gdb@vahedi.org \
--cc=gdb-patches@sourceware.org \
--cc=kolerov93@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).