From 33283d91d94e205ba34306cd1c253b9faceb4dd9 Mon Sep 17 00:00:00 2001 From: Yuriy Kolerov Date: Wed, 14 Feb 2024 18:16:16 +0000 Subject: 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 --- gdb/testsuite/gdb.arch/arc-dbnz.S | 47 ++++++++++++++++++ gdb/testsuite/gdb.arch/arc-dbnz.exp | 97 +++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 gdb/testsuite/gdb.arch/arc-dbnz.S create mode 100644 gdb/testsuite/gdb.arch/arc-dbnz.exp (limited to 'gdb/testsuite/gdb.arch') diff --git a/gdb/testsuite/gdb.arch/arc-dbnz.S b/gdb/testsuite/gdb.arch/arc-dbnz.S new file mode 100644 index 0000000..45e1dfe --- /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 . + + .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 0000000..f1fce0e --- /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 . + +# 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" -- cgit v1.1