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

Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
---
 configs/targets/sparc64-linux-user.mak |   2 +-
 configs/targets/sparc64-softmmu.mak    |   2 +-
 target/sparc/gdbstub.c                 | 193 ++++++++++++++-----------
 gdb-xml/sparc64-core.xml               |   7 -
 gdb-xml/sparc64-cp0.xml                |  16 ++
 5 files changed, 130 insertions(+), 90 deletions(-)
 create mode 100644 gdb-xml/sparc64-cp0.xml

diff --git a/configs/targets/sparc64-linux-user.mak 
b/configs/targets/sparc64-linux-user.mak
index 3bbd8495210..930f7e13ab9 100644
--- a/configs/targets/sparc64-linux-user.mak
+++ b/configs/targets/sparc64-linux-user.mak
@@ -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
diff --git a/configs/targets/sparc64-softmmu.mak 
b/configs/targets/sparc64-softmmu.mak
index 8a0290c2093..22e7f3c94a7 100644
--- a/configs/targets/sparc64-softmmu.mak
+++ b/configs/targets/sparc64-softmmu.mak
@@ -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
diff --git a/target/sparc/gdbstub.c b/target/sparc/gdbstub.c
index 79d661fbc10..bdd759dd0a9 100644
--- a/target/sparc/gdbstub.c
+++ b/target/sparc/gdbstub.c
@@ -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
 }
diff --git a/gdb-xml/sparc64-core.xml b/gdb-xml/sparc64-core.xml
index 375b9bb0cc6..1c26d8c01c1 100644
--- a/gdb-xml/sparc64-core.xml
+++ b/gdb-xml/sparc64-core.xml
@@ -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>
diff --git a/gdb-xml/sparc64-cp0.xml b/gdb-xml/sparc64-cp0.xml
new file mode 100644
index 00000000000..9b938dc7ecc
--- /dev/null
+++ b/gdb-xml/sparc64-cp0.xml
@@ -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>
-- 
2.52.0


Reply via email to