Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Kirill Radkin <kirill.radkin@syntacore.com>
To: <gdb-patches@sourceware.org>
Cc: Kirill Radkin <kirill.radkin@syntacore.com>
Subject: [PATCH 2/2] RISC-V Vector Extension Support Testing
Date: Fri, 7 Nov 2025 19:55:34 +0300	[thread overview]
Message-ID: <20251107165534.1688124-2-kirill.radkin@syntacore.com> (raw)
In-Reply-To: <20251107165534.1688124-1-kirill.radkin@syntacore.com>

This patch add extensive testing for RISC-V Vector Extension Support.
---
 ...iscv-vector-abi-full-generate-template.txt | 153 ++++++++
 .../riscv-vector-abi-full-generate.py         | 360 ++++++++++++++++++
 .../gdb.arch/riscv-vector-abi-full.c          |  23 ++
 .../gdb.arch/riscv-vector-abi-full.exp        |  65 ++++
 gdb/testsuite/gdb.arch/riscv-vector-abi.c     | 157 ++++++++
 gdb/testsuite/gdb.arch/riscv-vector-abi.exp   | 230 +++++++++++
 .../gdb.arch/riscv-vu-availability.c          |  67 ++++
 .../gdb.arch/riscv-vu-availability.exp        |  72 ++++
 .../gdb.arch/riscv-vu-consitency-checks.c     |  79 ++++
 .../gdb.arch/riscv-vu-consitency-checks.exp   | 152 ++++++++
 gdb/testsuite/gdb.arch/riscv-vu-ctx-print.c   | 106 ++++++
 gdb/testsuite/gdb.arch/riscv-vu-ctx-print.exp | 107 ++++++
 gdb/testsuite/gdb.arch/riscv-vu-printout.c    |  69 ++++
 gdb/testsuite/gdb.arch/riscv-vu-printout.exp  |  92 +++++
 .../gdb.arch/riscv-vu-rvv-unsupported.c       |  23 ++
 .../gdb.arch/riscv-vu-rvv-unsupported.exp     |  46 +++
 gdb/testsuite/gdb.arch/riscv-vu-rwr.c         |  62 +++
 gdb/testsuite/gdb.arch/riscv-vu-rwr.exp       | 163 ++++++++
 .../gdb.arch/riscv-vu-side-effects.c          |  86 +++++
 .../gdb.arch/riscv-vu-side-effects.exp        | 162 ++++++++
 gdb/testsuite/lib/riscv64-rvv-lib.exp         | 166 ++++++++
 21 files changed, 2440 insertions(+)
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vector-abi-full-generate-template.txt
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vector-abi-full-generate.py
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vector-abi-full.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vector-abi-full.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vector-abi.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vector-abi.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-availability.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-availability.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-consitency-checks.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-consitency-checks.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-ctx-print.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-ctx-print.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-printout.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-printout.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-rvv-unsupported.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-rvv-unsupported.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-rwr.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-rwr.exp
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-side-effects.c
 create mode 100644 gdb/testsuite/gdb.arch/riscv-vu-side-effects.exp
 create mode 100644 gdb/testsuite/lib/riscv64-rvv-lib.exp

diff --git a/gdb/testsuite/gdb.arch/riscv-vector-abi-full-generate-template.txt b/gdb/testsuite/gdb.arch/riscv-vector-abi-full-generate-template.txt
new file mode 100644
index 00000000000..081572bd8ea
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vector-abi-full-generate-template.txt
@@ -0,0 +1,153 @@
+{% macro main_header(file) -%}
+/* DO NOT EDIT: Autogenerated by {{ file }}
+   Copyright 2025 Free Software Foundation, Inc.
+   This file is part of GDB, the GNU debugger.  */
+
+#include <riscv_vector.h>
+{% endmacro %}
+
+{% macro main_tail_start() %}
+void
+test ()
+{
+  size_t vl = 0;
+{% endmacro %}
+
+{% macro expect_header(file) -%}
+# DO NOT EDIT: Autogenerated by {{ file }}
+# Copyright 2025 Free Software Foundation, Inc.
+# This file is part of GDB, the GNU debugger.
+
+proc generate_response { start step count } {
+  if {$step == 0 && $count > 8} {
+    return "\\{${start} <repeats ${count} times>\\}"
+  }
+
+  set res "\\{$start"
+  set count [expr {$count - 1}]
+
+  for {set i 0} {$i < $count} {incr i} {
+    set start [expr {$start + $step}]
+    set res "${res}, $start"
+  }
+  set res "${res}\\}"
+  return $res
+}
+
+proc generate_tuple_response { nfields starts step count } {
+  set res "\\{__val = \\{"
+  set start [lindex $starts 0]
+  set entry [generate_response $start $step $count]
+  set res "${res}${entry}"
+
+  for {set i 1} {$i < $nfields} {incr i} {
+    set start [lindex $starts $i]
+    set entry [generate_response $start $step $count]
+    set res "${res}, $entry"
+  }
+
+  set res "${res}\\}\\}"
+  return $res
+}
+
+standard_testfile [standard_output_file riscv-vector-abi-full-generated.c]
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+  return -1
+}
+
+if {![runto_main]} {
+  return -1
+}
+{% endmacro %}
+
+{% macro func_name_template(type_name) -%}
+add_{{ type_name }}
+{%- endmacro %}
+
+{% macro func_template(type_name, vadd_name, func_name, vsetvlmax) -%}
+{{ type_name }}
+{{ func_name }} ({{ type_name }} a, {{ type_name }} b)
+{
+  size_t vl = {{ vsetvlmax }} ();
+  return {{ vadd_name }} (a, b, vl);
+}
+
+{% endmacro %}
+
+{% macro main_entry_template(type_name, var_idx, vmv_name, var_val, func_name, vsetvlmax) %}
+  // {{ type_name }}
+  vl = {{ vsetvlmax }} ();
+  {{ type_name }} var{{ var_idx }} = {{ vmv_name }} ({{ var_val }}, vl);
+  {{ type_name }} res{{ var_idx }} = {{ func_name }} (var{{ var_idx }}, var{{ var_idx }});
+  // {{ type_name }}_break
+{% endmacro %}
+
+{% macro test_entry_template(main_file, type_name, break_idx, var_idx, var_val, res_val, func_name) %}
+gdb_breakpoint "[host_standard_output_file {{ main_file }}]:[gdb_get_line_number "{{ type_name }}_break"]"
+gdb_continue_to_breakpoint "break {{ break_idx }}"
+set vl [get_valueof "/d" "vl" -1 "get_vl_{{ break_idx }}"]
+gdb_test "print var{{ var_idx }}" "[generate_response {{ var_val }} 0 $vl]"
+gdb_test "print res{{ var_idx }}" "[generate_response {{ res_val }} 0 $vl]"
+gdb_test "print {{ func_name }} (var{{ var_idx }}, var{{ var_idx }})" "[generate_response {{ res_val }} 0 $vl]"
+{% endmacro %}
+
+{% macro tuple_func_template_start() %}
+{type_name}
+{func_name} ({type_name} a, {type_name} b)
+{{ '{{' }}
+  {type_name} result;
+  size_t vl = {vsetvlmax} ();
+{% endmacro %}
+
+{% macro tuple_func_template_entry(index) %}
+  {short_type_name} a{{ index }} = {vget_name} (a, {{ index }});
+  {short_type_name} b{{ index }} = {vget_name} (b, {{ index }});
+  {short_type_name} r{{ index }} = {vadd_name} (a{{ index }}, b{{ index }}, vl);
+  result = {vset_name} (result, {{ index }}, r{{ index }});
+{% endmacro %}
+
+{% macro tuple_func_template_end() %}
+  return result;
+{{ '}}' }}
+{% endmacro %}
+
+{% macro tuple_main_entry_template_start() %}
+  // {type_name}
+  vl = {vsetvlmax} ();
+  {type_name} var{var_idx};
+{% endmacro %}
+
+{% macro tuple_main_entry_template_entry(index) %}
+  {short_type_name} var{var_idx}_{{ index }} = {vmv_name} ({var_values[{{ index }}]}, vl);
+  var{var_idx} = {vset_name} (var{var_idx}, {{ index }}, var{var_idx}_{{ index }});
+{% endmacro %}
+
+{% macro tuple_main_entry_template_end() %}
+  {type_name} res{var_idx} = {func_name} (var{var_idx}, var{var_idx});
+  // {type_name}_break
+{% endmacro %}
+
+{% macro tuple_test_template_start(main_file) %}
+gdb_breakpoint "[host_standard_output_file {{ main_file }}]:[gdb_get_line_number "{type_name}_break"]"
+gdb_continue_to_breakpoint "break {break_idx}"
+set vl [get_valueof "/d" "vl" -1 "get_vl_{break_idx}"]
+{% endmacro %}
+
+{% macro tuple_test_template_entry_first(index) -%}
+gdb_test "print var{var_idx}_{{ index }}" "[generate_response {var_values[{{ index }}]} 0 $vl]"
+{% endmacro %}
+
+{% macro tuple_test_template_entry_middle() -%}
+set res_values {{ '{{' }}
+{%- endmacro %}
+
+{% macro tuple_test_template_entry_second(index) -%}
+{{ ' ' }}{{ '{{' }}{res_values[{{ index }}]}{{ '}}' }}
+{%- endmacro %}
+
+{% macro tuple_test_template_end(nfields) -%}
+{{ ' }}' }}
+gdb_test "print res{var_idx}" "[generate_tuple_response {{ nfields }} $res_values 0 $vl]"
+gdb_test "print {func_name} (var{var_idx}, var{var_idx})" "[generate_tuple_response {{ nfields }} $res_values 0 $vl]"
+{% endmacro %}
diff --git a/gdb/testsuite/gdb.arch/riscv-vector-abi-full-generate.py b/gdb/testsuite/gdb.arch/riscv-vector-abi-full-generate.py
new file mode 100644
index 00000000000..b9113d526df
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vector-abi-full-generate.py
@@ -0,0 +1,360 @@
+import os
+import itertools
+import re
+from pathlib import Path
+from enum import StrEnum
+from jinja2 import Environment, FileSystemLoader
+
+FILE = Path(__file__).name
+TEST_DIR = Path(__file__).resolve().parent
+JINJA_TEMPLATE_FILE = "riscv-vector-abi-full-generate-template.txt"
+
+WORK_DIR = os.getenv("WORK_DIR")
+TEST_NAME = os.getenv("TEST_NAME")
+
+
+class ElemType(StrEnum):
+    INT = "int"
+    UINT = "uint"
+    FLOAT = "float"
+
+
+class InstrType(StrEnum):
+    VADD = "vadd"
+    VMV = "vmv"
+    VGET = "vget"
+    VSET = "vset"
+    VSETVLMAX = "vlmax"
+
+
+class InstructionTemplate:
+    vadd_instr_templates = {
+        ElemType.INT: "__riscv_vadd_vv_i{suffix1}",
+        ElemType.UINT: "__riscv_vadd_vv_u{suffix1}",
+        ElemType.FLOAT: "__riscv_vfadd_vv_f{suffix1}",
+    }
+
+    vmv_instr_templates = {
+        ElemType.INT: "__riscv_vmv_v_x_i{suffix1}",
+        ElemType.UINT: "__riscv_vmv_v_x_u{suffix1}",
+        ElemType.FLOAT: "__riscv_vfmv_v_f_f{suffix1}",
+    }
+
+    vget_instr_templates = {
+        ElemType.INT: "__riscv_vget_v_i{suffix1}_i{suffix2}",
+        ElemType.UINT: "__riscv_vget_v_u{suffix1}_u{suffix2}",
+        ElemType.FLOAT: "__riscv_vget_v_f{suffix1}_f{suffix2}",
+    }
+
+    vset_instr_templates = {
+        ElemType.INT: "__riscv_vset_v_i{suffix1}_i{suffix2}",
+        ElemType.UINT: "__riscv_vset_v_u{suffix1}_u{suffix2}",
+        ElemType.FLOAT: "__riscv_vset_v_f{suffix1}_f{suffix2}",
+    }
+
+    vsetvlmax_template = {k: "__riscv_vsetvlmax_e{suffix1}" for k in ElemType}
+
+    templates = {
+        InstrType.VADD: vadd_instr_templates,
+        InstrType.VMV: vmv_instr_templates,
+        InstrType.VGET: vget_instr_templates,
+        InstrType.VSET: vset_instr_templates,
+        InstrType.VSETVLMAX: vsetvlmax_template,
+    }
+
+    def get(self, elem_type: ElemType, instr_type: InstrType):
+        return self.templates[instr_type][elem_type]
+
+
+def generate(directory: Path, test_name: Path):
+    instr_templates = InstructionTemplate()
+
+    env = Environment(loader=FileSystemLoader(str(TEST_DIR)))
+    tpl = env.get_template(str(JINJA_TEMPLATE_FILE))
+
+    counter_vars = itertools.count(0)
+    counter_values = itertools.cycle(range(0, 64, 1))
+    counter_break_idx = itertools.count(2)
+
+    main_file = Path(f"{test_name}.c")
+    main_file_path = directory / main_file
+
+    test_script = Path(f"{test_name}.exp")
+    test_script_path = directory / test_script
+
+    if not os.path.exists(main_file_path):
+        os.mknod(main_file_path)
+
+    if not os.path.exists(test_script_path):
+        os.mknod(test_script_path)
+
+    main_header = tpl.module.main_header(FILE)
+
+    with open(main_file_path, "w") as f:
+        f.write(main_header)
+
+    main_tail = tpl.module.main_tail_start()
+
+    expect_header = tpl.module.expect_header(FILE)
+
+    with open(test_script_path, "w") as f:
+        f.write(expect_header)
+
+    # int, uint, float
+
+    # fmt: off
+    vint_types = [
+        # 8-bit
+        "vint8mf8_t", "vint8mf4_t", "vint8mf2_t", "vint8m1_t", "vint8m2_t", "vint8m4_t", "vint8m8_t",
+
+        # 16-bit
+        "vint16mf4_t", "vint16mf2_t", "vint16m1_t", "vint16m2_t", "vint16m4_t", "vint16m8_t",
+
+        # 32-bit
+        "vint32mf2_t", "vint32m1_t", "vint32m2_t", "vint32m4_t", "vint32m8_t",
+
+        # 64-bit
+        "vint64m1_t", "vint64m2_t", "vint64m4_t", "vint64m8_t",
+    ]
+
+    vuint_types = [_.replace("int", "uint") for _ in vint_types]
+
+    vfloat_types = [
+        # SEW = 16 (half-precision)
+        "vfloat16mf4_t", "vfloat16mf2_t", "vfloat16m1_t", "vfloat16m2_t", "vfloat16m4_t", "vfloat16m8_t",
+
+        # SEW = 32 (single-precision)
+        "vfloat32mf2_t", "vfloat32m1_t", "vfloat32m2_t", "vfloat32m4_t", "vfloat32m8_t",
+
+        # SEW = 64 (double-precision)
+        "vfloat64m1_t", "vfloat64m2_t", "vfloat64m4_t", "vfloat64m8_t",
+    ]
+    # fmt: on
+
+    for type_name in vint_types + vuint_types + vfloat_types:
+        m = re.match(r"v(int|uint|float)(8|16|32|64)(m|mf)(1|2|4|8)_t", type_name)
+        if not m:
+            raise RuntimeError("wrong type")
+
+        elem_type = ElemType(m.group(1))
+        small_suffix = "".join(m.group(2, 3, 4))  # 16m2
+
+        func_name = tpl.module.func_name_template(type_name)
+        vsetvlmax = instr_templates.get(elem_type, InstrType.VSETVLMAX).format(
+            suffix1=small_suffix
+        )
+        vadd_name = instr_templates.get(elem_type, InstrType.VADD).format(
+            suffix1=small_suffix
+        )
+        vmv_name = instr_templates.get(elem_type, InstrType.VMV).format(
+            suffix1=small_suffix
+        )
+
+        var_idx = next(counter_vars)
+        var_val = next(counter_values)
+        res_val = 2 * var_val
+
+        new_line = tpl.module.func_template(
+            type_name,
+            vadd_name,
+            func_name,
+            vsetvlmax,
+        )
+
+        with open(main_file_path, "a") as f:
+            f.write(new_line)
+
+        main_tail += tpl.module.main_entry_template(
+            type_name,
+            var_idx,
+            vmv_name,
+            var_val,
+            func_name,
+            vsetvlmax,
+        )
+
+        break_idx = next(counter_break_idx)
+        test_command = tpl.module.test_entry_template(
+            main_file,
+            type_name,
+            break_idx,
+            var_idx,
+            var_val,
+            res_val,
+            func_name,
+        )
+        with open(test_script_path, "a") as f:
+            f.write(test_command)
+
+    # tuple int
+
+    # fmt: off
+    vint_tuple_types = [
+        # LMUL = mf8
+        "vint8mf8x2_t", "vint8mf8x3_t", "vint8mf8x4_t", "vint8mf8x5_t", "vint8mf8x6_t", "vint8mf8x7_t", "vint8mf8x8_t",
+
+        # LMUL = mf4
+        "vint8mf4x2_t", "vint8mf4x3_t", "vint8mf4x4_t", "vint8mf4x5_t", "vint8mf4x6_t", "vint8mf4x7_t", "vint8mf4x8_t",
+        "vint16mf4x2_t", "vint16mf4x3_t", "vint16mf4x4_t", "vint16mf4x5_t", "vint16mf4x6_t", "vint16mf4x7_t", "vint16mf4x8_t",
+
+        # LMUL = mf2
+        "vint8mf2x2_t", "vint8mf2x3_t", "vint8mf2x4_t", "vint8mf2x5_t", "vint8mf2x6_t", "vint8mf2x7_t", "vint8mf2x8_t",
+        "vint16mf2x2_t", "vint16mf2x3_t", "vint16mf2x4_t", "vint16mf2x5_t", "vint16mf2x6_t", "vint16mf2x7_t", "vint16mf2x8_t",
+        "vint32mf2x2_t", "vint32mf2x3_t", "vint32mf2x4_t", "vint32mf2x5_t", "vint32mf2x6_t", "vint32mf2x7_t", "vint32mf2x8_t",
+
+        # LMUL = m1
+        "vint8m1x2_t", "vint8m1x3_t", "vint8m1x4_t", "vint8m1x5_t", "vint8m1x6_t", "vint8m1x7_t", "vint8m1x8_t",
+        "vint16m1x2_t", "vint16m1x3_t", "vint16m1x4_t", "vint16m1x5_t", "vint16m1x6_t", "vint16m1x7_t", "vint16m1x8_t",
+        "vint32m1x2_t", "vint32m1x3_t", "vint32m1x4_t", "vint32m1x5_t", "vint32m1x6_t", "vint32m1x7_t", "vint32m1x8_t",
+        "vint64m1x2_t", "vint64m1x3_t", "vint64m1x4_t", "vint64m1x5_t", "vint64m1x6_t", "vint64m1x7_t", "vint64m1x8_t",
+
+        # LMUL = m2
+        "vint8m2x2_t", "vint8m2x3_t", "vint8m2x4_t",
+        "vint16m2x2_t", "vint16m2x3_t", "vint16m2x4_t",
+        "vint32m2x2_t", "vint32m2x3_t", "vint32m2x4_t",
+        "vint64m2x2_t", "vint64m2x3_t", "vint64m2x4_t",
+
+        # LMUL = m4
+        "vint8m4x2_t",
+        "vint16m4x2_t",
+        "vint32m4x2_t",
+        "vint64m4x2_t",
+    ]
+
+    vuint_tuple_types = [_.replace("int", "uint") for _ in vint_tuple_types]
+
+    vfloat_tuple_types = [
+        # vfloat16
+        "vfloat16mf4x2_t", "vfloat16mf4x3_t", "vfloat16mf4x4_t", "vfloat16mf4x5_t",
+        "vfloat16mf4x6_t", "vfloat16mf4x7_t", "vfloat16mf4x8_t",
+        "vfloat16mf2x2_t", "vfloat16mf2x3_t", "vfloat16mf2x4_t", "vfloat16mf2x5_t",
+        "vfloat16mf2x6_t", "vfloat16mf2x7_t", "vfloat16mf2x8_t",
+        "vfloat16m1x2_t", "vfloat16m1x3_t", "vfloat16m1x4_t", "vfloat16m1x5_t",
+        "vfloat16m1x6_t", "vfloat16m1x7_t", "vfloat16m1x8_t",
+        "vfloat16m2x2_t", "vfloat16m2x3_t", "vfloat16m2x4_t",
+        "vfloat16m4x2_t",
+
+        # LMUL = mf2 (1/2)
+        "vfloat32mf2x2_t", "vfloat32mf2x3_t", "vfloat32mf2x4_t", "vfloat32mf2x5_t",
+        "vfloat32mf2x6_t", "vfloat32mf2x7_t", "vfloat32mf2x8_t",
+
+        # LMUL = m1 (1)
+        "vfloat32m1x2_t", "vfloat32m1x3_t", "vfloat32m1x4_t", "vfloat32m1x5_t",
+        "vfloat32m1x6_t", "vfloat32m1x7_t", "vfloat32m1x8_t",
+        "vfloat64m1x2_t", "vfloat64m1x3_t", "vfloat64m1x4_t", "vfloat64m1x5_t",
+        "vfloat64m1x6_t", "vfloat64m1x7_t", "vfloat64m1x8_t",
+
+        # LMUL = m2 (2)
+        "vfloat32m2x2_t", "vfloat32m2x3_t", "vfloat32m2x4_t",
+        "vfloat64m2x2_t", "vfloat64m2x3_t", "vfloat64m2x4_t",
+
+        # LMUL = m4 (4)
+        "vfloat32m4x2_t",
+        "vfloat64m4x2_t",
+    ]
+    # fmt: on
+
+    def get_tuple_template(nfields: int) -> str:
+        tuple_template = tpl.module.tuple_func_template_start()
+        for i in range(nfields):
+            tuple_template += tpl.module.tuple_func_template_entry(i)
+        tuple_template += tpl.module.tuple_func_template_end()
+        return tuple_template
+
+    def get_main_tuple_template(nfields: int) -> str:
+        main_tuple_template = tpl.module.tuple_main_entry_template_start()
+        for i in range(nfields):
+            main_tuple_template += tpl.module.tuple_main_entry_template_entry(i)
+        main_tuple_template += tpl.module.tuple_main_entry_template_end()
+        return main_tuple_template
+
+    def get_test_tuple_template(nfields: int) -> str:
+        test_tuple_template = tpl.module.tuple_test_template_start(main_file)
+        for i in range(nfields):
+            test_tuple_template += tpl.module.tuple_test_template_entry_first(i)
+        test_tuple_template += tpl.module.tuple_test_template_entry_middle()
+        for i in range(nfields):
+            test_tuple_template += tpl.module.tuple_test_template_entry_second(i)
+        test_tuple_template += tpl.module.tuple_test_template_end(nfields)
+        return test_tuple_template
+
+    for type_name in vint_tuple_types + vuint_tuple_types + vfloat_tuple_types:
+        m = re.match(
+            r"v(int|uint|float)(8|16|32|64)(m|mf)(1|2|4|8)(x)([2-8])_t",
+            type_name,
+        )
+        if not m:
+            raise RuntimeError("wrong type")
+
+        elem_type = ElemType(m.group(1))
+        nfields = int(m.group(6))
+        short = type_name[:-4] + "_t"
+        big_suffix = "".join(m.group(2, 3, 4, 5, 6))  # 16m2x3
+        small_suffix = "".join(m.group(2, 3, 4))  # 16m2
+
+        func_name = tpl.module.func_name_template(type_name)
+        vsetvlmax = instr_templates.get(elem_type, InstrType.VSETVLMAX).format(
+            suffix1=small_suffix
+        )
+        vget_name = instr_templates.get(elem_type, InstrType.VGET).format(
+            suffix1=big_suffix, suffix2=small_suffix
+        )
+        vadd_name = instr_templates.get(elem_type, InstrType.VADD).format(
+            suffix1=small_suffix
+        )
+        vset_name = instr_templates.get(elem_type, InstrType.VSET).format(
+            suffix1=small_suffix, suffix2=big_suffix
+        )
+        vmv_name = instr_templates.get(elem_type, InstrType.VMV).format(
+            suffix1=small_suffix
+        )
+
+        var_idx = next(counter_vars)
+        var_values = [val for _, val in zip(range(nfields), counter_values)]
+        res_values = [2 * val for val in var_values]
+
+        string = get_tuple_template(nfields).format(
+            type_name=type_name,
+            short_type_name=short,
+            vget_name=vget_name,
+            vadd_name=vadd_name,
+            vset_name=vset_name,
+            func_name=func_name,
+            vsetvlmax=vsetvlmax,
+        )
+
+        with open(main_file_path, "a") as f:
+            f.write(string)
+
+        main_tail += get_main_tuple_template(nfields).format(
+            vsetvlmax=vsetvlmax,
+            short_type_name=short,
+            var_idx=var_idx,
+            small_suffix=small_suffix,
+            type_name=type_name,
+            vset_name=vset_name,
+            func_name=func_name,
+            vmv_name=vmv_name,
+            var_values=var_values,
+        )
+
+        break_idx = next(counter_break_idx)
+        test_command = get_test_tuple_template(nfields).format(
+            type_name=type_name,
+            break_idx=break_idx,
+            var_idx=var_idx,
+            var_values=var_values,
+            res_values=res_values,
+            func_name=func_name,
+        )
+
+        with open(test_script_path, "a") as f:
+            f.write(test_command)
+
+    with open(main_file_path, "a") as f:
+        f.write(main_tail)
+        f.write("\n  return;\n}\n")
+        f.write("\nint main () {test();}\n")
+
+
+generate(WORK_DIR, TEST_NAME)
diff --git a/gdb/testsuite/gdb.arch/riscv-vector-abi-full.c b/gdb/testsuite/gdb.arch/riscv-vector-abi-full.c
new file mode 100644
index 00000000000..b8ab1fc1784
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vector-abi-full.c
@@ -0,0 +1,23 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+int
+main ()
+{
+  __asm__ __volatile__ ("vsetvli t0, x0, e8");
+  return 0; /* break 2 */
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vector-abi-full.exp b/gdb/testsuite/gdb.arch/riscv-vector-abi-full.exp
new file mode 100644
index 00000000000..3ee6c7edc15
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vector-abi-full.exp
@@ -0,0 +1,65 @@
+# Copyright 2025 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/>.
+
+load_lib riscv64-rvv-lib.exp
+
+if {[catch {exec python3 -c "import jinja2"} result]} {
+    unsupported "python3 with jinja2 is required"
+    return
+}
+
+if {![riscv_support_rvv]} {
+  unsupported "RVV unsupported"
+  return
+}
+
+if {![riscv_support_rvv_intrinsic]} {
+  unsupported "RVV intrinsic unsupported"
+  return
+}
+
+standard_testfile
+
+set compile_flags {"debug"}
+lappend compile_flags "additional_flags=-march=rv64gcv"
+
+# First, we figure out VLENB value to set correct vector extension to march
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+  return -1
+}
+
+if {![runto_main]} {
+  return -1
+}
+
+gdb_breakpoint "$srcfile:[gdb_get_line_number "break 2"]"
+gdb_continue_to_breakpoint "preparing stage"
+set vlenb [riscvlib_rvv_get_csr vlenb "$testfile"]
+
+set compile_flags {"debug"}
+if {$vlenb >= 16} {
+  lappend compile_flags "additional_flags=-march=rv64gcv_zvfh"
+} elseif {$vlenb >= 8} {
+  lappend compile_flags "additional_flags=-march=rv64gc_zve64d_zvfh"
+} else {
+  unsupported "Unsupported VLENB value: $vlenb"
+  return
+}
+
+set env(WORK_DIR) [standard_output_file ""]
+set env(TEST_NAME) riscv-vector-abi-full-generated
+exec python3 $srcdir/$subdir/riscv-vector-abi-full-generate.py
+
+source [standard_output_file riscv-vector-abi-full-generated.exp]
diff --git a/gdb/testsuite/gdb.arch/riscv-vector-abi.c b/gdb/testsuite/gdb.arch/riscv-vector-abi.c
new file mode 100644
index 00000000000..120e2e2fd1e
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vector-abi.c
@@ -0,0 +1,157 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#include <riscv_vector.h>
+#include <malloc.h>
+
+unsigned
+do_vlen_read ()
+{
+  unsigned vlenb;
+  asm volatile ("csrr %[vlenb], vlenb" : [vlenb] "=r"(vlenb) : :);
+  /* According to vector spec: "vlenb holds the value VLEN/8".  */
+  return vlenb * 8;
+}
+
+vint64m1_t
+foo (vint64m1_t a, vint32mf2_t b, vint64m1_t c, size_t n)
+{
+  vint64m1_t tmp = __riscv_vwadd_wv_i64m1 (a, b, n);
+  return __riscv_vadd_vv_i64m1 (c, tmp, n);
+}
+
+vint32m4_t
+foo1 (vint32m4_t a, vint16m2_t b, size_t n)
+{
+  return __riscv_vwadd_wv_i32m4 (a, b, n);
+}
+
+vint32m4_t
+foo2 (vint16m2_t a, vint32m4_t b, size_t n)
+{
+  return __riscv_vwadd_wv_i32m4 (b, a, n);
+}
+
+vint64m8_t
+foo3 (vint64m8_t a, vint64m8_t b, vint64m8_t c, size_t n)
+{
+  vint64m8_t tmp = __riscv_vadd_vv_i64m8 (a, b, n);
+  return __riscv_vadd_vv_i64m8 (tmp, c, n);
+}
+
+vint64m8_t
+foo4 (vint64m8_t a, vint64m8_t b, vbool8_t mask, vbool8_t mask2, size_t n)
+{
+  return __riscv_vadd_vv_i64m8_m (mask2, a, b, n);
+}
+
+vint32m4_t
+foo5_get0 (vint16m2_t tmp_a, vint32m4x2_t a)
+{
+  return __riscv_vget_v_i32m4x2_i32m4 (a, 0);
+}
+
+vint32m4_t
+foo5_get1 (vint16m2_t tmp_a, vint32m4x2_t a)
+{
+  return __riscv_vget_v_i32m4x2_i32m4 (a, 1);
+}
+
+vint32mf2_t
+foo6_get0 (vint16m2_t tmp_a, vint32mf2x2_t a)
+{
+  return __riscv_vget_v_i32mf2x2_i32mf2 (a, 0);
+}
+
+vint32mf2_t
+foo6_get1 (vint16m2_t tmp_a, vint32mf2x2_t a)
+{
+  return __riscv_vget_v_i32mf2x2_i32mf2 (a, 1);
+}
+
+int
+main ()
+{
+  unsigned n = do_vlen_read () / 64;
+  vint64m1_t a = __riscv_vmv_v_x_i64m1 (42, n);
+  vint32mf2_t b = __riscv_vmv_v_x_i32mf2 (43, n);
+  vint64m1_t c = __riscv_vmv_v_x_i64m1 (44, n);
+
+  vint64m1_t res = foo (a, b, c, n);
+  /* break 2 */
+
+  n = do_vlen_read () * 4 / 32;
+  vint32m4_t g = __riscv_vmv_v_x_i32m4 (48, n);
+  vint16m2_t h = __riscv_vmv_v_x_i16m2 (49, n);
+
+  vint32m4_t res_1 = foo1 (g, h, n); // g is on v8-v11, h is on v12-v13
+  vint32m4_t res_2 = foo2 (h, g, n); // h is on v8-v9,  g is on v12-v15
+  /* break 3 */
+
+  n = do_vlen_read () * 8 / 64;
+  vint64m8_t big1 = __riscv_vmv_v_x_i64m8 (50, n);
+  vint64m8_t big2 = __riscv_vmv_v_x_i64m8 (51, n);
+  vint64m8_t big3 = __riscv_vmv_v_x_i64m8 (52, n);
+  vint64m8_t big_res = foo3 (big1, big2, big3, n);
+  /* break 4 */
+
+  unsigned mask_size = n / 8;
+  uint8_t *rs1_mask = malloc (mask_size * sizeof (uint8_t));
+  for (int i = 0; i < mask_size; i++)
+    rs1_mask[i] = 0xa5;
+
+  vbool8_t mask = __riscv_vlm_v_b8 (rs1_mask, n);
+  vint64m8_t masked_sum = foo4 (big1, big2, mask, mask, n);
+  /* break 5 */
+
+  n = do_vlen_read () * 4 * 2 / 32;
+  unsigned addr_size = n / 2;
+  uint32_t *addr = malloc (addr_size * sizeof (uint32_t));
+  for (unsigned i = 0; i < addr_size; i++)
+    addr[i] = 8 * (uint32_t)i;
+
+  vuint32m4_t rs2 = __riscv_vle32_v_u32m4 (addr, addr_size);
+  /* break 6 */
+
+  int32_t *rs1 = malloc (n);
+  for (int i = 0; i < n; i++)
+    rs1[i] = (int32_t)i;
+
+  vint32m4x2_t a_seg = __riscv_vluxseg2ei32_v_i32m4x2 (rs1, rs2, n);
+  /* break 7 */
+  vint32m4_t res_a_seg0 = foo5_get0 (h, a_seg);
+  /* break 8 */
+  vint32m4_t res_a_seg1 = foo5_get1 (h, a_seg);
+  /* break 9 */
+
+  vuint32mf2_t rs2_2 = __riscv_vle32_v_u32mf2 (addr, addr_size);
+  /* break 10 */
+
+  n = do_vlen_read () / 32;
+  vint32mf2x2_t b_seg = __riscv_vluxseg2ei32_v_i32mf2x2 (rs1, rs2_2, n);
+  /* break 11 */
+  vint32mf2_t res_b_seg0 = foo6_get0 (h, b_seg);
+  /* break 12 */
+  vint32mf2_t res_b_seg1 = foo6_get1 (h, b_seg);
+  /* break 13 */
+
+  free (rs1_mask);
+  free (addr);
+  free (rs1);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vector-abi.exp b/gdb/testsuite/gdb.arch/riscv-vector-abi.exp
new file mode 100644
index 00000000000..00b046f2f1f
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vector-abi.exp
@@ -0,0 +1,230 @@
+# Copyright 2025 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/>.
+
+load_lib riscv64-rvv-lib.exp
+
+set get_vl_called_times 0
+
+proc get_vl {} {
+  global hex
+  global decimal
+  global gdb_prompt
+  global gdb_test_name
+  global get_vl_called_times
+
+  set vl 0x0
+
+  gdb_test_multiple "info registers \$vl" "$get_vl_called_times call of get_vl()" {
+    -re "^info registers\[^\r\n\]+\r\n" {
+      exp_continue
+    }
+
+    -re "^vl\\s+(${hex})\\s+(${decimal})\r\n" {
+      set vl $expect_out(2,string)
+      exp_continue
+    }
+
+    -re "^$gdb_prompt $" {
+      pass $gdb_test_name
+    }
+  }
+
+  set get_vl_called_times [expr {$get_vl_called_times + 1}]
+
+  return $vl
+}
+
+proc generate_sequence { start step count } {
+  if {$step == 0 && $count > 8} {
+    return "$start <repeats $count times>"
+  }
+
+  set res "$start"
+  set count [expr {$count - 1}]
+
+  for {set i 0} {$i < $count} {incr i} {
+    set start [expr {$start + $step}]
+    set res "${res}, $start"
+  }
+
+  return $res
+}
+
+if {![riscv_support_rvv]} {
+  unsupported "RVV unsupported"
+  return
+}
+
+if {![riscv_support_rvv_intrinsic]} {
+  unsupported "RVV intrinsic unsupported"
+  return
+}
+
+standard_testfile
+
+set compile_flags {"debug"}
+lappend compile_flags "additional_flags=-march=rv64gcv"
+
+# First, we figure out VLENB value to set correct vector extension to march
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+  return -1
+}
+
+if {![runto_main]} {
+  return -1
+}
+
+gdb_breakpoint "$srcfile:[gdb_get_line_number "break 2"]"
+gdb_continue_to_breakpoint "preparing stage"
+set vlenb [riscvlib_rvv_get_csr vlenb "$testfile"]
+
+set compile_flags {"debug"}
+if {$vlenb >= 16} {
+  lappend compile_flags "additional_flags=-march=rv64gcv"
+} elseif {$vlenb >= 8} {
+  lappend compile_flags "additional_flags=-march=rv64gc_zve64x"
+} else {
+  unsupported "Unsupported VLENB value: $vlenb"
+  return
+}
+
+# Here is real test started
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+  return -1
+}
+
+if {![runto_main]} {
+  return -1
+}
+
+for {set i 2} {$i <= 13} {incr i} {
+  gdb_breakpoint "$srcfile:[gdb_get_line_number "break $i"]"
+}
+
+gdb_continue_to_breakpoint "break 2"
+
+set vl [get_vl]
+
+gdb_test "print a" "\\{[generate_sequence 42 0 $vl]\\}"
+gdb_test "print b" "\\{[generate_sequence 43 0 $vl]\\}"
+gdb_test "print c" "\\{[generate_sequence 44 0 $vl]\\}"
+gdb_test "print res" "\\{[generate_sequence 129 0 $vl]\\}"
+gdb_test "print foo(a, b, c, n)" "\\{[generate_sequence 129 0 $vl]\\}"
+
+gdb_continue_to_breakpoint "break 3"
+
+set vl [get_vl]
+
+gdb_test "print g" "\\{[generate_sequence 48 0 $vl]\\}"
+gdb_test "print h" "\\{[generate_sequence 49 0 $vl]\\}"
+
+gdb_test "print res_1" "\\{[generate_sequence 97 0 $vl]\\}"
+gdb_test "print foo1(g, h, n)" "\\{[generate_sequence 97 0 $vl]\\}"
+
+gdb_test "print res_2" "\\{[generate_sequence 97 0 $vl]\\}"
+gdb_test "print foo2(h, g, n)" "\\{[generate_sequence 97 0 $vl]\\}"
+
+gdb_continue_to_breakpoint "break 4"
+
+set vl [get_vl]
+
+gdb_test "print big1" "\\{[generate_sequence 50 0 $vl]\\}"
+gdb_test "print big2" "\\{[generate_sequence 51 0 $vl]\\}"
+gdb_test "print big3" "\\{[generate_sequence 52 0 $vl]\\}"
+gdb_test "print big_res" "\\{[generate_sequence 153 0 $vl]\\}"
+gdb_test "print foo3(big1, big2, big3, n)" "\\{[generate_sequence 153 0 $vl]\\}"
+
+gdb_continue_to_breakpoint "break 5"
+
+set vl [get_vl]
+set repeat_num [expr {$vl / 8 - 1}]
+
+set pattern_part "101, 51, 101, 51, 51, 101, 51, 101"
+set pattern "\\{$pattern_part"
+for {set i 0} {$i < $repeat_num} {incr i} {
+  set pattern "$pattern, $pattern_part"
+}
+set pattern "$pattern\\}"
+
+gdb_test "print masked_sum" $pattern
+gdb_test "print foo4(big1, big2, mask, mask, n)" $pattern
+
+gdb_continue_to_breakpoint "break 6"
+
+set vl [get_vl]
+
+set pattern "\\{[generate_sequence 0 8 $vl]\\}"
+
+gdb_test "print rs2" $pattern
+
+gdb_continue_to_breakpoint "break 7"
+
+set vl [get_vl]
+
+set pattern "= \\{\\{[generate_sequence 0 2 $vl].*\\}, \\{[generate_sequence 1 2 $vl].*\\}\\}"
+
+gdb_test "print a_seg" $pattern
+
+gdb_continue_to_breakpoint "break 8"
+
+set vl [get_vl]
+
+set pattern "= \\{[generate_sequence 0 2 $vl].*\\}"
+
+gdb_test "print res_a_seg0" $pattern
+gdb_test "print foo5_get0(h, a_seg)" $pattern
+
+gdb_continue_to_breakpoint "break 9"
+
+set vl [get_vl]
+
+set pattern "= \\{[generate_sequence 1 2 $vl].*\\}"
+
+gdb_test "print res_a_seg1" $pattern
+gdb_test "print foo5_get1(h, a_seg)" $pattern
+
+gdb_continue_to_breakpoint "break 10"
+
+set vl [get_vl]
+
+set pattern "\\{[generate_sequence 0 8 $vl]\\}"
+
+gdb_test "print rs2_2" $pattern
+
+gdb_continue_to_breakpoint "break 11"
+
+set vl [get_vl]
+
+set pattern "= \\{\\{[generate_sequence 0 2 $vl].*\\}, \\{[generate_sequence 1 2 $vl].*\\}\\}"
+
+gdb_test "print b_seg" $pattern
+
+gdb_continue_to_breakpoint "break 12"
+
+set vl [get_vl]
+
+set pattern "= \\{[generate_sequence 0 2 $vl].*\\}"
+
+gdb_test "print res_b_seg0" $pattern
+gdb_test "print foo6_get0(h, b_seg)" $pattern
+
+gdb_continue_to_breakpoint "break 13"
+
+set vl [get_vl]
+
+set pattern "= \\{[generate_sequence 1 2 $vl].*\\}"
+
+gdb_test "print res_b_seg1" $pattern
+gdb_test "print foo6_get1(h, b_seg)" $pattern
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-availability.c b/gdb/testsuite/gdb.arch/riscv-vu-availability.c
new file mode 100644
index 00000000000..620ecb7142d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-availability.c
@@ -0,0 +1,67 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+asm (".option arch, +v\n");
+
+unsigned
+do_vlenb_read ()
+{
+  unsigned vlenb;
+  asm volatile ("csrr %[vlenb], vlenb" : [vlenb] "=r"(vlenb) : :);
+  return vlenb;
+}
+
+unsigned
+do_vsetvli ()
+{
+  unsigned vl;
+  asm volatile ("vsetvli %[new_vl], x0, e8, m1, ta, ma"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  return vl;
+}
+
+#ifdef READ_VLENB_BEFORE_MAIN
+unsigned VLENB = do_vlenb_read ();
+#endif // READ_VLENB_BEFORE_MAIN
+
+#ifdef SET_VSETVLI_BEFORE_MAIN
+unsigned VL = do_vsetvli ();
+#endif // SET_VSETVLI_BEFORE_MAIN
+
+int STORAGE[64];
+
+void
+do_vector_stuff ()
+{
+  do_vsetvli ();
+  asm volatile ("vadd.vi v1, v1, 0x1");
+  asm volatile ("vadd.vi v2, v1, 0x2");
+  asm volatile ("vs1r.v v1, (%0)"
+		:
+		: "r"(STORAGE)
+		: "memory"); /* pre_vect_mem */
+  asm volatile ("vl1re8.v v2, (%0)" : : "r"(STORAGE) : "memory");
+}
+
+int
+main ()
+{
+  do_vector_stuff ();
+  return 0; /* post_vector_op */
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-availability.exp b/gdb/testsuite/gdb.arch/riscv-vu-availability.exp
new file mode 100644
index 00000000000..dbbb010f055
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-availability.exp
@@ -0,0 +1,72 @@
+# Copyright 2025 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/>.
+
+require {istarget "riscv*-*-*"}
+
+if {![riscv_support_rvv]} {
+  unsupported "RVV unsupported"
+  return
+}
+
+standard_testfile
+load_lib riscv64-rvv-lib.exp
+
+proc initialize_vu_availability_test {extra_args } {
+  global testfile
+  global srcfile
+
+  set compile_flags {}
+  lappend compile_flags debug
+  lappend compile_flags c++
+  lappend compile_flags "additional_flags=-march=rv64gc ${extra_args}"
+
+  if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+    return -1
+  }
+
+  if {![runto_main]} {
+    return -1
+  }
+}
+
+proc test_unavailable_regs { extra_args } {
+  initialize_vu_availability_test ${extra_args}
+  gdb_test "print \$vtype" "= <unavailable>" "test vtype unavailable ${extra_args}"
+  gdb_test "print \$vcsr" "= <unavailable>" "test vcsr unavailable ${extra_args}"
+  gdb_test "print \$vl" "= <unavailable>" "test vl unavailable ${extra_args}"
+  gdb_test "print \$vstart" "= <unavailable>" "test vstart unavailable ${extra_args}"
+  gdb_test "print \$vlenb" "= <unavailable>" "test vlenb unavailable ${extra_args}"
+  for {set i 0} {$i < 32} {incr i} {
+    gdb_test "print \$v${i}" "= <unavailable>" "test v${i} unavailable ${extra_args}"
+  }
+}
+
+proc test_available_regs { extra_args } {
+  global testfile
+  initialize_vu_availability_test ${extra_args}
+  set VLENB [riscvlib_rvv_get_csr vlenb "$testfile"]
+  gdb_test "print \$vtype" "= 192" "test vtype available ${extra_args}"
+  gdb_test "print \$vcsr" "= 0" "test vcsr available ${extra_args}"
+  gdb_test "print \$vl" "= $VLENB" "test vl available ${extra_args}"
+  gdb_test "print \$vstart" "= 0" "test vstart available ${extra_args}"
+  gdb_test "print \$vlenb" "= $VLENB" "test vlenb available ${extra_args}"
+  for {set i 0} {$i < 32} {incr i} {
+    gdb_test "print \$v${i}" [riscvlib_rvv_vreg_zero_pattern $VLENB] "test v${i} available ${extra_args}"
+  }
+}
+
+test_unavailable_regs "-DREAD_VLENB_BEFORE_MAIN"
+test_unavailable_regs ""
+test_available_regs "-DSET_VSETVLI_BEFORE_MAIN"
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-consitency-checks.c b/gdb/testsuite/gdb.arch/riscv-vu-consitency-checks.c
new file mode 100644
index 00000000000..f392b0a2df3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-consitency-checks.c
@@ -0,0 +1,79 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+asm (".option arch, +v\n");
+
+#include <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+
+unsigned
+do_vlenb_read ()
+{
+  unsigned vlenb;
+  asm volatile ("csrr %[vlenb], vlenb" : [vlenb] "=r"(vlenb) : :);
+  return vlenb;
+}
+
+void
+reset_vu ()
+{
+  unsigned vl;
+  asm volatile ("vsetvli %[new_vl], x0, e8, m8, ta, ma"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  asm volatile ("vxor.vv v0, v0, v0\n"
+		"vxor.vv v8, v8, v8\n"
+		"vxor.vv v16, v16, v16\n"
+		"vxor.vv v24, v24, v24\n"
+		"csrrci zero, vxrm, 3\n"
+		"csrrci zero, vxsat, 1\n");
+  asm volatile ("vsetvli %[new_vl], x0, e8, m1, tu, mu"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  asm volatile ("nop"); /* vu_reset_end */
+}
+
+void
+do_workload ()
+{
+  unsigned long long app_vtype;
+  unsigned app_vl;
+  unsigned app_vlenb;
+  asm volatile ("csrr %[vtype], vtype\n" : [vtype] "=r"(app_vtype) : :);
+  asm volatile ("csrr %[vl], vl\n"
+		: [vl] "=r"(app_vl) /* vect_test_vtype_read */
+		:
+		:);
+  asm volatile ("csrr %[vlenb], vlenb\n" : [vlenb] "=r"(app_vlenb) : :);
+  asm volatile ("vxor.vv v24, v16, v8\n" : : :);
+  asm volatile ("nop"); /* workload_end */
+}
+
+int
+main ()
+{
+  unsigned vlenb_value = do_vlenb_read ();
+  (void)vlenb_value;
+  reset_vu ();
+  /* vect_test_start */
+  for (int i = 0; i < 777; ++i)
+    do_workload ();
+  return 0; /* vect_test_end */
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-consitency-checks.exp b/gdb/testsuite/gdb.arch/riscv-vu-consitency-checks.exp
new file mode 100644
index 00000000000..9f52d1dcbd4
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-consitency-checks.exp
@@ -0,0 +1,152 @@
+# Copyright 2025 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/>.
+
+require {istarget "riscv*-*-*"}
+
+if {![riscv_support_rvv]} {
+  unsupported "RVV unsupported"
+  return
+}
+
+standard_testfile
+load_lib riscv64-rvv-lib.exp
+
+proc test_vu_consistency_vl_overflow {VLENB} {
+  set the_proc [lindex [info level 0] 0]
+
+  gdb_continue_to_breakpoint "$the_proc: start"
+  gdb_test "print app_vtype" "= 0"      "$the_proc: app vtype"
+  gdb_test "print app_vl" "= $VLENB"    "$the_proc: app vl"
+  gdb_test "print app_vlenb" "= $VLENB" "$the_proc: app vlenb"
+  gdb_test_no_output "set \$vl = 9999"
+
+  gdb_continue_to_breakpoint "$the_proc: vl updated"
+  gdb_test "print app_vtype" "= 0"      "$the_proc: app vtype - after vl update"
+  gdb_test "print app_vl" "= $VLENB"    "$the_proc: app vl - after vl update"
+  gdb_test "print app_vlenb" "= $VLENB" "$the_proc: app vlenb - after vl update"
+  gdb_test "print \$vl" "= $VLENB"      "$the_proc: ptraced vl - after vl update"
+}
+
+proc test_vu_coherent_vl_lmul_downgrade {VLENB} {
+  set the_proc [lindex [info level 0] 0]
+
+  gdb_continue_to_breakpoint "$the_proc: start"
+  gdb_test_no_output "set \$vtype = 3"
+
+  gdb_continue_to_breakpoint "$the_proc: run with updated LMUL 8"
+  gdb_test_no_output "set \$vl = 9999" "set \$vl = 9999 large value"
+
+  gdb_continue_to_breakpoint "$the_proc: run with updated large vl"
+  gdb_test "print app_vtype" "= 3"                "$the_proc: app vtype - after vtype LMUL 8 update"
+  gdb_test "print app_vl" "= [expr {$VLENB * 8}]" "$the_proc: app vl - after vl LMUL 8 update"
+  gdb_test "print app_vlenb" "= $VLENB"           "$the_proc: app vlenb - after LMUL 8 update"
+  gdb_test "print \$vl" "= [expr {$VLENB * 8}]"   "$the_proc: ptraced vl - VLENB * 8"
+  gdb_test "print \$vtype" "= 3"                  "$the_proc: ptraced vtype - 3"
+
+  gdb_continue_to_breakpoint "$the_proc: going to switch LMUL back to 1"
+  gdb_test_no_output "set \$vtype = 0"
+
+  gdb_continue_to_breakpoint "$the_proc: LMUL should be 1"
+  gdb_test "print app_vtype" "= 0"      "$the_proc: app vtype - after LMUL 1 update"
+  gdb_test "print app_vl" "= $VLENB"    "$the_proc: app vl - after LMUL 1 update"
+  gdb_test "print app_vlenb" "= $VLENB" "$the_proc: app vlenb - after LMUL 1 update"
+  gdb_test "print \$vl" "= $VLENB"      "$the_proc: ptraced vl - after LMUL 1 update"
+  gdb_test "print \$vtype" "= 0"        "$the_proc: ptraced vtype - after LMUL 1 update"
+}
+
+proc test_vu_coherent_non_zero_vstart {VLENB} {
+  set the_proc [lindex [info level 0] 0]
+  gdb_continue_to_breakpoint "$the_proc: messing up vstart"
+  gdb_test_no_output "set \$vstart = 8"
+
+  gdb_continue_to_breakpoint "$the_proc: vstart was 8"
+  gdb_test "print \$vstart" "= 0" "$the_proc: ptraced vstart - after vstart update"
+}
+
+proc test_vu_consistency_incorrect_vtype {VLENB} {
+  global srcfile
+  set the_proc [lindex [info level 0] 0]
+  if {$VLENB >= 64} {
+    untested "$the_proc: VLENB must be less than 64"
+    return
+  }
+  gdb_continue_to_breakpoint "$the_proc: setting SEW to 64 and LMUL to 1/8"
+  set incorrect_vtype [expr { 5  | (3 << 3)}]
+  gdb_test_no_output "set \$vtype = $incorrect_vtype"
+  gdb_test "stepi" ".*"                            "$the_proc: stepi after incorrect"
+  # kernel BUG: this should not match
+  gdb_test "print/ \$vtype" "= 0x8000000000000000" "$the_proc: ptraced vtype - after setting illegal mode"
+
+  gdb_breakpoint $srcfile:[gdb_get_line_number vect_test_vtype_read] temporary
+  gdb_continue_to_breakpoint "$the_proc: app vtype read"
+  gdb_test "print/x app_vtype" "= 0x8000000000000000" "$the_proc: app vtype- after setting illegal mode"
+  gdb_test "print/ \$vtype" "= 0x8000000000000000"    "$the_proc: ptraced vtype - still illegal"
+  gdb_test_no_output "set \$vtype = 0"                "$the_proc: legalizing vtype"
+
+  gdb_continue_to_breakpoint "$the_proc: vtype is legal again"
+  gdb_test "print app_vl" "= 0"           "$the_proc: app vl - after vtype legalized"
+  gdb_test "print app_vlenb" "= $VLENB"   "$the_proc: app vlenb - after vtype legalized"
+  # kernel BUG: this should match app_vl
+  gdb_test "print \$vl" "= 0"             "$the_proc: ptraced vl - after vtype legalizied"
+  gdb_test "print \$vtype" "= 0"          "$the_proc: ptraced vtype - after vtype legalized"
+  gdb_test_no_output "set \$vl = $VLENB"  "$the_proc: setting vl after vtype legalized"
+
+  gdb_continue_to_breakpoint "$the_proc: everything is legalized"
+  gdb_test "print app_vl" "= $VLENB"    "$the_proc: app vl - really legal app vl"
+  gdb_test "print app_vlenb" "= $VLENB" "$the_proc: app vlenb - really legal app vtype"
+  gdb_test "print \$vl" "= $VLENB"      "$the_proc: ptraced vl - really legal"
+  gdb_test "print \$vtype" "= 0"        "$the_proc: ptraced vtype - really legal"
+}
+
+proc test_vu_do_consistency_test {VLENB} {
+  global srcfile
+  gdb_breakpoint "$srcfile:[gdb_get_line_number workload_end]"
+
+  gdb_continue_to_breakpoint "warm up"
+
+  test_vu_consistency_vl_overflow $VLENB
+  test_vu_coherent_vl_lmul_downgrade $VLENB
+  test_vu_coherent_non_zero_vstart $VLENB
+  test_vu_consistency_incorrect_vtype $VLENB
+}
+
+proc prepare_vu_consistency_test {} {
+  global testfile
+  global srcfile
+
+  set compile_flags {}
+  lappend compile_flags debug
+  lappend compile_flags "additional_flags=-march=rv64gc"
+
+  if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+    return -1
+  }
+
+  if {![runto_main]} {
+    return -1
+  }
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_test_start]"
+  gdb_continue_to_breakpoint "vect_test_start"
+
+  return 0
+}
+
+if {[prepare_vu_consistency_test]} {
+  untested "could not initialize"
+  return -1
+}
+set vlenb [riscvlib_rvv_get_csr vlenb "$testfile"]
+test_vu_do_consistency_test $vlenb
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-ctx-print.c b/gdb/testsuite/gdb.arch/riscv-vu-ctx-print.c
new file mode 100644
index 00000000000..b947c7834ea
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-ctx-print.c
@@ -0,0 +1,106 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#include <vector>
+
+asm (".option arch, +v\n");
+
+enum VLMUL
+{
+  LMUL1 = 0,
+  LMUL2 = 1,
+  LMUL4 = 2,
+  LMUL8 = 3,
+  LMUL_F8 = 5,
+  LMUL_F4 = 6,
+  LMUL_F2 = 7
+};
+
+enum SEW
+{
+  SEW8 = 0,
+  SEW16 = 1,
+  SEW32 = 2,
+  SEW64 = 3,
+};
+
+unsigned
+do_vsetvli ()
+{
+  unsigned vl;
+  asm volatile ("vsetvli %[new_vl], x0, e8, m1, ta, ma"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  return vl;
+}
+
+unsigned
+do_vsetv (unsigned vl, VLMUL vlmul, SEW vsew, unsigned vta, unsigned vma)
+{
+  unsigned vtype
+      = (unsigned)vlmul | ((unsigned)vsew << 3) | (vta << 6) | (vma << 7);
+  asm volatile ("vsetvl %[new_vl], %[new_vl], %[vtype]"
+		: [new_vl] "+r"(vl)
+		: [vtype] "r"(vtype)
+		:);
+  return vl; /* vsetvl_done */
+}
+
+int STORAGE[64];
+
+void
+do_vector_stuff ()
+{
+  std::vector<VLMUL> vlmul = {
+    VLMUL::LMUL1,   VLMUL::LMUL2,   VLMUL::LMUL4,   VLMUL::LMUL8,
+    VLMUL::LMUL_F8, VLMUL::LMUL_F4, VLMUL::LMUL_F2,
+  };
+  std::vector<SEW> vsew = {
+    SEW::SEW8,
+    SEW::SEW16,
+    SEW::SEW32,
+    SEW::SEW64,
+  };
+  for (auto vlmul : vlmul)
+    for (auto sew : vsew)
+      for (int vta = 0; vta < 2; ++vta)
+	for (int vma = 0; vma < 2; ++vma)
+	  for (int vl = 1; vl < 3; ++vl)
+	    do_vsetv (vl, vlmul, sew, vta, vma);
+
+  asm volatile ("csrw vxrm, %[rnd_m]" : : [rnd_m] "i"(0) :);
+  asm volatile ("csrw vxrm, %[rnd_m]" : : [rnd_m] "i"(1) :);  /* vxrm_0 */
+  asm volatile ("csrw vxrm, %[rnd_m]" : : [rnd_m] "i"(2) :);  /* vxrm_1 */
+  asm volatile ("csrw vxrm, %[rnd_m]" : : [rnd_m] "i"(3) :);  /* vxrm_2 */
+  asm volatile ("csrw vxsat, %[vxsat]" : : [vxsat] "i"(1) :); /* vxrm_3 */
+  asm volatile ("csrw vxrm, %[rnd_m]" : : [rnd_m] "i"(0) :); /* vxrm_0_again */
+  unsigned vtype = -1;
+  unsigned vl = -1;
+  asm volatile ("vsetvl %[new_vl], %[new_vl], %[vtype]"
+		: [new_vl] "+r"(vl), [vtype] "=r"(vtype)
+		:
+		:); /* vcsr_done */
+}
+
+int
+main ()
+{
+  do_vsetvli ();
+  do_vector_stuff (); /* rvv_initialized */
+  return 0;	      /* do_vector_stuff_done */
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-ctx-print.exp b/gdb/testsuite/gdb.arch/riscv-vu-ctx-print.exp
new file mode 100644
index 00000000000..9c4c6079be6
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-ctx-print.exp
@@ -0,0 +1,107 @@
+# Copyright 2025 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/>.
+
+require {istarget "riscv*-*-*"}
+
+if {![riscv_support_rvv]} {
+  unsupported "RVV unsupported"
+  return
+}
+
+standard_testfile
+load_lib riscv64-rvv-lib.exp
+
+proc test_vu_ctx_printouts {VLENB} {
+  global testfile
+  global srcfile
+  global hex
+
+  array set vlmul { 0 1 1 2 2 4 3 8 7 1/2 6 1/4 5 1/8 }
+  array set vsew { 0 e8 1 e16 2 e32 3 e64 }
+  array set vta { 0 tu 1 ta }
+  array set vma { 0 mu 1 ma }
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vsetvl_done]"
+
+  foreach lmul [lsort -integer [array names vlmul]] {
+    foreach sew [lsort -integer [array names vsew]] {
+      foreach ta [lsort -integer [array names vta]] {
+        foreach ma [lsort -integer [array names vma]] {
+          foreach vl {1 2} {
+            set slmul $vlmul($lmul)
+            set ssew $vsew($sew)
+            set sta $vta($ta)
+            set sma $vma($ma)
+            set case_id "vlmul: $lmul, sew: $sew, ta: $ta, ma: $ma, vl: $vl"
+            gdb_continue_to_breakpoint "vsetvl_done lmul / $case_id"
+
+            if {![riscvlib_is_vlmul_vsew_legal $VLENB $lmul $sew]} {
+              set vtype_pattern "vill:1"
+            } else {
+              set vtype_pattern "$hex\tLMUL:$lmul \\($slmul\\) SEW:$sew \\($ssew\\) vta:$ta \\($sta\\) vma:$ma \\($sma\\) vill:0"
+            }
+            gdb_test "info reg vtype" "${vtype_pattern}" "info reg vtype: $case_id"
+            set fvl [riscvlib_get_allowed_vl $VLENB $lmul $sew $vl]
+            gdb_test "info reg vl" "^vl\\s+[format 0x%x $fvl]\t$fvl" "info reg vl: $case_id, fvl: $fvl"
+          }
+        }
+      }
+    }
+  }
+
+  foreach vxrm {0 1 2 3} {
+      gdb_breakpoint "$srcfile:[gdb_get_line_number vxrm_$vxrm]"
+      gdb_continue_to_breakpoint "vxrm_$vxrm"
+      set vcsr_value_hex [format 0x%x [expr { ($vxrm << 1) }]]
+      gdb_test "info reg vcsr" "^vcsr\\s+$vcsr_value_hex\tVXSAT:0 VXRM:$vxrm" "info reg vcsr: vxrm_$vxrm"
+  }
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vxrm_0_again]"
+  gdb_continue_to_breakpoint "vxrm_0_again"
+  gdb_test "info reg vcsr" "^vcsr\\s+0x7\tVXSAT:1 VXRM:3" "info reg vcsr: vxsat_1"
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vcsr_done]"
+  gdb_continue_to_breakpoint "vcsr_done"
+  gdb_test "info reg vcsr" "^vcsr\\s+0x1\tVXSAT:1 VXRM:0" "info reg vcsr: vxsat_1_vxrm0"
+}
+
+proc prepare_vu_printout_test {} {
+  global testfile
+  global srcfile
+
+  set compile_flags {}
+  lappend compile_flags debug
+  lappend compile_flags c++
+  lappend compile_flags "additional_flags=-march=rv64gc"
+
+  if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+    return -1
+  }
+
+  if {![runto_main]} {
+    return -1
+  }
+
+  return 0
+}
+
+if {[prepare_vu_printout_test]} {
+  untested "could not initialize"
+  return -1
+}
+gdb_breakpoint "$srcfile:[gdb_get_line_number rvv_initialized]"
+gdb_continue_to_breakpoint "rvv_initialized"
+set vlenb [riscvlib_rvv_get_csr vlenb "$testfile"]
+
+test_vu_ctx_printouts $vlenb
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-printout.c b/gdb/testsuite/gdb.arch/riscv-vu-printout.c
new file mode 100644
index 00000000000..c87f71d8ee2
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-printout.c
@@ -0,0 +1,69 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+#include <stdlib.h>
+#include <limits.h>
+
+asm (".option arch, +v\n");
+
+unsigned
+do_vlenb_read ()
+{
+  unsigned vlenb;
+  asm volatile ("csrr %[vlenb], vlenb" : [vlenb] "=r"(vlenb) : :);
+  return vlenb;
+}
+
+unsigned
+do_vsetvli ()
+{
+  unsigned vl;
+  asm volatile ("vsetvli %[new_vl], x0, e8, m8, tu, mu"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  return vl;
+}
+
+char *STORAGE;
+
+void
+do_vector_stuff ()
+{
+  unsigned vlenb_value = do_vlenb_read ();
+  STORAGE = (char *)calloc (1, vlenb_value * CHAR_BIT);
+  do_vsetvli ();
+  asm volatile ("vxor.vv v0, v0, v0");
+  asm volatile ("vxor.vv v8, v8, v8");
+  asm volatile ("vxor.vv v16, v16, v16");
+  asm volatile ("vxor.vv v24, v24, v24");
+  asm volatile ("vsetvli t0, x0, e8, m1, tu, mu" : : : "t0");
+  asm volatile ("vadd.vi v1, v1, 0x1");
+  asm volatile ("vadd.vi v2, v1, 0x2");
+  asm volatile ("vs1r.v v1, (%0)"
+		:
+		: "r"(STORAGE)
+		: "memory"); /* pre_vect_mem */
+  asm volatile ("vl1re8.v v2, (%0)" : : "r"(STORAGE) : "memory");
+}
+
+int
+main ()
+{
+  do_vector_stuff ();
+  return 0; /* post_vector_op */
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-printout.exp b/gdb/testsuite/gdb.arch/riscv-vu-printout.exp
new file mode 100644
index 00000000000..e2fd65f4d9d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-printout.exp
@@ -0,0 +1,92 @@
+# Copyright 2025 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/>.
+
+require {istarget "riscv*-*-*"}
+
+if {![riscv_support_rvv]} {
+  unsupported "RVV unsupported"
+  return
+}
+
+standard_testfile
+load_lib riscv64-rvv-lib.exp
+
+proc test_vu_printouts {VLENB} {
+  global srcfile
+
+  set vtype_pattern "0x0\tLMUL:0 \\(1\\) SEW:0 \\(e8\\) vta:0 \\(tu\\) vma:0 \\(mu\\) vill:0"
+  gdb_test "info reg vtype" "${vtype_pattern}" "printout info reg vtype"
+  gdb_test "info reg vcsr" "0x0\tVXSAT:0 VXRM:0" "printout info reg vcsr"
+  gdb_test "info reg vl" "[format 0x%x $VLENB]\t$VLENB" "printout info reg vl"
+  gdb_test "info reg vstart" "0x0\t0" "printout info reg vstart"
+  gdb_test "info reg vlenb" "[format 0x%x $VLENB]\t$VLENB" "printout info reg vlenb"
+
+  set zero_pattern [riscvlib_rvv_vreg_zero_pattern $VLENB]
+  gdb_test "print \$v0" ${zero_pattern} "printout print v0"
+  gdb_test "print \$v1" [riscvlib_rvv_vreg_1_pattern $VLENB] "printout print v1"
+  gdb_test "print \$v2" [riscvlib_rvv_vreg_3_pattern $VLENB] "printout print v2"
+  for {set i 3} {$i < 32} {incr i} {
+    gdb_test "print \$v${i}" ${zero_pattern} "printout print v${i}"
+  }
+
+  set vregs [capture_command_output "info registers vector" ""]
+  foreach {- regname} [regexp -all -inline -line {^(\w+)\s+} $vregs] {
+    incr vreg_arr($regname)
+  }
+  set expected_list { vtype vcsr vl vstart vlenb }
+  for {set i 0 } { $i < 32 } { incr i } {
+    lappend expected_list v$i
+  }
+  set s_expc_list [lsort $expected_list]
+  set s_vreg_list [lsort [array names vreg_arr]]
+  if {![string equal $s_expc_list $s_vreg_list]} {
+    fail "info registers vector (contents)"
+  }
+  foreach reg $expected_list {
+    if { $vreg_arr($reg) != 1 } {
+      fail "info registers vector has duplicated $reg"
+    } else {
+      pass "info register vector has $reg"
+    }
+  }
+}
+
+proc prepare_vu_printout_test {} {
+  global testfile
+  global srcfile
+
+  set compile_flags {}
+  lappend compile_flags debug
+  lappend compile_flags "additional_flags=-march=rv64gc"
+
+  if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+    return -1
+  }
+
+  if {![runto_main]} {
+    return -1
+  }
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number pre_vect_mem]"
+  gdb_continue_to_breakpoint "pre_vect_mem"
+  return 0
+}
+
+if {[prepare_vu_printout_test]} {
+  untested "could not initialize"
+  return -1
+}
+set vlenb [riscvlib_rvv_get_csr vlenb "$testfile"]
+test_vu_printouts $vlenb
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-rvv-unsupported.c b/gdb/testsuite/gdb.arch/riscv-vu-rvv-unsupported.c
new file mode 100644
index 00000000000..8a9284e5a5f
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-rvv-unsupported.c
@@ -0,0 +1,23 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+int
+main ()
+{
+  int a = 42;
+  return 0; /* break 2 */
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-rvv-unsupported.exp b/gdb/testsuite/gdb.arch/riscv-vu-rvv-unsupported.exp
new file mode 100644
index 00000000000..7205ec8d810
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-rvv-unsupported.exp
@@ -0,0 +1,46 @@
+# Copyright 2025 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/>.
+
+require {istarget "riscv*-*-*"}
+
+if {[riscv_support_rvv]} {
+  unsupported "need to run on targets without RVV support"
+  return
+}
+
+standard_testfile
+
+set compile_flags {"debug"}
+lappend compile_flags "additional_flags=-march=rv64gcv"
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+  return -1
+}
+
+if {![runto_main]} {
+  return -1
+}
+
+gdb_breakpoint "$srcfile:[gdb_get_line_number "break 2"]"
+gdb_continue_to_breakpoint "break 2"
+
+gdb_test "print a" " = 42"
+
+set a0_val 42
+set a0_hex_val 0x[format %x $a0_val]
+gdb_test_no_output "set \$a0 = $a0_val"
+gdb_test "info reg a0" "a0\[ \t\]+$a0_hex_val\[ \t\]+$a0_val"
+
+gdb_test "info reg v0" "Invalid register `v0'"
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-rwr.c b/gdb/testsuite/gdb.arch/riscv-vu-rwr.c
new file mode 100644
index 00000000000..05874b1fdb3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-rwr.c
@@ -0,0 +1,62 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+asm (".option arch, +v\n");
+
+#include <stdlib.h>
+#include <limits.h>
+
+unsigned
+do_vlenb_read ()
+{
+  unsigned vlenb;
+  asm volatile ("csrr %[vlenb], vlenb" : [vlenb] "=r"(vlenb) : :);
+  return vlenb;
+}
+
+void
+reset_vu ()
+{
+  unsigned vl;
+  asm volatile ("vsetvli %[new_vl], x0, e8, m8, ta, ma"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  asm volatile ("vxor.vv v0, v0, v0\n"
+		"vxor.vv v8, v8, v8\n"
+		"vxor.vv v16, v16, v16\n"
+		"vxor.vv v24, v24, v24\n"
+		"vadd.vi v0, v0, 15\n"
+		"vadd.vi v8, v8, 15\n"
+		"vadd.vi v16, v16, 15\n"
+		"vadd.vi v24, v24, 15\n"
+		"csrrsi zero, vxrm, 3\n"
+		"csrrsi zero, vxsat, 1\n");
+  asm volatile ("nop"); /* vu_reset_end */
+}
+
+int
+main ()
+{
+  unsigned vlenb_value = do_vlenb_read ();
+  (void)vlenb_value;
+  reset_vu ();
+  /* vect_test_start */
+  for (int i = 0; i < 777; ++i)
+    reset_vu ();
+  return 0; /* vect_test_end */
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-rwr.exp b/gdb/testsuite/gdb.arch/riscv-vu-rwr.exp
new file mode 100644
index 00000000000..ba8269e6b98
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-rwr.exp
@@ -0,0 +1,163 @@
+# Copyright 2025 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/>.
+
+require {istarget "riscv*-*-*"}
+
+if {![riscv_support_rvv]} {
+  unsupported "RVV unsupported"
+  return
+}
+
+standard_testfile
+load_lib riscv64-rvv-lib.exp
+
+proc test_vu_rwr_get_default_vtype_pattern {} {
+  return "0xc3\tLMUL:3 \\(8\\) SEW:0 \\(e8\\) vta:1 \\(ta\\) vma:1 \\(ma\\) vill:0"
+}
+proc test_vu_rwr_get_zero_vtype_pattern {} {
+  return "0x0\tLMUL:0 \\(1\\) SEW:0 \\(e8\\) vta:0 \\(tu\\) vma:0 \\(mu\\) vill:0"
+}
+proc test_vu_rwr_get_default_vl {VLENB} {
+  return [expr $VLENB * 8]
+}
+
+proc test_vu_rwr_is_reg_excluded {excluded reg} {
+  return [expr { [lsearch -exact $excluded $reg] != -1 }]
+}
+
+proc test_vu_rwr_csr_scan { VLENB test_info exclude } {
+  set the_proc [lindex [info level 0] 0]
+  if {![test_vu_rwr_is_reg_excluded $exclude "vtype"]} {
+    set vtype_pattern [test_vu_rwr_get_default_vtype_pattern]
+    gdb_test "info reg vtype" $vtype_pattern "$the_proc: info reg vtype - $test_info"
+  }
+  if {![test_vu_rwr_is_reg_excluded $exclude "vcsr"]} {
+    gdb_test "info reg vcsr" "0x7\tVXSAT:1 VXRM:3" "$the_proc: info reg vcsr - $test_info"
+  }
+  if {![test_vu_rwr_is_reg_excluded $exclude "vl"]} {
+    set vl [test_vu_rwr_get_default_vl $VLENB]
+    gdb_test "info reg vl" "[format 0x%x $vl]\t$vl" "$the_proc: info reg vl - $test_info"
+  }
+  if {![test_vu_rwr_is_reg_excluded $exclude "vstart"]} {
+    gdb_test "info reg vstart" "0x0\t0" "$the_proc: info reg vstart - $test_info"
+  }
+  if {![test_vu_rwr_is_reg_excluded $exclude "vlenb"]} {
+    gdb_test "info reg vlenb" "[format 0x%x $VLENB]\t$VLENB" "$the_proc: info reg vlenb - $test_info"
+  }
+}
+
+proc test_vu_rwr_scan_context {VLENB test_info exclude} {
+  test_vu_rwr_csr_scan $VLENB $test_info $exclude
+  set 15_pattern [riscvlib_rvv_vreg_15_pattern $VLENB]
+  set the_proc [lindex [info level 0] 0]
+
+  for {set i 0} {$i < 32} {incr i} {
+    if { $exclude eq "v$i" } {
+      continue
+    }
+    gdb_test "print \$v$i" ${15_pattern} "$the_proc: print v$i - $test_info"
+  }
+}
+
+proc test_vu_rwr {VLENB} {
+  global srcfile
+
+  set the_proc [lindex [info level 0] 0]
+  set i8_fmt [riscvlib_rvv_vreg_fmt8]
+  test_vu_rwr_scan_context $VLENB "initial-scan" ""
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vu_reset_end]"
+  gdb_continue_to_breakpoint "vu_reset_end"
+
+  for {set i 0} {$i < 32} {incr i} {
+    gdb_continue_to_breakpoint "vu_reset_end - v$i"
+    set vreg_contents {}
+    for { set j 0} {$j < $VLENB } { incr j } {
+      gdb_test_no_output "set \$v$i.${i8_fmt}\[$j\] = $j"
+      lappend vreg_contents $j
+    }
+    test_vu_rwr_scan_context $VLENB "v$i update-scan" "v$i"
+
+    set vreg_pattern [join $vreg_contents ", "]
+    gdb_test "print \$v$i" "\\\{$i8_fmt = \\{$vreg_pattern\\},.+" "print v$i - after modification"
+  }
+
+  gdb_continue_to_breakpoint "vu_reset_end - vtype"
+  gdb_test_no_output "set \$vtype = 0"
+  test_vu_rwr_scan_context $VLENB "vtype update-scan" {vtype vl}
+  set zero_vtype_pattern [test_vu_rwr_get_zero_vtype_pattern]
+  set default_vl [test_vu_rwr_get_default_vl $VLENB]
+  gdb_test "info reg vtype" $zero_vtype_pattern "$the_proc: info reg vtype - csr update"
+  gdb_test "info reg vl" "[format 0x%x $default_vl]\t$default_vl" "$the_proc: info reg vl - vl after vtype update"
+  gdb_test "stepi" ".*" "$the_proc: stepi after vtype update"
+  gdb_test "info reg vtype" $zero_vtype_pattern "$the_proc: info reg vtype - csr update and stepi"
+  gdb_test "info reg vl" "[format 0x%x $default_vl]\t$default_vl" "$the_proc: info reg vl - vl after vtype update and stepi"
+
+  gdb_continue_to_breakpoint "vu_reset_end - vcsr"
+  gdb_test_no_output "set \$vcsr = 0"
+  test_vu_rwr_scan_context $VLENB "vcsr update-scan" "vcsr"
+  gdb_test "info reg vcsr" "0x0\tVXSAT:0 VXRM:0" "$the_proc: info reg vcsr - csr update"
+  gdb_test "stepi" ".*" "$the_proc: stepi after vcsr update"
+  gdb_test "info reg vcsr" "0x0\tVXSAT:0 VXRM:0" "$the_proc: info reg vcsr - after stepi"
+
+  gdb_continue_to_breakpoint "vu_reset_end - vl"
+  gdb_test_no_output "set \$vl = 2"
+  test_vu_rwr_scan_context $VLENB "vl update-scan" "vl"
+  gdb_test "info reg vl" "[format 0x%x 2]\t2" "$the_proc: info reg vl - csr update"
+  gdb_test "stepi" ".*" "$the_proc: stepi after vl update"
+  gdb_test "info reg vl" "0x2\t2" "$the_proc: info reg vl - after stepi"
+
+  gdb_continue_to_breakpoint "vu_reset_end - vstart"
+  gdb_test_no_output "set \$vstart = 2"
+  test_vu_rwr_scan_context $VLENB "vstart update-scan" "vstart"
+  gdb_test "info reg vstart" "0x2\t2" "$the_proc: info reg vstart - vsart update"
+  gdb_test "stepi" ".*" "$the_proc: stepi after vstart update"
+  gdb_test "info reg vstart" "0x2\t2" "$the_proc: info reg vstart - after stepi"
+
+  gdb_continue_to_breakpoint "vu_reset_end - vlenb"
+  gdb_test_no_output "set \$vlenb = 0"
+  test_vu_rwr_scan_context $VLENB "$the_proc: vlenb update-scan" ""
+  gdb_test "stepi" ".*" "$the_proc: stepi after vlenb update"
+  test_vu_rwr_scan_context $VLENB "$the_proc: final scan after stepi" ""
+}
+
+proc prepare_vu_rwr_test {} {
+  global testfile
+  global srcfile
+
+  set compile_flags {}
+  lappend compile_flags debug
+  lappend compile_flags "additional_flags=-march=rv64gc"
+
+  if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+    return -1
+  }
+
+  if {![runto_main]} {
+    return -1
+  }
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_test_start]"
+  gdb_continue_to_breakpoint "vect_test_start"
+
+  return 0
+}
+
+if {[prepare_vu_rwr_test]} {
+  untested "could not initialize"
+  return -1
+}
+set vlenb [riscvlib_rvv_get_csr vlenb "$testfile"]
+test_vu_rwr $vlenb
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-side-effects.c b/gdb/testsuite/gdb.arch/riscv-vu-side-effects.c
new file mode 100644
index 00000000000..138d2895dad
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-side-effects.c
@@ -0,0 +1,86 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2025 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/>.  */
+
+asm (".option arch, +v\n");
+
+#include <stdlib.h>
+#include <limits.h>
+
+unsigned
+do_vlenb_read ()
+{
+  unsigned vlenb;
+  asm volatile ("csrr %[vlenb], vlenb" : [vlenb] "=r"(vlenb) : :);
+  return vlenb;
+}
+
+char *STORAGE;
+
+void
+zero_out_vu ()
+{
+  unsigned vl;
+  asm volatile ("vsetvli %[new_vl], x0, e8, m8, tu, mu"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  asm volatile ("vxor.vv v0, v0, v0");
+  asm volatile ("vxor.vv v8, v8, v8");
+  asm volatile ("vxor.vv v16, v16, v16");
+  asm volatile ("vxor.vv v24, v24, v24");
+}
+
+void
+do_wide_operations ()
+{
+  unsigned vl;
+  asm volatile ("vsetvli %[new_vl], x0, e8, m8, tu, mu"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  asm volatile ("vadd.vi v0, v0, 0x1");	 /* vect_wide_op_start */
+  asm volatile ("vadd.vi v24, v0, 0x2"); /* vect_op_v0_add1 */
+  asm volatile ("vadd.vi v16, v8, 0x2"); /* vect_op_v24_v0_add2 */
+  asm volatile ("vadd.vi v10, v9, 0x3"); /* vect_op_v16_v8_add2 */
+  asm volatile ("nop");			 /* vect_wide_op_end */
+}
+
+void
+do_controlled_vadd ()
+{
+  unsigned vl;
+  asm volatile ("vsetvli %[new_vl], x0, e8, m1, tu, mu"
+		: [new_vl] "=r"(vl)
+		:
+		:);
+  asm volatile ("vadd.vv v2, v1, v0"); /* vect_control_vadd_start */
+  asm volatile ("nop");		       /* controlled_vadd_done */
+}
+
+int
+main ()
+{
+  unsigned vlenb_value = do_vlenb_read ();
+  STORAGE = (char *)calloc (1, vlenb_value * CHAR_BIT);
+
+  zero_out_vu ();
+  /* vect_test_start */
+  do_controlled_vadd ();
+  zero_out_vu ();
+  do_wide_operations ();
+  return 0; /* vect_test_end */
+}
diff --git a/gdb/testsuite/gdb.arch/riscv-vu-side-effects.exp b/gdb/testsuite/gdb.arch/riscv-vu-side-effects.exp
new file mode 100644
index 00000000000..e96dd421db8
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/riscv-vu-side-effects.exp
@@ -0,0 +1,162 @@
+# Copyright 2025 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/>.
+
+require {istarget "riscv*-*-*"}
+
+if {![riscv_support_rvv]} {
+  unsupported "RVV unsupported"
+  return
+}
+
+standard_testfile
+load_lib riscv64-rvv-lib.exp
+
+proc test_vu_controlled_add {VLENB} {
+  global srcfile
+
+  set i8_fmt [riscvlib_rvv_vreg_fmt8]
+  set zero_pattern [riscvlib_rvv_vreg_zero_pattern $VLENB]
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_control_vadd_start]"
+  gdb_continue_to_breakpoint "vect_control_vadd_start"
+
+  set the_proc [lindex [info level 0] 0]
+
+  # ensure that state is pristine
+  for { set vregn 0 } { $vregn < 32 } { incr vregn } {
+    gdb_test "print \$v${vregn}" ${zero_pattern} "$the_proc: print v${vregn} - pristine"
+  }
+
+  # update v0
+  for {set i 0} {$i < $VLENB} {incr i} {
+    set val [expr {$i % 256 - 128}]
+    gdb_test_no_output "set \$v0.${i8_fmt}\[$i\] = $val"
+    lappend v0_contents $val
+  }
+
+  # update v1
+  for {set i 0} {$i < $VLENB} {incr i} {
+    set val [expr {($i + 7) % 256 - 128}]
+    gdb_test_no_output "set \$v1.${i8_fmt}\[$i\] = $val"
+    lappend v1_contents $val
+  }
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number controlled_vadd_done]"
+  # execute addition operation, v3 register must be updated to summ of v0 and v1
+  gdb_continue_to_breakpoint "controlled_vadd_done"
+
+  set v0_pattern [join $v0_contents ", "]
+  gdb_test "print \$v0" "\\\{$i8_fmt = \\{$v0_pattern\\},.+" "$the_proc: print v0 - after add"
+
+  set v1_pattern [join $v1_contents ", "]
+  gdb_test "print \$v1" "\\\{$i8_fmt = \\{$v1_pattern\\},.+" "$the_proc: print v1 - after add"
+  for {set i 0} {$i < $VLENB} {incr i} {
+    lappend v2_contents [expr {($i + $i + 7 + 128) % 256 - 128}]
+  }
+  set v2_pattern [join $v2_contents ", "]
+  gdb_test "print \$v2" "\\\{$i8_fmt = \\{$v2_pattern\\},.+" "$the_proc: print v2 - add result"
+  for { set vregn 3 } { $vregn < 32 } { incr vregn } {
+    gdb_test "print \$v${vregn}" ${zero_pattern} "$the_proc: print v${vregn} - pristine after add"
+  }
+}
+
+proc test_vu_wide_operations {VLENB} {
+  global srcfile
+
+  set i8_fmt [riscvlib_rvv_vreg_fmt8]
+  set the_proc [lindex [info level 0] 0]
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_wide_op_start]"
+  gdb_continue_to_breakpoint "vect_wide_op_start"
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_op_v0_add1]"
+  gdb_continue_to_breakpoint "vect_op_v0_add1"
+
+  gdb_test_no_output "set \$vl = 2"
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_op_v24_v0_add2]"
+  gdb_continue_to_breakpoint "vect_op_v24_v0_add2"
+
+  for {set i 0} {$i < $VLENB} {incr i} {
+    gdb_test_no_output "set \$v8.${i8_fmt}\[$i\] = $i"
+    lappend v8_contents $i
+  }
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_op_v16_v8_add2]"
+  gdb_continue_to_breakpoint "vect_op_v16_v8_add2"
+
+  gdb_test_no_output "set \$vtype = 0"
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_wide_op_end]"
+  gdb_continue_to_breakpoint "vect_wide_op_end"
+
+  set vtype_pattern "0x0\tLMUL:0 \\(1\\) SEW:0 \\(e8\\) vta:0 \\(tu\\) vma:0 \\(mu\\) vill:0"
+  gdb_test "info reg vtype" "${vtype_pattern}" "$the_proc: info reg vtype - end state"
+  gdb_test "info reg vcsr" "0x0\tVXSAT:0 VXRM:0" "$the_proc: info reg vcsr - end state"
+  gdb_test "info reg vl" "[format 0x%x 2]\t2" "$the_proc: info reg vl - end state"
+  gdb_test "info reg vstart" "0x0\t0" "$the_proc: info reg vstart - end state"
+  gdb_test "info reg vlenb" "[format 0x%x $VLENB]\t$VLENB" "$the_proc: info reg vlenb - end state"
+
+  set zero_pattern [riscvlib_rvv_vreg_zero_pattern $VLENB]
+  set ones_pattern [riscvlib_rvv_vreg_1_pattern $VLENB]
+  foreach vregn { 0 1 2 3 4 5 6 7 } {
+    gdb_test "print \$v${vregn}" ${ones_pattern} "$the_proc: print v${vregn} - end state"
+  }
+  foreach vregn { 9 11 12 13 14 15 17 18 19 20 21 22 23 25 26 27 28 29 30 31} {
+    gdb_test "print \$v${vregn}" ${zero_pattern} "$the_proc: print v${vregn} - end state"
+  }
+  set xn_zeroes_rep [riscvlib_rvv_vreg_component_pattern [expr {$VLENB - 2}] 0]
+  # for VLENB = 16 we have:
+  # v10  \{i8 = {3, 3, 0 <repeats 14 times>} ...
+  # v16  \{i8 = {2, 3, 0 <repeats 14 times>} ...
+  # v24  \{i8 = {3, 3, 0 <repeats 14 times>} ...
+  foreach vregn { 10 24 } {
+    gdb_test "print \$v${vregn}" "\\\{$i8_fmt = \\{3, 3, ${xn_zeroes_rep}\\},.+" "$the_proc: print v${vregn} - end state"
+  }
+  gdb_test "print \$v16" "\\\{$i8_fmt = \\{2, 3, ${xn_zeroes_rep}\\},.+" "$the_proc: print v16 - end state"
+
+  # v8   \{i8 = {0, 1, 2, ...} ....
+  set v8_pattern [join $v8_contents ", "]
+  gdb_test "print \$v8" "\\\{$i8_fmt = \\{$v8_pattern\\},.+" "$the_proc: print v8 - end state"
+}
+
+proc prepare_vu_rw_test {} {
+  global testfile
+  global srcfile
+
+  set compile_flags {}
+  lappend compile_flags debug
+  lappend compile_flags "additional_flags=-march=rv64gc"
+
+  if {[prepare_for_testing "failed to prepare" $testfile $srcfile $compile_flags]} {
+    return -1
+  }
+
+  if {![runto_main]} {
+    return -1
+  }
+
+  gdb_breakpoint "$srcfile:[gdb_get_line_number vect_test_start]"
+  gdb_continue_to_breakpoint "vect_test_start"
+
+  return 0
+}
+
+if {[prepare_vu_rw_test]} {
+  untested "could not initialize"
+  return -1
+}
+set vlenb [riscvlib_rvv_get_csr vlenb "$testfile"]
+test_vu_controlled_add $vlenb
+test_vu_wide_operations $vlenb
diff --git a/gdb/testsuite/lib/riscv64-rvv-lib.exp b/gdb/testsuite/lib/riscv64-rvv-lib.exp
new file mode 100644
index 00000000000..ada5a9c052d
--- /dev/null
+++ b/gdb/testsuite/lib/riscv64-rvv-lib.exp
@@ -0,0 +1,166 @@
+proc riscvlib_is_vlmul_vsew_legal {VLENB vlmul vsew} {
+  # vlmul == 5 => 1/8
+  # vlmul == 6 => 1/4
+  # vlmul == 7 => 1/2
+  set sew [expr {1 << ($vsew + 3)}]
+  if {$vlmul > 4} {
+    set lmul_modifier [expr {1 << (8 - $vlmul)}]
+    set required_vlen [expr {$sew * $lmul_modifier}]
+    set vlen [expr {$VLENB * 8}]
+    return [expr {$vlen >= $required_vlen}];
+  }
+  if {$vlmul < 4} {
+    set lmul_modifier [expr {1 << $vlmul}]
+    set required_vlen $sew
+    set vlen [expr {$VLENB * 8 * $lmul_modifier}]
+    return [expr {$vlen >= $required_vlen}]
+  }
+
+  return 0;
+}
+
+proc riscvlib_get_allowed_vl {VLENB vlmul vsew vl} {
+  # vlmul == 5 => 1/8
+  # vlmul == 6 => 1/4
+  # vlmul == 7 => 1/2
+  # dummy way to filter-out illegal cases
+  if {![riscvlib_is_vlmul_vsew_legal $VLENB $vlmul $vsew]} {
+    return 0
+  }
+  set sew [expr {1 << ($vsew + 3)}]
+  set vlen [expr {$VLENB * 8}]
+  set vlmax 0
+
+  if {$vlmul > 4} {
+    set lmul_modifier [expr {1 << (8 - $vlmul)}]
+    set vlmax [expr {$vlen / ($lmul_modifier * $sew)}]
+  }
+
+  if {$vlmul < 4} {
+    set lmul_modifier [expr {1 << $vlmul}]
+    set vlmax [expr {$vlen * $lmul_modifier / $sew}]
+  }
+
+  if {$vl > $vlmax} {
+    return $vlmax
+  }
+
+  return $vl
+}
+
+proc riscvlib_rvv_get_csr {name test_id} {
+  global hex
+  global decimal
+  global gdb_prompt
+  global gdb_test_name
+
+  gdb_test_multiple "info registers $name" "" {
+    -re "^info registers\[^\r\n\]+\r\n" {
+      exp_continue
+    }
+    -re "^$name\\s+(${hex})\\s+\[^\n]+\r\n" {
+      set value [expr {$expect_out(1,string)}]
+      exp_continue
+    }
+    -re "^$gdb_prompt $" {
+      pass "$gdb_test_name $test_id"
+    }
+  }
+  return $value
+}
+
+proc riscvlib_rvv_vreg_fmt8 {} {
+  return i8
+}
+proc riscvlib_rvv_vreg_fmt16 {} {
+  return i16
+}
+proc riscvlib_rvv_vreg_fmt32 {} {
+  return i32
+}
+proc riscvlib_rvv_vreg_fmt64 {} {
+  return i64
+}
+
+proc riscvlib_rvv_vreg_print_pattern { i8 i16 i32 i64 half f32 f64} {
+  set I8_FMT [riscvlib_rvv_vreg_fmt8]
+  set I16_FMT [riscvlib_rvv_vreg_fmt16]
+  set I32_FMT [riscvlib_rvv_vreg_fmt32]
+  set I64_FMT [riscvlib_rvv_vreg_fmt64]
+  set HALF_FMT half
+  set F32_FMT f32
+  set F64_FMT f64
+  return [join [list \
+    "\\\{${I8_FMT} = \\{$i8\\}" \
+    "${I16_FMT} = \\{$i16\\}" \
+    "${I32_FMT} = \\{$i32\\}" \
+    "${I64_FMT} = \\{$i64\\}" \
+    "${HALF_FMT} = \\{$half\\}" \
+    "${F32_FMT} = \\{$f32\\}" \
+    "${F64_FMT} = \\{$f64\\}\\\}" \
+  ] ", "]
+}
+
+proc riscvlib_rvv_vreg_component_pattern {repeat_count symbol {collapse_allowed 1}} {
+  if { $collapse_allowed } {
+    if { $repeat_count > 8 } {
+      return "$symbol <repeats $repeat_count times>"
+    }
+  }
+  return [join [lrepeat $repeat_count $symbol] ", "]
+}
+
+proc riscvlib_rvv_vreg_zero_pattern {vlenb} {
+  set zero_symbol 0
+  set pattern [list \
+      [riscvlib_rvv_vreg_component_pattern $vlenb $zero_symbol] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 2 }] $zero_symbol] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 4 }] $zero_symbol] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 8 }] $zero_symbol] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 2 }] $zero_symbol] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 4 }] $zero_symbol] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 8 }] $zero_symbol] \
+  ]
+  return [riscvlib_rvv_vreg_print_pattern {*}$pattern]
+}
+
+proc riscvlib_rvv_vreg_1_pattern {vlenb} {
+  set pattern [list \
+      [riscvlib_rvv_vreg_component_pattern $vlenb 1] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 2 }] 257] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 4 }] 16843009] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 8 }] 72340172838076673] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 2 }] 1.5318e-05] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 4 }] 2.36942783e-38] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 8 }] 7.7486041854893479e-304] \
+  ]
+  return [riscvlib_rvv_vreg_print_pattern {*}$pattern]
+}
+
+proc riscvlib_rvv_vreg_3_pattern {vlenb} {
+  set zero_symbol 0
+  set pattern [list \
+      [riscvlib_rvv_vreg_component_pattern $vlenb 3] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 2 }] 771] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 4 }] 50529027] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 8 }] 217020518514230019] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 2 }] 4.5955e-05] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 4 }] 3.85008973e-37] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 8 }] 3.7209743448696002e-294] \
+  ]
+  return [riscvlib_rvv_vreg_print_pattern {*}$pattern]
+}
+
+proc riscvlib_rvv_vreg_15_pattern {vlenb} {
+  set zero_symbol 0
+  set pattern [list \
+      [riscvlib_rvv_vreg_component_pattern $vlenb 15] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 2 }] 3855] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 4 }] 252645135] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 8 }] 1085102592571150095] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 2 }] 0.00043082] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 4 }] 7.05334452e-30] \
+      [riscvlib_rvv_vreg_component_pattern [expr { $vlenb / 8 }] 3.8157368271180168e-236] \
+  ]
+  return [riscvlib_rvv_vreg_print_pattern {*}$pattern]
+}
-- 
2.43.0


  reply	other threads:[~2025-11-07 16:56 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-07 16:55 [PATCH 1/2] RISC-V Vector Extension Support Kirill Radkin
2025-11-07 16:55 ` Kirill Radkin [this message]
2026-04-13  4:22 [PATCH 2/2] RISC-V Vector Extension Support Testing Jerry Zhang Jian

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=20251107165534.1688124-2-kirill.radkin@syntacore.com \
    --to=kirill.radkin@syntacore.com \
    --cc=gdb-patches@sourceware.org \
    /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