diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index 866595b4f1..a8fff2a3d0 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -195,22 +195,17 @@ static const struct TypeSize vec_lanes[] = { { "uint128", 128, 'q', 'u' }, { "int128", 128, 'q', 's' }, /* 64 bit */ + { "ieee_double", 64, 'd', 'f' }, { "uint64", 64, 'd', 'u' }, { "int64", 64, 'd', 's' }, - { "ieee_double", 64, 'd', 'f' }, /* 32 bit */ + { "ieee_single", 32, 's', 'f' }, { "uint32", 32, 's', 'u' }, { "int32", 32, 's', 's' }, - { "ieee_single", 32, 's', 'f' }, /* 16 bit */ + { "ieee_half", 16, 'h', 'f' }, { "uint16", 16, 'h', 'u' }, { "int16", 16, 'h', '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", 8, 'b', 'u' }, { "int8", 8, 'b', 's' }, @@ -223,17 +218,16 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg) GString *s = g_string_new(NULL); DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml; g_autoptr(GString) ts = g_string_new(""); - int i, bits, reg_width = (cpu->sve_max_vq * 128); + int i, j, bits, reg_width = (cpu->sve_max_vq * 128); info->num = 0; g_string_printf(s, ""); g_string_append_printf(s, ""); - g_string_append_printf(s, ""); + g_string_append_printf(s, ""); /* First define types and totals in a whole VL */ for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) { int count = reg_width / vec_lanes[i].size; - g_string_printf(ts, "vq%d%c%c", count, - vec_lanes[i].sz, vec_lanes[i].suffix); + g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix); g_string_append_printf(s, "", ts->str, vec_lanes[i].gdb_type, count); @@ -243,39 +237,37 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg) * signed and potentially float versions of each size from 128 to * 8 bits. */ - for (bits = 128; bits >= 8; bits /= 2) { - int count = reg_width / bits; - g_string_append_printf(s, "", count); - for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) { - if (vec_lanes[i].size == bits) { - g_string_append_printf(s, "", - vec_lanes[i].suffix, - count, - vec_lanes[i].sz, vec_lanes[i].suffix); + for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) { + const char suf[] = { 'q', 'd', 's', 'h', 'b' }; + g_string_append_printf(s, "", suf[i]); + for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) { + if (vec_lanes[j].size == bits) { + g_string_append_printf(s, "", + vec_lanes[j].suffix, + vec_lanes[j].sz, vec_lanes[j].suffix); } } g_string_append(s, ""); } /* And now the final union of unions */ - g_string_append(s, ""); - for (bits = 128; bits >= 8; bits /= 2) { - int count = reg_width / bits; - for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) { - if (vec_lanes[i].size == bits) { - g_string_append_printf(s, "", - vec_lanes[i].sz, count); - break; - } - } + g_string_append(s, ""); + for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) { + const char suf[] = { 'q', 'd', 's', 'h', 'b' }; + g_string_append_printf(s, "", + suf[i], suf[i]); } g_string_append(s, ""); + /* Finally the sve prefix type */ + g_string_append_printf(s, + "", + reg_width / 8); + /* Then define each register in parts for each vq */ for (i = 0; i < 32; i++) { g_string_append_printf(s, "", + " regnum=\"%d\" type=\"svev\"/>", i, reg_width, base_reg++); info->num++; } @@ -287,31 +279,22 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg) " regnum=\"%d\" group=\"float\"" " type=\"int\"/>", base_reg++); info->num += 2; - /* - * Predicate registers aren't so big they are worth splitting up - * but we do need to define a type to hold the array of quad - * references. - */ - g_string_append_printf(s, - "", - cpu->sve_max_vq); + for (i = 0; i < 16; i++) { g_string_append_printf(s, "", + " regnum=\"%d\" type=\"svep\"/>", i, cpu->sve_max_vq * 16, base_reg++); info->num++; } g_string_append_printf(s, "", + " type=\"svep\"/>", cpu->sve_max_vq * 16, base_reg++); g_string_append_printf(s, "", + " regnum=\"%d\" type=\"int\"/>", base_reg++); info->num += 2; g_string_append_printf(s, ""); diff --git a/target/arm/helper.c b/target/arm/helper.c index 5ab3f5ace3..8a492465d6 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -276,7 +276,7 @@ static int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg) * while the ZCR works in Vector Quads (VQ) which is 128bit chunks. */ int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1; - return gdb_get_reg32(buf, vq * 2); + return gdb_get_reg64(buf, vq * 2); } default: /* gdbstub asked for something out our range */ diff --git a/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py b/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py index 972cf73c31..b9ef169c1a 100644 --- a/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py +++ b/tests/tcg/aarch64/gdbstub/test-sve-ioctl.py @@ -40,6 +40,17 @@ class TestBreakpoint(gdb.Breakpoint): except gdb.error: report(False, "checking zregs (out of range)") + # Check the aliased V registers are set and GDB has correctly + # created them for us having recognised and handled SVE. + try: + for i in range(0, 16): + val_z = gdb.parse_and_eval("$z0.b.u[%d]" % i) + val_v = gdb.parse_and_eval("$v0.b.u[%d]" % i) + report(int(val_z) == int(val_v), + "v0.b.u[%d] == z0.b.u[%d]" % (i, i)) + except gdb.error: + report(False, "checking vregs (out of range)") + def run_test(): "Run through the tests one by one"