Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Kirill Radkin <hokeygo@gmail.com>
To: gdb-patches@sourceware.org
Cc: Peter Bergner <bergner@oss.tenstorrent.com>,
	Sergey Matyukevich <geomatsi@gmail.com>,
	Jerry Zhang Jian <jerry.zhangjian@sifive.com>,
	Heinrich Schuchardt <heinrich.schuchardt@canonical.com>,
	Andrew Burgess <aburgess@redhat.com>,
	Palmer Dabbelt <palmer@dabbelt.com>
Subject: [PATCH v2 2/3] Reverse execution support for RISC-V Vector Extension
Date: Fri, 25 Sep 2026 20:29:46 +0300	[thread overview]
Message-ID: <20260925172947.403655-3-hokeygo@gmail.com> (raw)
In-Reply-To: <20260925172947.403655-1-hokeygo@gmail.com>

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<gdb_byte> 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<ULONGEST *> (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


  parent reply	other threads:[~2026-09-25 17:30 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-25 17:29 [PATCH v2 0/3] RISC-V Vector Extension support Kirill Radkin
2026-09-25 17:29 ` [PATCH v2 1/3] RISC-V Vector Extension Support Kirill Radkin
2026-09-25 17:29 ` Kirill Radkin [this message]
2026-09-25 17:29 ` [PATCH v2 3/3] RISC-V Vector Extension Support Testing Kirill Radkin

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=20260925172947.403655-3-hokeygo@gmail.com \
    --to=hokeygo@gmail.com \
    --cc=aburgess@redhat.com \
    --cc=bergner@oss.tenstorrent.com \
    --cc=gdb-patches@sourceware.org \
    --cc=geomatsi@gmail.com \
    --cc=heinrich.schuchardt@canonical.com \
    --cc=jerry.zhangjian@sifive.com \
    --cc=palmer@dabbelt.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