target/sparc: Restore 'gdb-xml/sparc64-cp0.xml'

Restore gdb-xml/sparc64-cp0.xml from mainstream binutils, tag
'binutils-2_46', found in the gdb/features/sparc/folder [*].

Extract sparc_cp0_gdb_write_register() out of
sparc_cpu_gdb_read_register() and sparc_cp0_gdb_write_register()
out of sparc_cpu_gdb_write_register(), taking care to update the
register indexes in the switch cases.

Register these helpers with a call to gdb_register_coprocessor()
in sparc_cpu_register_gdb_regs().

[*] https://sourceware.org/git/?p=binutils-gdb.git;a=tree;f=gdb/features/sparc;hb=refs/tags/binutils-2_46

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20260219191955.83815-12-philmd@linaro.org>
This commit is contained in:
Philippe Mathieu-Daudé
2026-02-15 02:38:28 +01:00
parent 733c41f0aa
commit 891601f2e4
6 changed files with 131 additions and 90 deletions

View File

@@ -402,6 +402,7 @@ M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
M: Artyom Tarasenko <atar4qemu@gmail.com>
S: Maintained
F: target/sparc/
F: gdb-xml/sparc*.xml
F: hw/sparc/
F: hw/sparc64/
F: include/hw/sparc/sparc64.h

View File

@@ -4,6 +4,6 @@ TARGET_ABI_DIR=sparc
TARGET_SYSTBL_ABI=common,64
TARGET_SYSTBL=syscall.tbl
TARGET_BIG_ENDIAN=y
TARGET_XML_FILES=gdb-xml/sparc64-core.xml
TARGET_XML_FILES=gdb-xml/sparc64-core.xml gdb-xml/sparc64-cp0.xml
TARGET_LONG_BITS=64
TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API=y

View File

@@ -1,7 +1,7 @@
TARGET_ARCH=sparc64
TARGET_BASE_ARCH=sparc
TARGET_BIG_ENDIAN=y
TARGET_XML_FILES=gdb-xml/sparc64-core.xml
TARGET_XML_FILES=gdb-xml/sparc64-core.xml gdb-xml/sparc64-cp0.xml
TARGET_LONG_BITS=64
TARGET_NOT_USING_LEGACY_LDST_PHYS_API=y
TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API=y

View File

@@ -89,11 +89,4 @@
<reg name="f58" bitsize="64" type="ieee_double" regnum="77"/>
<reg name="f60" bitsize="64" type="ieee_double" regnum="78"/>
<reg name="f62" bitsize="64" type="ieee_double" regnum="79"/>
<reg name="pc" bitsize="64" type="code_ptr" regnum="80"/>
<reg name="npc" bitsize="64" type="code_ptr" regnum="81"/>
<reg name="state" bitsize="64" type="uint64" regnum="82"/>
<reg name="fsr" bitsize="64" type="uint64" regnum="83"/>
<reg name="fprs" bitsize="64" type="uint64" regnum="84"/>
<reg name="y" bitsize="64" type="uint64" regnum="85"/>
</feature>

16
gdb-xml/sparc64-cp0.xml Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2013-2026 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.sparc.cp0">
<reg name="pc" bitsize="64" type="code_ptr" regnum="80"/>
<reg name="npc" bitsize="64" type="code_ptr" regnum="81"/>
<reg name="state" bitsize="64" type="uint64" regnum="82"/>
<reg name="fsr" bitsize="64" type="uint64" regnum="83"/>
<reg name="fprs" bitsize="64" type="uint64" regnum="84"/>
<reg name="y" bitsize="64" type="uint64" regnum="85"/>
</feature>

View File

@@ -18,6 +18,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "exec/gdbstub.h"
#include "cpu.h"
#include "gdbstub/helpers.h"
@@ -48,27 +49,6 @@ int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.upper);
}
}
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
switch (n) {
case 64:
return gdb_get_rega(mem_buf, env->y);
case 65:
return gdb_get_rega(mem_buf, cpu_get_psr(env));
case 66:
return gdb_get_rega(mem_buf, env->wim);
case 67:
return gdb_get_rega(mem_buf, env->tbr);
case 68:
return gdb_get_rega(mem_buf, env->pc);
case 69:
return gdb_get_rega(mem_buf, env->npc);
case 70:
return gdb_get_rega(mem_buf, cpu_get_fsr(env));
case 71:
return gdb_get_rega(mem_buf, 0); /* csr */
default:
return gdb_get_rega(mem_buf, 0);
}
#else
if (n < 64) {
/* f0-f31 */
@@ -87,21 +67,51 @@ int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
*/
return gdb_get_reg64(mem_buf, env->fpr[(n - 64) + 16].ll);
}
#endif
return 0;
}
__attribute__((unused))
static int sparc_cp0_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
CPUSPARCState *env = cpu_env(cs);
#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
switch (n) {
case 80:
case 0:
return gdb_get_rega(mem_buf, env->y);
case 1:
return gdb_get_rega(mem_buf, cpu_get_psr(env));
case 2:
return gdb_get_rega(mem_buf, env->wim);
case 3:
return gdb_get_rega(mem_buf, env->tbr);
case 4:
return gdb_get_rega(mem_buf, env->pc);
case 5:
return gdb_get_rega(mem_buf, env->npc);
case 6:
return gdb_get_rega(mem_buf, cpu_get_fsr(env));
case 7:
return gdb_get_rega(mem_buf, 0); /* csr */
}
#else
switch (n) {
case 0:
return gdb_get_regl(mem_buf, env->pc);
case 81:
case 1:
return gdb_get_regl(mem_buf, env->npc);
case 82:
case 2:
return gdb_get_regl(mem_buf, (cpu_get_ccr(env) << 32) |
((env->asi & 0xff) << 24) |
((env->pstate & 0xfff) << 8) |
cpu_get_cwp64(env));
case 83:
case 3:
return gdb_get_regl(mem_buf, cpu_get_fsr(env));
case 84:
case 4:
return gdb_get_regl(mem_buf, env->fprs);
case 85:
case 5:
return gdb_get_regl(mem_buf, env->y);
}
#endif
@@ -138,33 +148,6 @@ int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
} else {
env->fpr[(n - 32) / 2].l.upper = tmp;
}
} else {
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
switch (n) {
case 64:
env->y = tmp;
break;
case 65:
cpu_put_psr(env, tmp);
break;
case 66:
env->wim = tmp;
break;
case 67:
env->tbr = tmp;
break;
case 68:
env->pc = tmp;
break;
case 69:
env->npc = tmp;
break;
case 70:
cpu_put_fsr(env, tmp);
break;
default:
return 0;
}
}
return 4;
#else
@@ -185,32 +168,77 @@ int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
* n == 79: f62 : env->fpr[31]
*/
env->fpr[(n - 64) + 16].ll = tmp;
} else {
switch (n) {
case 80:
env->pc = tmp;
break;
case 81:
env->npc = tmp;
break;
case 82:
cpu_put_ccr(env, tmp >> 32);
env->asi = (tmp >> 24) & 0xff;
env->pstate = (tmp >> 8) & 0xfff;
cpu_put_cwp64(env, tmp & 0xff);
break;
case 83:
cpu_put_fsr(env, tmp);
break;
case 84:
env->fprs = tmp;
break;
case 85:
env->y = tmp;
break;
default:
return 0;
}
}
return 8;
#endif
}
__attribute__((unused))
static int sparc_cp0_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
CPUSPARCState *env = cpu_env(cs);
#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
uint32_t tmp;
tmp = ldl_p(mem_buf);
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
switch (n) {
case 0:
env->y = tmp;
break;
case 1:
cpu_put_psr(env, tmp);
break;
case 2:
env->wim = tmp;
break;
case 3:
env->tbr = tmp;
break;
case 4:
env->pc = tmp;
break;
case 5:
env->npc = tmp;
break;
case 6:
cpu_put_fsr(env, tmp);
break;
default:
return 0;
}
return 4;
#else
uint64_t tmp;
tmp = ldq_p(mem_buf);
switch (n) {
case 0:
env->pc = tmp;
break;
case 1:
env->npc = tmp;
break;
case 2:
cpu_put_ccr(env, tmp >> 32);
env->asi = (tmp >> 24) & 0xff;
env->pstate = (tmp >> 8) & 0xfff;
cpu_put_cwp64(env, tmp & 0xff);
break;
case 3:
cpu_put_fsr(env, tmp);
break;
case 4:
env->fprs = tmp;
break;
case 5:
env->y = tmp;
break;
default:
return 0;
}
return 8;
#endif
@@ -221,6 +249,9 @@ void sparc_cpu_register_gdb_regs(CPUState *cs)
#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
/* Not yet supported */
#else
/* Not yet supported */
gdb_register_coprocessor(cs, sparc_cp0_gdb_read_register,
sparc_cp0_gdb_write_register,
gdb_find_static_feature("sparc64-cp0.xml"),
0);
#endif
}