Enhance the RISC-V GDB stub to support viewing vector registers in
multiple data type formats. This allows GDB users to inspect vector
register contents as different element types.
New type views using GDB builtin type names:
- Integer types: uint8, int8, uint16, int16, uint32, int32,
uint64, int64, uint128, int128
- Float types (conditionally enabled based on extensions):
- fp64 (Zve64d)
- fp32 (Zve32f)
- fp16 (Zvfhmin)
- bf16 (Zvfbfmin)
Backward-compatible aliases are preserved:
- b, s, w, l, q
Example GDB usage:
(gdb) print $v0.uint32
(gdb) print $v0.f32
(gdb) print $v0.w
Signed-off-by: Jerry Zhang Jian <[email protected]>
---
target/riscv/gdbstub.c | 120 +++++++++++++++++++++++++++++++----------
1 file changed, 92 insertions(+), 28 deletions(-)
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 1934f919c0..89a3700508 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -21,30 +21,24 @@
#include "gdbstub/helpers.h"
#include "cpu.h"
-struct TypeSize {
- const char *gdb_type;
- const char *id;
- int size;
- const char suffix;
+/*
+ * Vector lane type definitions for GDB target description.
+ * Uses GDB's builtin type names (uint8, int8, ieee_half, etc.)
+ */
+enum RVVExtension {
+ RVV_EXT_NONE = 0, /* Zve32x (checked at call site) */
+ RVV_EXT_ZVE64X, /* 64-bit integer elements */
+ RVV_EXT_ZVE64D, /* Double-precision float */
+ RVV_EXT_ZVE32F, /* Single-precision float */
+ RVV_EXT_ZVFHMIN, /* Half-precision float */
+ RVV_EXT_ZVFBFMIN, /* BFloat16 */
};
-static const struct TypeSize vec_lanes[] = {
- /* quads */
- { "uint128", "quads", 128, 'q' },
- /* 64 bit */
- { "uint64", "longs", 64, 'l' },
- /* 32 bit */
- { "uint32", "words", 32, 'w' },
- /* 16 bit */
- { "uint16", "shorts", 16, 's' },
- /*
- * TODO: currently there is no reliable way of telling
- * if the remote gdb actually understands ieee_half so
- * we don't expose it in the target description for now.
- * { "ieee_half", 16, 'h', 'f' },
- */
- /* bytes */
- { "uint8", "bytes", 8, 'b' },
+struct TypeSize {
+ const char *gdb_type; /* GDB builtin type name */
+ const char *name; /* Short name for union field (NULL = use
gdb_type) */
+ int size; /* Element size in bits */
+ enum RVVExtension required; /* Required extension, RVV_EXT_NONE if always
enabled */
};
int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
@@ -300,6 +294,53 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState
*cs, int base_reg)
return &cpu->dyn_csr_feature;
}
+/*
+ * Vector lane types using GDB's builtin type names.
+ * Float types are conditionally included based on extension availability.
+ */
+static const struct TypeSize vec_lanes[] = {
+ /* 128 bit - requires Zve64x */
+ { "uint128", NULL, 128, RVV_EXT_ZVE64X },
+ { "int128", NULL, 128, RVV_EXT_ZVE64X },
+ /* 64 bit - requires Zve64x */
+ { "uint64", NULL, 64, RVV_EXT_ZVE64X },
+ { "int64", NULL, 64, RVV_EXT_ZVE64X },
+ { "ieee_double", "fp64", 64, RVV_EXT_ZVE64D },
+ /* 32 bit */
+ { "uint32", NULL, 32, RVV_EXT_NONE },
+ { "int32", NULL, 32, RVV_EXT_NONE },
+ { "ieee_single", "fp32", 32, RVV_EXT_ZVE32F },
+ /* 16 bit */
+ { "uint16", NULL, 16, RVV_EXT_NONE },
+ { "int16", NULL, 16, RVV_EXT_NONE },
+ { "ieee_half", "fp16", 16, RVV_EXT_ZVFHMIN },
+ { "bfloat16", "bf16", 16, RVV_EXT_ZVFBFMIN },
+ /* 8 bit */
+ { "uint8", NULL, 8, RVV_EXT_NONE },
+ { "int8", NULL, 8, RVV_EXT_NONE },
+};
+
+/* Check if a vector lane type should be included based on CPU extensions */
+static bool riscv_gdb_vec_lane_enabled(RISCVCPU *cpu, const struct TypeSize
*ts)
+{
+ switch (ts->required) {
+ case RVV_EXT_NONE:
+ return true;
+ case RVV_EXT_ZVE64X:
+ return cpu->cfg.ext_zve64x;
+ case RVV_EXT_ZVE64D:
+ return cpu->cfg.ext_zve64d;
+ case RVV_EXT_ZVE32F:
+ return cpu->cfg.ext_zve32f;
+ case RVV_EXT_ZVFHMIN:
+ return cpu->cfg.ext_zvfhmin;
+ case RVV_EXT_ZVFBFMIN:
+ return cpu->cfg.ext_zvfbfmin;
+ default:
+ return false;
+ }
+}
+
static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
{
RISCVCPU *cpu = RISCV_CPU(cs);
@@ -311,21 +352,44 @@ static GDBFeature
*ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
"org.gnu.gdb.riscv.vector", "riscv-vector.xml",
base_reg);
- /* First define types and totals in a whole VL */
+ /* Define vector types for each lane type */
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
- int count = bitsize / vec_lanes[i].size;
+ const struct TypeSize *ts = &vec_lanes[i];
+ if (!riscv_gdb_vec_lane_enabled(cpu, ts)) {
+ continue;
+ }
gdb_feature_builder_append_tag(
&builder, "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
- vec_lanes[i].id, vec_lanes[i].gdb_type, count);
+ ts->gdb_type, ts->gdb_type, bitsize / ts->size);
}
- /* Define unions */
+ /* Create a single flat union with all type views */
gdb_feature_builder_append_tag(&builder, "<union id=\"riscv_vector\">");
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
+ const struct TypeSize *ts = &vec_lanes[i];
+ const char *name = ts->name ? ts->name : ts->gdb_type;
+ if (!riscv_gdb_vec_lane_enabled(cpu, ts)) {
+ continue;
+ }
gdb_feature_builder_append_tag(&builder,
- "<field name=\"%c\" type=\"%s\"/>",
- vec_lanes[i].suffix, vec_lanes[i].id);
+ "<field name=\"%s\" type=\"%s\"/>",
+ name, ts->gdb_type);
}
+
+ /* Add backward-compatible aliases for unsigned types */
+ gdb_feature_builder_append_tag(&builder,
+ "<field name=\"b\" type=\"uint8\"/>");
+ gdb_feature_builder_append_tag(&builder,
+ "<field name=\"s\" type=\"uint16\"/>");
+ gdb_feature_builder_append_tag(&builder,
+ "<field name=\"w\" type=\"uint32\"/>");
+ if (cpu->cfg.ext_zve64x) {
+ gdb_feature_builder_append_tag(&builder,
+ "<field name=\"l\" type=\"uint64\"/>");
+ gdb_feature_builder_append_tag(&builder,
+ "<field name=\"q\" type=\"uint128\"/>");
+ }
+
gdb_feature_builder_append_tag(&builder, "</union>");
/* Define vector registers */
--
2.51.0