From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) by sourceware.org (Postfix) with ESMTPS id CDCDB3858D39 for ; Wed, 21 Feb 2024 13:17:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CDCDB3858D39 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=vahedi.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=vahedi.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CDCDB3858D39 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1708521460; cv=none; b=XDwbE7uIrEsZwCDQWMV1puARg77KzLPA29oGXRbFIG62EC8m6dDUoaVllFXs83VbN3eAgqh7geR5USth5t/TXUcW6jYblv1E96y+MJbp0I6zzkBroTgnG9PCkMkgRNCK+GdNV7kColVgzO2gDfkz98oi1iyTxySMHR2nT7+21Tg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1708521460; c=relaxed/simple; bh=rvFalZYwWMJt1RQ+Z5JWXlmArSNPojUHFuHtzuAdHjU=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=EMSEbDKITBBaXPfINFCShd7eMdeKY96awEo/K5KyLJkbJZ+ItidAh1/LtAJ18pRdAHsrWMvvW46PfJ4x7blxd4lZaCE43H2XmRaJXoY4USoQ/UTxbod88Z21LY5Of2k/+7lVNRikvUaReXrv2NDunrC5YoT4LrZ43Tqx/U70fGU= ARC-Authentication-Results: i=1; server2.sourceware.org X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vahedi.org; s=key1; t=1708521455; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4nr7As+gqIWEKUahf/uKCWq2vQAJIe2Q//6pyLCOkk4=; b=jq1e3QqcjpUErCtr+29La2tip4zUKqkwXF5Lykm3tnY7bBmm4vcfbl7gdlukiUQReTksWX H7iWSZRps2p7yvM8PpNWXkJGYxIho4PREQfpgn3aJ9704oD6h4SiER0Byw9vmVPP1dhFT1 09PjgNwOkzmTq7oe4djy6X0WTI17T1NQ6ADA2niznl1E8Pr7Up+Y/AGg+NwMyHlm6XSx+K rbwAxymDiTU0dSmbhcqMglVgUS8XDLZYBKYhgvbIPNOkVPs6/MResEqfpbL0KkUVf9ez7b F++bsva3hru/BkS/Is/Q11G9Ed6qrjYwnEMqjLgy9MeNQ9IDsD7HuTR7jLZIBA== From: Shahab Vahedi To: gdb-patches@sourceware.org Cc: Yuriy Kolerov Subject: [PUSHED] arc: Determine a branch target of DBNZ correctly Date: Wed, 21 Feb 2024 14:17:21 +0100 Message-Id: <20240221131721.15430-1-list+gdb@vahedi.org> In-Reply-To: <20240214181616.36502-1-kolerov93@gmail.com> References: <20240214181616.36502-1-kolerov93@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Yuriy Kolerov 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/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 . + + .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 . + +# 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