From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 2ahUFsyvtmqTkQMAWB0awg (envelope-from ) for ; Fri, 25 Sep 2026 13:30:52 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=EDeBiVlF; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 4F6951E06B; Fri, 25 Sep 2026 13:30:52 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-4.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FORGED_GMAIL_RCVD,FREEMAIL_FROM, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 9AE561E01F for ; Fri, 25 Sep 2026 13:30:50 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 917074B920F2 for ; Fri, 25 Sep 2026 17:30:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 917074B920F2 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=EDeBiVlF Received: from mail-lf2-x11.google.com (mail-lf2-x11.google.com [IPv6:2a00:1450:4864:36::11]) by sourceware.org (Postfix) with ESMTPS id 236EE4B920CB for ; Fri, 25 Sep 2026 17:30:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 236EE4B920CB Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 236EE4B920CB Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:36::11 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1790357411; cv=none; b=BtcNY/fhlP+FLMug307lh5vEo96T4sPsmG7y0VT7UugNSIY2KfmwhxYNFHef9ipSfupYCui0xbe850gHPye4DIiZIYZD6MEO5zwK8qKCBmkYBTXGTHroqg8k0jN/C1IshDkKWyeVBuiSmG2LNrgUa3anhyWb7NTOuwKhhFFB1zY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1790357411; c=relaxed/simple; bh=Gwv54COhULYDhIX6R9NTIbghTkL6poPVY//kl5GZR7w=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=rOJd86/EEry/TG/+Iz2uIqKM3HJuoGTudGal1BH66cQXwu1YpXysvX/n9Kl5zIKnwLwvm3PedU4ozuBeFNLqhTmzL6dmmZm9kS3fIPYJjiOI1uZsmyy9ZZy22xZSzKQZBgctrQzmD5d7oPZkCPCoQoxdhwGJ7jJcXRtAJLQlFwQ= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=EDeBiVlF DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 236EE4B920CB Received: by mail-lf2-x11.google.com with SMTP id 2adb3069b0e04-5b5e4f16f15so1084662e87.3 for ; Fri, 25 Sep 2026 10:30:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790357410; x=1790962210; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=6Rkpmk5tNJAoLtI2MmG+LZcEh1/jvYbY6dOFR2780xY=; b=EDeBiVlFKKp24S+5e/MJSk1a9WFy4AfC+/HDBuclpscTo16qjUGfhPkgCjO9WK+l2L mCa5mb5CCWFZY1jFlTwuEY6S4mTddppyQaDpdhuK3/abK+octcBngwgxngyotUqgFKtD 5xf22unAiNcJoajzH7UBE9QKmFKsSkzRZMQ9CUZeWFiYnxpyZ/7fvvybnb7+mWlnyfBN zepEUAdqx7sTjMRPMOEGAQ7BeorZLed07kz5+d+Z7wfNyZDigosmoQxFC20g97iKeizo xNam9pqKt1S5ne0O4Z6/9qI7t6o55tKvnv0y7W8K9bTStmOyheF1V6+a2RwxhrOXRwlk HuHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790357410; x=1790962210; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=6Rkpmk5tNJAoLtI2MmG+LZcEh1/jvYbY6dOFR2780xY=; b=XdVrdUQLoJUH10mco5VkGCLa3k3mqtvjky5HoINWtYtA9kVmhtVpfP1rE75yr8NKPq l8gLlREMVPDTc7XdpwX8h/7n2rjdgkKdlQ3lRFDkhjAeNHYEeaEQBZve69kNE5gEZaVb F7aHWY2BsXc7klIzZ5fazqC1I5W3bd6w2Nd8zP32fxXUl9UMJxB3RBczS1Cm8W9IK8i/ LiV0JI1vbuzd+cmRyohWvcFfMLtsxvoCTucnmbZnCjCb0wzWjt6ZDjubOkD8yybSOiW5 KTJ8Eotfgv7m20vC59E7Tfx4yYfAZdfaOVCqkEQG3zShJI6MuFmfANYWCNq+UiYp4iIU wo/g== X-Gm-Message-State: AFuF++mdPHp5Vzal+Bh+2NLsCXbw5qSVesmhcoHIF3d+eYwgkyY21N/A +QgE3HKcuXCeFc9lTDz2Ofs42E3UQpAXfmaXxmQPdqAOlVe36GrmsVRJ3ExHfYXQcfjDmgx1 X-Gm-Gg: AYBFou3EVzHuAJ0m9gR0ascf+PQ9rOEHNbMUQEPYp2cQ8jg28r434emxg/dVQ18UD9i eSY8BurHPI3pEU217LrXoqQ8X9Y+ln0CrVtnxSnEs/mKw3abSJ7xLjAsBQwXL5uNbWq62eDJ3DK rbBGif+DIPWPIlfoEfH5MUrXcCXGp4KCjpg4Ndl12lIUhFq5O7KrdiV4FF85n+onyFWxW6EvG4b JLRORP4Jybvzr0Ncz/4lAY8GO9AkaVfAlDd0CXVjlpDYWv9Wv8fV8Hzuwp2cOsZ2mqvOGSq8Fya eqpqyZlvtVm2XCIZj7ltfw/2YJ/C0tiEosazZ3qMJUwPDEQlMg3dUhRrWw8S/jEMjWEXbI8oonY J/JwWNvtV6+ZPqSOQv/OR+ZKStuXA8v8rUcbgR10qPGIn4TbbJZj+l2R5+mPBYCwD11wyOoNd2x yKdx5QwxyDBH88u2BeU0DRgaPbpCj3o4JwNnJvKBhhSPR9ev5jB8Ndcots3hHL6IgUIsqiKYw35 73lI00gj4cN+iKL X-Received: by 2002:ac2:51d5:0:b0:5b8:ef23:414c with SMTP id 2adb3069b0e04-5b8ef234266mr33538e87.34.1790357409580; Fri, 25 Sep 2026 10:30:09 -0700 (PDT) Received: from ouran.high.school.host.club ([89.207.88.244]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5b8e6b02d57sm711564e87.57.2026.09.25.10.30.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Sep 2026 10:30:09 -0700 (PDT) From: Kirill Radkin To: gdb-patches@sourceware.org Cc: Peter Bergner , Sergey Matyukevich , Jerry Zhang Jian , Heinrich Schuchardt , Andrew Burgess , Palmer Dabbelt Subject: [PATCH v2 2/3] Reverse execution support for RISC-V Vector Extension Date: Fri, 25 Sep 2026 20:29:46 +0300 Message-ID: <20260925172947.403655-3-hokeygo@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260925172947.403655-1-hokeygo@gmail.com> References: <20260925172947.403655-1-hokeygo@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org This patch adds support for reverse execution feature for the RISC-V Vector Extension (RVV). Implementation was tested on massive auto-generated tests on Openocd + spike configuration. --- gdb/riscv-tdep.c | 493 ++++++++++++++++++++++++++++++++++++- include/opcode/riscv-opc.h | 79 ++++++ include/opcode/riscv.h | 10 + 3 files changed, 580 insertions(+), 2 deletions(-) diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 12bc51beb38..0cef77f8750 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -5709,6 +5709,18 @@ class riscv_recorded_insn final return (ival >> OP_SH_CSR) & OP_MASK_CSR; } + /* Helper for decode 32-bit vector instruction VD. */ + static regnum_type decode_vd (ULONGEST ival) noexcept + { + return ((ival >> OP_SH_VD) & OP_MASK_VD) + RISCV_V0_REGNUM; + } + + /* Helper for decode 32-bit instruction VS2. */ + static regnum_type decode_vs2 (ULONGEST ival) noexcept + { + return ((ival >> OP_SH_VS2) & OP_MASK_VS2) + RISCV_V0_REGNUM; + } + /* Reads register. Returns false if error happened. */ bool read_reg (regnum_type regnum, ULONGEST &addr) noexcept @@ -5720,6 +5732,16 @@ class riscv_recorded_insn final return false; } + bool read_vector_reg (regnum_type regnum, gdb_byte *val) noexcept + { + gdb_assert (RISCV_V0_REGNUM <= regnum && regnum <= RISCV_V31_REGNUM); + if (m_regcache->raw_read (regnum, val) == register_status::REG_VALID) + return true; + + warning (_ ("Can not read at vector reg %d"), regnum); + return false; + } + /* Save register. Returns false if error happened. */ bool save_reg (regnum_type regnum) noexcept @@ -5827,7 +5849,10 @@ class riscv_recorded_insn final || is_xperm4_insn (ival) || is_xperm8_insn (ival) || is_zext_h_insn (ival) || (m_xlen == 4 && is_zext_h_rv32_insn (ival)) - || (m_xlen == 4 && is_zip_insn (ival))); + || (m_xlen == 4 && is_zip_insn (ival)) + /* vector */ + || is_vmv_x_s_insn (ival) || is_vcpop_m_insn (ival) + || is_vfirst_m_insn (ival)); } /* Returns true if instruction successfully saved rd. */ @@ -5862,7 +5887,8 @@ class riscv_recorded_insn final || is_fmax_d_insn (ival) || is_fcvt_s_d_insn (ival) || is_fcvt_d_s_insn (ival) || is_fcvt_d_w_insn (ival) || is_fcvt_d_wu_insn (ival) || is_fcvt_d_l_insn (ival) - || is_fcvt_d_lu_insn (ival) || is_fmv_d_x_insn (ival)); + || is_fcvt_d_lu_insn (ival) || is_fmv_d_x_insn (ival) + || is_vfmv_f_s_insn (ival)); } /* Returns true if instruction successfully saved floating point rd. */ @@ -5948,6 +5974,454 @@ class riscv_recorded_insn final && save_reg (decode_rd (ival))); } + bool decode_width_vector (ULONGEST ival, ULONGEST &width) noexcept + { + ULONGEST val = (ival >> OP_SH_WIDTH) & OP_MASK_WIDTH; + + switch (val) + { + case 0x0: + width = 8; + break; + case 0x5: + width = 16; + break; + case 0x6: + width = 32; + break; + case 0x7: + width = 64; + break; + default: + warning (_ ("Unexpected vector width value: %lu"), val); + return false; + } + + return true; + } + + bool decode_nfields_vector (ULONGEST ival, ULONGEST &nfields) noexcept + { + ULONGEST val = (ival >> OP_SH_NF) & OP_MASK_NF; + + if (val >= 8) + { + warning (_ ("Unexpected nfields value: %lu"), val); + return false; + } + + nfields = val + 1; + return true; + } + + bool decode_element_width_vector (ULONGEST val, ULONGEST &elem_width) + { + ULONGEST sew = (val >> 3) & 0x7; + if (sew >= 4) + { + warning (_ ("Unexpected sew value: %lu"), sew); + return false; + } + + elem_width = (1 << (sew + 3)); + return true; + } + + /* Applies LMUL, encoded in a vtype value's VLMUL[2:0] field, to the + NUMERATOR/DENOMINATOR ratio, returning floor(NUMERATOR / DENOMINATOR + * LMUL). VLMUL encodes: 0..3 -> integer LMUL 1,2,4,8; 5..7 -> + fractional LMUL 1/8,1/4,1/2 (4 is reserved). Passing DENOMINATOR = 1 + just applies LMUL to a plain count. */ + static ULONGEST + scale_by_lmul (ULONGEST numerator, ULONGEST denominator, + ULONGEST vlmul) noexcept + { + if (vlmul > 4) + return numerator / (denominator * (1 << (8 - vlmul))); + return numerator * (1 << vlmul) / denominator; + } + + ULONGEST + decode_imm_vector (ULONGEST ival) noexcept + { + return (ival >> OP_SH_VIMM) & OP_MASK_VIMM; + } + + bool is_vector_unit_stride_instr (ULONGEST ival) noexcept + { + ULONGEST mop = (ival >> OP_SH_MOP) & OP_MASK_MOP; + bool res = (mop == 0x0); + if (record_debug) + debug_printf ("Process record: is_vector_unit_stride_instr: %d\n", res); + return res; + } + + bool is_vector_unit_stride_base_instr (ULONGEST ival) noexcept + { + ULONGEST mop = (ival >> OP_SH_MOP) & OP_MASK_MOP; + ULONGEST umop = (ival >> OP_SH_UMOP) & OP_MASK_UMOP; + bool res = (mop == 0x0) && (umop == 0x0); + if (record_debug) + debug_printf ("Process record: is_vector_unit_stride_base_instr: %d\n", + res); + return res; + } + + bool is_vector_unit_stride_whole_reg_instr (ULONGEST ival) + { + ULONGEST mop = (ival >> OP_SH_MOP) & OP_MASK_MOP; + ULONGEST umop = (ival >> OP_SH_UMOP) & OP_MASK_UMOP; + bool res = (mop == 0x0) && (umop == 0x8); + if (record_debug) + debug_printf ( + "Process record: is_vector_unit_stride_whole_reg_instr: %d\n", res); + return res; + } + + bool is_vector_strided_instr (ULONGEST ival) noexcept + { + ULONGEST mop = (ival >> OP_SH_MOP) & OP_MASK_MOP; + bool res = (mop == 0x2); + if (record_debug) + debug_printf ("Process record: is_vector_strided_instr: %d\n", res); + return res; + } + + bool is_vector_indexed_instr (ULONGEST ival) noexcept + { + ULONGEST mop = (ival >> OP_SH_MOP) & OP_MASK_MOP; + bool res = (mop == 0x1) || (mop == 0x3); + if (record_debug) + debug_printf ("Process record: is_vector_indexed_instr: %d\n", res); + return res; + } + + bool is_vector_load_insn (ULONGEST ival) + { + ULONGEST dummy; + return (((ival >> OP_SH_OP) & OP_MASK_OP) == MATCH_VECTOR_LOAD) + && (((ival >> OP_SH_MEW) & OP_MASK_MEW) == 0) + && decode_width_vector (ival, dummy); + } + + bool is_vector_store_insn (ULONGEST ival) + { + ULONGEST dummy; + return (((ival >> OP_SH_OP) & OP_MASK_OP) == MATCH_VECTOR_STORE) + && (((ival >> OP_SH_MEW) & OP_MASK_MEW) == 0) + && decode_width_vector (ival, dummy); + } + + bool is_vector_op_insn (ULONGEST ival) + { + return ((ival >> OP_SH_OP) & OP_MASK_OP) == MATCH_VECTOR_OP; + } + + bool is_vector_vmv_nr_v_insn (ULONGEST ival) + { + return is_vmv1r_v_insn (ival) || is_vmv2r_v_insn (ival) + || is_vmv4r_v_insn (ival) || is_vmv8r_v_insn (ival); + } + + bool is_vector_widening_insn (ULONGEST ival) + { + return is_vwaddu_vv_insn (ival) || is_vwaddu_vx_insn (ival) + || is_vwsubu_vv_insn (ival) || is_vwsubu_vx_insn (ival) + || is_vwadd_vv_insn (ival) || is_vwadd_vx_insn (ival) + || is_vwsub_vv_insn (ival) || is_vwsub_vx_insn (ival) + || is_vwaddu_wv_insn (ival) || is_vwaddu_wx_insn (ival) + || is_vwsubu_wv_insn (ival) || is_vwsubu_wx_insn (ival) + || is_vwadd_wv_insn (ival) || is_vwadd_wx_insn (ival) + || is_vwsub_wv_insn (ival) || is_vwsub_wx_insn (ival) + || is_vwmul_vv_insn (ival) || is_vwmul_vx_insn (ival) + || is_vwmulu_vv_insn (ival) || is_vwmulu_vx_insn (ival) + || is_vwmulsu_vv_insn (ival) || is_vwmulsu_vx_insn (ival) + || is_vwmaccu_vv_insn (ival) || is_vwmaccu_vx_insn (ival) + || is_vwmacc_vv_insn (ival) || is_vwmacc_vx_insn (ival) + || is_vwmaccsu_vv_insn (ival) || is_vwmaccsu_vx_insn (ival) + || is_vwmaccus_vx_insn (ival) || is_vwredsum_vs_insn (ival) + || is_vwredsumu_vs_insn (ival) || is_vfwadd_vv_insn (ival) + || is_vfwadd_vf_insn (ival) || is_vfwadd_wv_insn (ival) + || is_vfwadd_wf_insn (ival) || is_vfwsub_vv_insn (ival) + || is_vfwsub_vf_insn (ival) || is_vfwsub_wv_insn (ival) + || is_vfwsub_wf_insn (ival) || is_vfwmul_vv_insn (ival) + || is_vfwmul_vf_insn (ival) || is_vfwmacc_vv_insn (ival) + || is_vfwmacc_vf_insn (ival) || is_vfwnmacc_vv_insn (ival) + || is_vfwnmacc_vf_insn (ival) || is_vfwmsac_vv_insn (ival) + || is_vfwmsac_vf_insn (ival) || is_vfwnmsac_vv_insn (ival) + || is_vfwnmsac_vf_insn (ival) || is_vfwcvt_xu_f_v_insn (ival) + || is_vfwcvt_x_f_v_insn (ival) || is_vfwcvt_rtz_xu_f_v_insn (ival) + || is_vfwcvt_rtz_x_f_v_insn (ival) || is_vfwcvt_f_xu_v_insn (ival) + || is_vfwcvt_f_x_v_insn (ival) || is_vfwcvt_f_f_v_insn (ival) + || is_vfwredosum_vs_insn (ival) || is_vfwredusum_vs_insn (ival); + } + + /* Returns true if instruction needs only saving pc and vd. */ + bool need_save_vd (ULONGEST ival) noexcept + { + return is_vector_load_insn (ival) || is_vector_op_insn (ival); + } + + bool try_save_n_vector_regs_from_vreg (regnum_type vreg, int n) + { + for (int i = 0; i < n; i++) + if (!save_reg (vreg + i)) + return false; + + if (record_debug) + debug_printf ("Process record: try_save_n_vector_regs_from_vreg: saving " + "vregs from %d to %d\n", + vreg, vreg + n - 1); + + return true; + } + + bool try_save_vd_helper (ULONGEST ival, ULONGEST nfields) + { + ULONGEST vtype = 0; + if (!read_reg (RISCV_CSR_VTYPE_REGNUM, vtype)) + return false; + + ULONGEST vlmul = vtype & 0x7; + ULONGEST selected_width = 0; + if (!decode_element_width_vector (vtype, selected_width)) + return false; + + ULONGEST encoded_width = 0; + if (!decode_width_vector (ival, encoded_width)) + return false; + + ULONGEST emul = scale_by_lmul (encoded_width, selected_width, vlmul); + emul = (emul > 0) ? emul : 1; + + return try_save_n_vector_regs_from_vreg (decode_vd (ival), emul * nfields); + } + + bool try_save_vd_vector_unit_stride (ULONGEST ival, ULONGEST nfields) + { + if (is_vector_unit_stride_whole_reg_instr (ival)) + return try_save_n_vector_regs_from_vreg (decode_vd (ival), nfields); + + return try_save_vd_helper (ival, nfields); + } + + bool try_save_vd_vector_strided (ULONGEST ival, ULONGEST nfields) + { + return try_save_vd_helper (ival, nfields); + } + + bool try_save_vd_vector_indexed (ULONGEST ival, ULONGEST nfields) + { + ULONGEST vtype = 0; + if (!read_reg (RISCV_CSR_VTYPE_REGNUM, vtype)) + return false; + + ULONGEST vlmul = vtype & 0x7; + ULONGEST vd_count = scale_by_lmul (1, 1, vlmul); + vd_count = (vd_count > 0) ? vd_count : 1; + + return try_save_n_vector_regs_from_vreg (decode_vd (ival), + vd_count * nfields); + } + + bool try_save_vd_vmv_nr_v (ULONGEST ival) + { + ULONGEST vd_count = (decode_imm_vector (ival) & 0x7) + 1; + return try_save_n_vector_regs_from_vreg (decode_vd (ival), vd_count); + } + + bool try_save_vd_widening (ULONGEST ival) + { + ULONGEST vtype = 0; + if (!read_reg (RISCV_CSR_VTYPE_REGNUM, vtype)) + return false; + + ULONGEST vlmul = vtype & 0x7; + ULONGEST vd_count = scale_by_lmul (2, 1, vlmul); + vd_count = (vd_count > 0) ? vd_count : 1; + + return try_save_n_vector_regs_from_vreg (decode_vd (ival), vd_count); + } + + bool try_save_vd_vector_op (ULONGEST ival) + { + if (is_vector_vmv_nr_v_insn (ival)) + return try_save_vd_vmv_nr_v (ival); + + if (is_vector_widening_insn (ival)) + return try_save_vd_widening (ival); + + ULONGEST vtype = 0; + if (!read_reg (RISCV_CSR_VTYPE_REGNUM, vtype)) + return false; + + ULONGEST vlmul = vtype & 0x7; + ULONGEST vd_count = scale_by_lmul (1, 1, vlmul); + vd_count = (vd_count > 0) ? vd_count : 1; + + return try_save_n_vector_regs_from_vreg (decode_vd (ival), vd_count); + } + + /* Returns true if instruction successfully saved vd. */ + bool try_save_vd (ULONGEST ival) noexcept + { + ULONGEST nfields = 0; + if (!decode_nfields_vector (ival, nfields)) + return false; + + if (is_vector_op_insn (ival)) + return try_save_vd_vector_op (ival); + + if (is_vector_unit_stride_instr (ival)) + return try_save_vd_vector_unit_stride (ival, nfields); + + if (is_vector_strided_instr (ival)) + return try_save_vd_vector_strided (ival, nfields); + + if (is_vector_indexed_instr (ival)) + return try_save_vd_vector_indexed (ival, nfields); + + warning (_ ("Unexpected vector instr: %lu"), ival); + return false; + } + + bool try_save_mem_vector_unit_stride (ULONGEST ival, mem_addr addr, + ULONGEST nfields, ULONGEST length, + ULONGEST width) + { + ULONGEST vlenb_val = 0; + if (!read_reg (RISCV_CSR_VLENB_REGNUM, vlenb_val)) + return false; + + if (is_vector_unit_stride_whole_reg_instr (ival)) + return save_mem (addr, nfields * vlenb_val * 8); + + return save_mem (addr, nfields * length * width / 8); + } + + bool try_save_mem_vector_strided (ULONGEST ival, mem_addr addr, + ULONGEST nfields, ULONGEST length, + ULONGEST width) + { + ULONGEST stride = 0; + if (!read_reg (decode_rs2 (ival), stride)) + return false; + + for (ULONGEST i = 0; i < length; ++i) + { + if (!save_mem (addr, nfields * width / 8)) + return false; + addr += stride; + } + + return true; + } + + bool try_save_mem_vector_indexed (ULONGEST ival, mem_addr addr, + ULONGEST nfields, ULONGEST length, + ULONGEST width) + { + ULONGEST vtype_val = 0; + if (!read_reg (RISCV_CSR_VTYPE_REGNUM, vtype_val)) + return false; + + ULONGEST vector_elem_size = 0; + if (!decode_element_width_vector (vtype_val, vector_elem_size)) + return false; + + ULONGEST segment_len = nfields * vector_elem_size / 8; + + regnum_type vreg = decode_vs2 (ival); + + ULONGEST vtype = 0; + if (!read_reg (RISCV_CSR_VTYPE_REGNUM, vtype)) + return false; + + ULONGEST vlmul = vtype & 0x7; + ULONGEST selected_width = 0; + if (!decode_element_width_vector (vtype, selected_width)) + return false; + + ULONGEST encoded_width = 0; + if (!decode_width_vector (ival, encoded_width)) + return false; + + ULONGEST index_emul = scale_by_lmul (encoded_width, selected_width, vlmul); + index_emul = (index_emul > 0) ? index_emul : 1; + + int vreg_size = register_size (m_regcache->arch (), RISCV_V0_REGNUM); + std::vector vreg_buff (vreg_size * index_emul); + gdb_byte *raw_p = vreg_buff.data (); + + for (int i = 0; i < index_emul; ++i) + if (!read_vector_reg (vreg + i, raw_p + i * vreg_size)) + return false; + + gdb_byte *cur_offset_p = raw_p; + /* For indexed instructions, size of index depends on `width` value, so we + need this mask here to crop correctly here. For width == 64, byte-shift + approach is not working (because ULONGEST is 64-bit width). */ + ULONGEST mask = (width == 64) ? (~ULONGEST { 0 }) + : ((ULONGEST { 1 } << width) - 1); + for (ULONGEST i = 0; i < length; ++i) + { + ULONGEST cur_offset = (*reinterpret_cast (cur_offset_p)) + & mask; + + if (!save_mem (addr + cur_offset, segment_len)) + return false; + + cur_offset_p += width / 8; + } + return true; + } + + bool try_save_mem_vector (ULONGEST ival) noexcept + { + mem_addr addr = 0; + if (!read_reg (decode_rs1 (ival), addr)) + return false; + + ULONGEST nfields = 0; + if (!decode_nfields_vector (ival, nfields)) + return false; + + ULONGEST length = 0; + if (!read_reg (RISCV_CSR_VL_REGNUM, length)) + return false; + + ULONGEST width = 0; + if (!decode_width_vector (ival, width)) + return false; + + if (is_vector_unit_stride_instr (ival)) + return try_save_mem_vector_unit_stride (ival, addr, nfields, length, + width); + if (is_vector_strided_instr (ival)) + return try_save_mem_vector_strided (ival, addr, nfields, length, width); + + if (is_vector_indexed_instr (ival)) + return try_save_mem_vector_indexed (ival, addr, nfields, length, width); + + warning (_ ("Unexpected vector instr: %lu"), ival); + return false; + } + + bool try_save_all_vector_registers () noexcept + { + if (m_gdbarch->isa_features.vlenb) + { + return try_save_n_vector_regs_from_vreg (RISCV_V0_REGNUM, 32) + && save_reg (RISCV_CSR_VSTART_REGNUM) + && save_reg (RISCV_CSR_VCSR_REGNUM) + && save_reg (RISCV_CSR_VL_REGNUM) + && save_reg (RISCV_CSR_VTYPE_REGNUM) + && save_reg (RISCV_CSR_VLENB_REGNUM); + } + + return true; + } + /* Returns true if instruction is successfully recorded. The length of the instruction must be equal to 4 bytes. Helper function for record_insn_len4. */ @@ -5969,6 +6443,11 @@ class riscv_recorded_insn final return (save_reg (RISCV_CSR_MSTATUS_REGNUM) && save_reg (RISCV_CSR_MEPC_REGNUM)); + if (is_vsetvli_insn (ival) || is_vsetvl_insn (ival) + || is_vsetivli_insn (ival)) + return (try_save_rd (ival) && save_reg (RISCV_CSR_VTYPE_REGNUM) + && save_reg (RISCV_CSR_VL_REGNUM)); + if (need_save_only_pc (ival)) return true; @@ -5989,6 +6468,12 @@ class riscv_recorded_insn final if (len > 0) return try_save_rd_mem (ival, len); + if (need_save_vd (ival)) + return try_save_vd (ival); + + if (is_vector_store_insn (ival)) + return try_save_mem_vector (ival); + warning (_("Currently this instruction with len 4(%s) is unsupported"), hex_string (ival)); return false; @@ -6028,6 +6513,10 @@ class riscv_recorded_insn final mem_addr addr = 0; ULONGEST offset = 0; + if (record_debug) + debug_printf ("Process record: record_insn_len2: record insn 0x%lx\n", + ival); + /* The order here is very important, because opcodes of some instructions may be the same. */ diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h index 6b5004772a1..1e53e2bf61c 100644 --- a/include/opcode/riscv-opc.h +++ b/include/opcode/riscv-opc.h @@ -2159,6 +2159,11 @@ #define MASK_VDOTUVV 0xfc00707f #define MATCH_VFDOTVV 0xe4001057 #define MASK_VFDOTVV 0xfc00707f +/* RISC-V Vector instruction formats. */ +#define MATCH_VECTOR_LOAD 0x7 +#define MATCH_VECTOR_STORE 0x27 +#define MATCH_VECTOR_OP 0x57 +#define MATCH_VECTOR_OPIVI 0x3 /* These are only used by gdb for now. */ #define MATCH_BCLRI_RV32 0x48001013 #define MASK_BCLRI_RV32 0xfe00707f @@ -4955,6 +4960,80 @@ DECLARE_INSN(hsv_b, MATCH_HSV_B, MASK_HSV_B) DECLARE_INSN(hsv_h, MATCH_HSV_H, MASK_HSV_H) DECLARE_INSN(hsv_w, MATCH_HSV_W, MASK_HSV_W) DECLARE_INSN(hsv_d, MATCH_HSV_D, MASK_HSV_D) +/* RVV instructions. */ +DECLARE_INSN (vsetvl, MATCH_VSETVL, MASK_VSETVL) +DECLARE_INSN (vsetvli, MATCH_VSETVLI, MASK_VSETVLI) +DECLARE_INSN (vsetivli, MATCH_VSETIVLI, MASK_VSETIVLI) +DECLARE_INSN (vmv1r_v, MATCH_VMV1RV, MASK_VMV1RV) +DECLARE_INSN (vmv2r_v, MATCH_VMV2RV, MASK_VMV2RV) +DECLARE_INSN (vmv4r_v, MATCH_VMV4RV, MASK_VMV4RV) +DECLARE_INSN (vmv8r_v, MATCH_VMV8RV, MASK_VMV8RV) +DECLARE_INSN (vs1r_v, MATCH_VS1RV, MASK_VS1RV) +DECLARE_INSN (vs2r_v, MATCH_VS2RV, MASK_VS2RV) +DECLARE_INSN (vs4r_v, MATCH_VS4RV, MASK_VS4RV) +DECLARE_INSN (vs8r_v, MATCH_VS8RV, MASK_VS8RV) +DECLARE_INSN (vmv_x_s, MATCH_VMVXS, MASK_VMVXS) +DECLARE_INSN (vcpop_m, MATCH_VCPOPM, MASK_VCPOPM) +DECLARE_INSN (vfirst_m, MATCH_VFIRSTM, MASK_VFIRSTM) +DECLARE_INSN (vfmv_f_s, MATCH_VFMVFS, MASK_VFMVFS) +DECLARE_INSN (vwaddu_vv, MATCH_VWADDUVV, MASK_VWADDUVV) +DECLARE_INSN (vwaddu_vx, MATCH_VWADDUVX, MASK_VWADDUVX) +DECLARE_INSN (vwsubu_vv, MATCH_VWSUBUVV, MASK_VWSUBUVV) +DECLARE_INSN (vwsubu_vx, MATCH_VWSUBUVX, MASK_VWSUBUVX) +DECLARE_INSN (vwadd_vv, MATCH_VWADDVV, MASK_VWADDVV) +DECLARE_INSN (vwadd_vx, MATCH_VWADDVX, MASK_VWADDVX) +DECLARE_INSN (vwsub_vv, MATCH_VWSUBVV, MASK_VWSUBVV) +DECLARE_INSN (vwsub_vx, MATCH_VWSUBVX, MASK_VWSUBVX) +DECLARE_INSN (vwaddu_wv, MATCH_VWADDUWV, MASK_VWADDUWV) +DECLARE_INSN (vwaddu_wx, MATCH_VWADDUWX, MASK_VWADDUWX) +DECLARE_INSN (vwsubu_wv, MATCH_VWSUBUWV, MASK_VWSUBUWV) +DECLARE_INSN (vwsubu_wx, MATCH_VWSUBUWX, MASK_VWSUBUWX) +DECLARE_INSN (vwadd_wv, MATCH_VWADDWV, MASK_VWADDWV) +DECLARE_INSN (vwadd_wx, MATCH_VWADDWX, MASK_VWADDWX) +DECLARE_INSN (vwsub_wv, MATCH_VWSUBWV, MASK_VWSUBWV) +DECLARE_INSN (vwsub_wx, MATCH_VWSUBWX, MASK_VWSUBWX) +DECLARE_INSN (vwmul_vv, MATCH_VWMULVV, MASK_VWMULVV) +DECLARE_INSN (vwmul_vx, MATCH_VWMULVX, MASK_VWMULVX) +DECLARE_INSN (vwmulu_vv, MATCH_VWMULUVV, MASK_VWMULUVV) +DECLARE_INSN (vwmulu_vx, MATCH_VWMULUVX, MASK_VWMULUVX) +DECLARE_INSN (vwmulsu_vv, MATCH_VWMULSUVV, MASK_VWMULSUVV) +DECLARE_INSN (vwmulsu_vx, MATCH_VWMULSUVX, MASK_VWMULSUVX) +DECLARE_INSN (vwmaccu_vv, MATCH_VWMACCUVV, MASK_VWMACCUVV) +DECLARE_INSN (vwmaccu_vx, MATCH_VWMACCUVX, MASK_VWMACCUVX) +DECLARE_INSN (vwmacc_vv, MATCH_VWMACCVV, MASK_VWMACCVV) +DECLARE_INSN (vwmacc_vx, MATCH_VWMACCVX, MASK_VWMACCVX) +DECLARE_INSN (vwmaccsu_vv, MATCH_VWMACCSUVV, MASK_VWMACCSUVV) +DECLARE_INSN (vwmaccsu_vx, MATCH_VWMACCSUVX, MASK_VWMACCSUVX) +DECLARE_INSN (vwmaccus_vx, MATCH_VWMACCUSVX, MASK_VWMACCUSVX) +DECLARE_INSN (vwredsum_vs, MATCH_VWREDSUMVS, MASK_VWREDSUMVS) +DECLARE_INSN (vwredsumu_vs, MATCH_VWREDSUMUVS, MASK_VWREDSUMUVS) +DECLARE_INSN (vfwadd_vv, MATCH_VFWADDVV, MASK_VFWADDVV) +DECLARE_INSN (vfwadd_vf, MATCH_VFWADDVF, MASK_VFWADDVF) +DECLARE_INSN (vfwadd_wv, MATCH_VFWADDWV, MASK_VFWADDWV) +DECLARE_INSN (vfwadd_wf, MATCH_VFWADDWF, MASK_VFWADDWF) +DECLARE_INSN (vfwsub_vv, MATCH_VFWSUBVV, MASK_VFWSUBVV) +DECLARE_INSN (vfwsub_vf, MATCH_VFWSUBVF, MASK_VFWSUBVF) +DECLARE_INSN (vfwsub_wv, MATCH_VFWSUBWV, MASK_VFWSUBWV) +DECLARE_INSN (vfwsub_wf, MATCH_VFWSUBWF, MASK_VFWSUBWF) +DECLARE_INSN (vfwmul_vv, MATCH_VFWMULVV, MASK_VFWMULVV) +DECLARE_INSN (vfwmul_vf, MATCH_VFWMULVF, MASK_VFWMULVF) +DECLARE_INSN (vfwmacc_vv, MATCH_VFWMACCVV, MASK_VFWMACCVV) +DECLARE_INSN (vfwmacc_vf, MATCH_VFWMACCVF, MASK_VFWMACCVF) +DECLARE_INSN (vfwnmacc_vv, MATCH_VFWNMACCVV, MASK_VFWNMACCVV) +DECLARE_INSN (vfwnmacc_vf, MATCH_VFWNMACCVF, MASK_VFWNMACCVF) +DECLARE_INSN (vfwmsac_vv, MATCH_VFWMSACVV, MASK_VFWMSACVV) +DECLARE_INSN (vfwmsac_vf, MATCH_VFWMSACVF, MASK_VFWMSACVF) +DECLARE_INSN (vfwnmsac_vv, MATCH_VFWNMSACVV, MASK_VFWNMSACVV) +DECLARE_INSN (vfwnmsac_vf, MATCH_VFWNMSACVF, MASK_VFWNMSACVF) +DECLARE_INSN (vfwcvt_xu_f_v, MATCH_VFWCVTXUFV, MASK_VFWCVTXUFV) +DECLARE_INSN (vfwcvt_x_f_v, MATCH_VFWCVTXFV, MASK_VFWCVTXFV) +DECLARE_INSN (vfwcvt_rtz_xu_f_v, MATCH_VFWCVTRTZXUFV, MASK_VFWCVTRTZXUFV) +DECLARE_INSN (vfwcvt_rtz_x_f_v, MATCH_VFWCVTRTZXFV, MASK_VFWCVTRTZXFV) +DECLARE_INSN (vfwcvt_f_xu_v, MATCH_VFWCVTFXUV, MASK_VFWCVTFXUV) +DECLARE_INSN (vfwcvt_f_x_v, MATCH_VFWCVTFXV, MASK_VFWCVTFXV) +DECLARE_INSN (vfwcvt_f_f_v, MATCH_VFWCVTFFV, MASK_VFWCVTFFV) +DECLARE_INSN (vfwredosum_vs, MATCH_VFWREDOSUMVS, MASK_VFWREDOSUMVS) +DECLARE_INSN (vfwredusum_vs, MATCH_VFWREDUSUMVS, MASK_VFWREDUSUMVS) /* Zicbop instructions. */ DECLARE_INSN(prefetch_r, MATCH_PREFETCH_R, MASK_PREFETCH_R) DECLARE_INSN(prefetch_w, MATCH_PREFETCH_W, MASK_PREFETCH_W) diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 95b1f44567a..881597d342a 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -368,6 +368,16 @@ static inline unsigned int riscv_insn_length (insn_t insn) #define OP_MASK_VMASK 0x1 #define OP_SH_VMASK 25 #define OP_MASK_VFUNCT6 0x3f +#define OP_SH_MOP 26 +#define OP_MASK_MOP 0x3 +#define OP_SH_WIDTH 12 +#define OP_MASK_WIDTH 0x7 +#define OP_SH_MEW 28 +#define OP_MASK_MEW 0x1 +#define OP_SH_NF 29 +#define OP_MASK_NF 0x7 +#define OP_SH_UMOP 20 +#define OP_MASK_UMOP 0x1f #define OP_SH_VFUNCT6 26 #define OP_MASK_VLMUL 0x7 #define OP_SH_VLMUL 0 -- 2.43.0