commit 5b50e790f9e9403d11b4164193b76530ee85a2a1
Author: Andreas Färber <afaerber@suse.de>
Date:   Sat Jun 29 04:18:45 2013 +0200

    cpu: Introduce CPUClass::gdb_{read,write}_register()
    
    Completes migration of target-specific code to new target-*/gdbstub.c.
    
    Acked-by: Michael Walle <michael@walle.cc> (for lm32)
    Acked-by: Max Filippov <jcmvbkbc@gmail.com> (for xtensa)
    Signed-off-by: Andreas Färber <afaerber@suse.de>

diff --git a/gdbstub.c b/gdbstub.c
index eb50630..d8a5a0e 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -40,7 +40,6 @@
 #include "cpu.h"
 #include "qemu/sockets.h"
 #include "sysemu/kvm.h"
-#include "qemu/bitops.h"
 
 static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
                                          uint8_t *buf, int len, bool is_write)
@@ -316,10 +315,7 @@ static int sstep_flags = SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER;
 
 static GDBState *gdbserver_state;
 
-/* This is an ugly hack to cope with both new and old gdb.
-   If gdb sends qXfer:features:read then assume we're talking to a newish
-   gdb that understands target descriptions.  */
-static int gdb_has_xml;
+bool gdb_has_xml;
 
 #ifdef CONFIG_USER_ONLY
 /* XXX: This is not thread safe.  Do we care?  */
@@ -489,11 +485,7 @@ static int put_packet(GDBState *s, const char *buf)
     return put_packet_binary(s, buf, strlen(buf));
 }
 
-#if defined(TARGET_I386)
-
-#include "target-i386/gdbstub.c"
-
-#elif defined (TARGET_PPC)
+#if defined(TARGET_PPC)
 
 #if defined (TARGET_PPC64)
 #define GDB_CORE_XML "power64-core.xml"
@@ -501,72 +493,14 @@ static int put_packet(GDBState *s, const char *buf)
 #define GDB_CORE_XML "power-core.xml"
 #endif
 
-#include "target-ppc/gdbstub.c"
-
-#elif defined (TARGET_SPARC)
-
-#include "target-sparc/gdbstub.c"
-
 #elif defined (TARGET_ARM)
 
 #define GDB_CORE_XML "arm-core.xml"
 
-#include "target-arm/gdbstub.c"
-
 #elif defined (TARGET_M68K)
 
 #define GDB_CORE_XML "cf-core.xml"
 
-#include "target-m68k/gdbstub.c"
-
-#elif defined (TARGET_MIPS)
-
-#include "target-mips/gdbstub.c"
-
-#elif defined(TARGET_OPENRISC)
-
-#include "target-openrisc/gdbstub.c"
-
-#elif defined (TARGET_SH4)
-
-#include "target-sh4/gdbstub.c"
-
-#elif defined (TARGET_MICROBLAZE)
-
-#include "target-microblaze/gdbstub.c"
-
-#elif defined (TARGET_CRIS)
-
-#include "target-cris/gdbstub.c"
-
-#elif defined (TARGET_ALPHA)
-
-#include "target-alpha/gdbstub.c"
-
-#elif defined (TARGET_S390X)
-
-#include "target-s390x/gdbstub.c"
-
-#elif defined (TARGET_LM32)
-
-#include "target-lm32/gdbstub.c"
-
-#elif defined(TARGET_XTENSA)
-
-#include "target-xtensa/gdbstub.c"
-
-#else
-
-static int cpu_gdb_read_register(CPUArchState *env, uint8_t *mem_buf, int n)
-{
-    return 0;
-}
-
-static int cpu_gdb_write_register(CPUArchState *env, uint8_t *mem_buf, int n)
-{
-    return 0;
-}
-
 #endif
 
 #ifdef GDB_CORE_XML
@@ -642,7 +576,7 @@ static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg)
     GDBRegisterState *r;
 
     if (reg < cc->gdb_num_core_regs) {
-        return cpu_gdb_read_register(env, mem_buf, reg);
+        return cc->gdb_read_register(cpu, mem_buf, reg);
     }
 
     for (r = cpu->gdb_regs; r; r = r->next) {
@@ -660,7 +594,7 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
     GDBRegisterState *r;
 
     if (reg < cc->gdb_num_core_regs) {
-        return cpu_gdb_write_register(env, mem_buf, reg);
+        return cc->gdb_write_register(cpu, mem_buf, reg);
     }
 
     for (r = cpu->gdb_regs; r; r = r->next) {
@@ -1212,7 +1146,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             const char *xml;
             target_ulong total_len;
 
-            gdb_has_xml = 1;
+            gdb_has_xml = true;
             p += 19;
             xml = get_feature_xml(p, &p);
             if (!xml) {
@@ -1621,7 +1555,7 @@ static void gdb_accept(void)
     s->c_cpu = first_cpu;
     s->g_cpu = first_cpu;
     s->fd = fd;
-    gdb_has_xml = 0;
+    gdb_has_xml = false;
 
     gdbserver_state = s;
 
@@ -1707,7 +1641,7 @@ static void gdb_chr_event(void *opaque, int event)
     switch (event) {
     case CHR_EVENT_OPENED:
         vm_stop(RUN_STATE_PAUSED);
-        gdb_has_xml = 0;
+        gdb_has_xml = false;
         break;
     default:
         break;
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index a5bd341..a608a26 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -84,6 +84,14 @@ int gdbserver_start(int);
 int gdbserver_start(const char *port);
 #endif
 
+/**
+ * gdb_has_xml:
+ * This is an ugly hack to cope with both new and old gdb.
+ * If gdb sends qXfer:features:read then assume we're talking to a newish
+ * gdb that understands target descriptions.
+ */
+extern bool gdb_has_xml;
+
 /* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
 extern const char *const xml_builtin[][2];
 
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 195fe59..c001474 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -80,6 +80,8 @@ struct TranslationBlock;
  * @synchronize_from_tb: Callback for synchronizing state from a TCG
  * #TranslationBlock.
  * @get_phys_page_debug: Callback for obtaining a physical address.
+ * @gdb_read_register: Callback for letting GDB read a register.
+ * @gdb_write_register: Callback for letting GDB write a register.
  * @vmsd: State description for migration.
  * @gdb_num_core_regs: Number of core registers accessible to GDB.
  *
@@ -109,6 +111,8 @@ typedef struct CPUClass {
     void (*set_pc)(CPUState *cpu, vaddr value);
     void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
     hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
+    int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg);
+    int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
 
     int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
                             int cpuid, void *opaque);
diff --git a/qom/cpu.c b/qom/cpu.c
index 2839ddf..dbc9fb6 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -157,6 +157,17 @@ static int cpu_common_write_elf64_note(WriteCoreDumpFunction f,
 }
 
 
+static int cpu_common_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg)
+{
+    return 0;
+}
+
+static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg)
+{
+    return 0;
+}
+
+
 void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
@@ -253,6 +264,8 @@ static void cpu_class_init(ObjectClass *klass, void *data)
     k->write_elf32_note = cpu_common_write_elf32_note;
     k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
     k->write_elf64_note = cpu_common_write_elf64_note;
+    k->gdb_read_register = cpu_common_gdb_read_register;
+    k->gdb_write_register = cpu_common_gdb_write_register;
     dc->realize = cpu_common_realizefn;
     dc->no_user = 1;
 }
diff --git a/target-alpha/Makefile.objs b/target-alpha/Makefile.objs
index 590304c..b96c5da 100644
--- a/target-alpha/Makefile.objs
+++ b/target-alpha/Makefile.objs
@@ -1,3 +1,4 @@
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-y += translate.o helper.o cpu.o
 obj-y += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
+obj-y += gdbstub.o
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index b2eeba3..2ebc9bc 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -82,5 +82,7 @@ void alpha_cpu_do_interrupt(CPUState *cpu);
 void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
                           int flags);
 hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index cc0f69a..64c70bc 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -271,6 +271,8 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = alpha_cpu_do_interrupt;
     cc->dump_state = alpha_cpu_dump_state;
     cc->set_pc = alpha_cpu_set_pc;
+    cc->gdb_read_register = alpha_cpu_gdb_read_register;
+    cc->gdb_write_register = alpha_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->do_unassigned_access = alpha_cpu_unassigned_access;
     cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
diff --git a/target-alpha/gdbstub.c b/target-alpha/gdbstub.c
index 1c18698..980f140 100644
--- a/target-alpha/gdbstub.c
+++ b/target-alpha/gdbstub.c
@@ -17,9 +17,14 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
-static int cpu_gdb_read_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
+int alpha_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    AlphaCPU *cpu = ALPHA_CPU(cs);
+    CPUAlphaState *env = &cpu->env;
     uint64_t val;
     CPU_DoubleU d;
 
@@ -52,8 +57,10 @@ static int cpu_gdb_read_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
     return gdb_get_regl(mem_buf, val);
 }
 
-static int cpu_gdb_write_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
+int alpha_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    AlphaCPU *cpu = ALPHA_CPU(cs);
+    CPUAlphaState *env = &cpu->env;
     target_ulong tmp = ldtul_p(mem_buf);
     CPU_DoubleU d;
 
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index 4a6e52e..2d9f77f 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -4,3 +4,4 @@ obj-$(CONFIG_KVM) += kvm.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
+obj-y += gdbstub.o
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 02162c9..cf36587 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -149,4 +149,7 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 
 hwaddr arm_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
+int arm_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
 #endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index f39c19f..a493cc2 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -824,6 +824,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = arm_cpu_do_interrupt;
     cc->dump_state = arm_cpu_dump_state;
     cc->set_pc = arm_cpu_set_pc;
+    cc->gdb_read_register = arm_cpu_gdb_read_register;
+    cc->gdb_write_register = arm_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
     cc->vmsd = &vmstate_arm_cpu;
diff --git a/target-arm/gdbstub.c b/target-arm/gdbstub.c
index e1c7df4..1c34396 100644
--- a/target-arm/gdbstub.c
+++ b/target-arm/gdbstub.c
@@ -17,6 +17,9 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
 /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
    whatever the target description contains.  Due to a historical mishap
@@ -24,8 +27,11 @@
    We hack round this by giving the FPA regs zero size when talking to a
    newer gdb.  */
 
-static int cpu_gdb_read_register(CPUARMState *env, uint8_t *mem_buf, int n)
+int arm_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
     if (n < 16) {
         /* Core integer register.  */
         return gdb_get_reg32(mem_buf, env->regs[n]);
@@ -53,8 +59,10 @@ static int cpu_gdb_read_register(CPUARMState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUARMState *env, uint8_t *mem_buf, int n)
+int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
     uint32_t tmp;
 
     tmp = ldl_p(mem_buf);
diff --git a/target-cris/Makefile.objs b/target-cris/Makefile.objs
index afb87bc..7779227 100644
--- a/target-cris/Makefile.objs
+++ b/target-cris/Makefile.objs
@@ -1,2 +1,3 @@
 obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
 obj-$(CONFIG_SOFTMMU) += mmu.o machine.o
diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index d7baf07..3e92ea0 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -81,4 +81,7 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 
 hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
+int cris_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
 #endif
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index 31eeddf..8fcc95d 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -255,6 +255,8 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = cris_cpu_do_interrupt;
     cc->dump_state = cris_cpu_dump_state;
     cc->set_pc = cris_cpu_set_pc;
+    cc->gdb_read_register = cris_cpu_gdb_read_register;
+    cc->gdb_write_register = cris_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = cris_cpu_get_phys_page_debug;
 #endif
diff --git a/target-cris/gdbstub.c b/target-cris/gdbstub.c
index ed23966..958a370 100644
--- a/target-cris/gdbstub.c
+++ b/target-cris/gdbstub.c
@@ -17,6 +17,9 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
 static int
 read_register_crisv10(CPUCRISState *env, uint8_t *mem_buf, int n)
@@ -48,8 +51,10 @@ read_register_crisv10(CPUCRISState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_read_register(CPUCRISState *env, uint8_t *mem_buf, int n)
+int cris_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    CRISCPU *cpu = CRIS_CPU(cs);
+    CPUCRISState *env = &cpu->env;
     uint8_t srs;
 
     if (env->pregs[PR_VR] < 32) {
@@ -85,8 +90,10 @@ static int cpu_gdb_read_register(CPUCRISState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUCRISState *env, uint8_t *mem_buf, int n)
+int cris_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    CRISCPU *cpu = CRIS_CPU(cs);
+    CPUCRISState *env = &cpu->env;
     uint32_t tmp;
 
     if (n > 49) {
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
index c1d4f05..3b629d4d 100644
--- a/target-i386/Makefile.objs
+++ b/target-i386/Makefile.objs
@@ -1,6 +1,7 @@
 obj-y += translate.o helper.o cpu.o
 obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
 obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o
+obj-y += gdbstub.o
 obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
 obj-$(CONFIG_KVM) += kvm.o hyperv.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index d928562..60d2b5d 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -106,4 +106,7 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 
 hwaddr x86_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 
+int x86_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
 #endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index df9832e..2b59b7d 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2538,6 +2538,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     cc->dump_state = x86_cpu_dump_state;
     cc->set_pc = x86_cpu_set_pc;
     cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
+    cc->gdb_read_register = x86_cpu_gdb_read_register;
+    cc->gdb_write_register = x86_cpu_gdb_write_register;
     cc->get_arch_id = x86_cpu_get_arch_id;
     cc->get_paging_enabled = x86_cpu_get_paging_enabled;
 #ifndef CONFIG_USER_ONLY
diff --git a/target-i386/gdbstub.c b/target-i386/gdbstub.c
index 0a4d97d..15bebef 100644
--- a/target-i386/gdbstub.c
+++ b/target-i386/gdbstub.c
@@ -17,6 +17,9 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
 #ifdef TARGET_X86_64
 static const int gpr_map[16] = {
@@ -35,8 +38,11 @@ static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 #define IDX_XMM_REGS    (IDX_FP_REGS + 16)
 #define IDX_MXCSR_REG   (IDX_XMM_REGS + CPU_NB_REGS)
 
-static int cpu_gdb_read_register(CPUX86State *env, uint8_t *mem_buf, int n)
+int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
     if (n < CPU_NB_REGS) {
         if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
             return gdb_get_reg64(mem_buf, env->regs[gpr_map[n]]);
@@ -108,8 +114,9 @@ static int cpu_gdb_read_register(CPUX86State *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_x86_gdb_load_seg(CPUX86State *env, int sreg, uint8_t *mem_buf)
+static int x86_cpu_gdb_load_seg(X86CPU *cpu, int sreg, uint8_t *mem_buf)
 {
+    CPUX86State *env = &cpu->env;
     uint16_t selector = ldl_p(mem_buf);
 
     if (selector != env->segs[sreg].selector) {
@@ -135,8 +142,10 @@ static int cpu_x86_gdb_load_seg(CPUX86State *env, int sreg, uint8_t *mem_buf)
     return 4;
 }
 
-static int cpu_gdb_write_register(CPUX86State *env, uint8_t *mem_buf, int n)
+int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
     uint32_t tmp;
 
     if (n < CPU_NB_REGS) {
@@ -179,17 +188,17 @@ static int cpu_gdb_write_register(CPUX86State *env, uint8_t *mem_buf, int n)
             return 4;
 
         case IDX_SEG_REGS:
-            return cpu_x86_gdb_load_seg(env, R_CS, mem_buf);
+            return x86_cpu_gdb_load_seg(cpu, R_CS, mem_buf);
         case IDX_SEG_REGS + 1:
-            return cpu_x86_gdb_load_seg(env, R_SS, mem_buf);
+            return x86_cpu_gdb_load_seg(cpu, R_SS, mem_buf);
         case IDX_SEG_REGS + 2:
-            return cpu_x86_gdb_load_seg(env, R_DS, mem_buf);
+            return x86_cpu_gdb_load_seg(cpu, R_DS, mem_buf);
         case IDX_SEG_REGS + 3:
-            return cpu_x86_gdb_load_seg(env, R_ES, mem_buf);
+            return x86_cpu_gdb_load_seg(cpu, R_ES, mem_buf);
         case IDX_SEG_REGS + 4:
-            return cpu_x86_gdb_load_seg(env, R_FS, mem_buf);
+            return x86_cpu_gdb_load_seg(cpu, R_FS, mem_buf);
         case IDX_SEG_REGS + 5:
-            return cpu_x86_gdb_load_seg(env, R_GS, mem_buf);
+            return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);
 
         case IDX_FP_REGS + 8:
             env->fpuc = ldl_p(mem_buf);
diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs
index ca20f21..4023687 100644
--- a/target-lm32/Makefile.objs
+++ b/target-lm32/Makefile.objs
@@ -1,2 +1,3 @@
 obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
 obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index 9e27329..723f604 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -79,5 +79,7 @@ void lm32_cpu_do_interrupt(CPUState *cpu);
 void lm32_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
 hwaddr lm32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int lm32_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int lm32_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index aa52696..962d553 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -87,6 +87,8 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = lm32_cpu_do_interrupt;
     cc->dump_state = lm32_cpu_dump_state;
     cc->set_pc = lm32_cpu_set_pc;
+    cc->gdb_read_register = lm32_cpu_gdb_read_register;
+    cc->gdb_write_register = lm32_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug;
     cc->vmsd = &vmstate_lm32_cpu;
diff --git a/target-lm32/gdbstub.c b/target-lm32/gdbstub.c
index 17f08f5..4979a98 100644
--- a/target-lm32/gdbstub.c
+++ b/target-lm32/gdbstub.c
@@ -17,10 +17,16 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 #include "hw/lm32/lm32_pic.h"
 
-static int cpu_gdb_read_register(CPULM32State *env, uint8_t *mem_buf, int n)
+int lm32_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    LM32CPU *cpu = LM32_CPU(cs);
+    CPULM32State *env = &cpu->env;
+
     if (n < 32) {
         return gdb_get_reg32(mem_buf, env->regs[n]);
     } else {
@@ -45,10 +51,11 @@ static int cpu_gdb_read_register(CPULM32State *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPULM32State *env, uint8_t *mem_buf, int n)
+int lm32_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
-    LM32CPU *cpu = lm32_env_get_cpu(env);
-    CPUClass *cc = CPU_GET_CLASS(cpu);
+    LM32CPU *cpu = LM32_CPU(cs);
+    CPUClass *cc = CPU_GET_CLASS(cs);
+    CPULM32State *env = &cpu->env;
     uint32_t tmp;
 
     if (n > cc->gdb_num_core_regs) {
diff --git a/target-m68k/Makefile.objs b/target-m68k/Makefile.objs
index 2e2b850..02cf616 100644
--- a/target-m68k/Makefile.objs
+++ b/target-m68k/Makefile.objs
@@ -1,2 +1,3 @@
 obj-y += m68k-semi.o
 obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index 7115707..7f388ed 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -74,5 +74,7 @@ void m68k_cpu_do_interrupt(CPUState *cpu);
 void m68k_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
 hwaddr m68k_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int m68k_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 93200d9..01a70f1 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -190,6 +190,8 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
     cc->do_interrupt = m68k_cpu_do_interrupt;
     cc->dump_state = m68k_cpu_dump_state;
     cc->set_pc = m68k_cpu_set_pc;
+    cc->gdb_read_register = m68k_cpu_gdb_read_register;
+    cc->gdb_write_register = m68k_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
 #endif
diff --git a/target-m68k/gdbstub.c b/target-m68k/gdbstub.c
index 9fa9fa6..ae8179c 100644
--- a/target-m68k/gdbstub.c
+++ b/target-m68k/gdbstub.c
@@ -17,9 +17,15 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
-static int cpu_gdb_read_register(CPUM68KState *env, uint8_t *mem_buf, int n)
+int m68k_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    M68kCPU *cpu = M68K_CPU(cs);
+    CPUM68KState *env = &cpu->env;
+
     if (n < 8) {
         /* D0-D7 */
         return gdb_get_reg32(mem_buf, env->dregs[n]);
@@ -39,8 +45,10 @@ static int cpu_gdb_read_register(CPUM68KState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUM68KState *env, uint8_t *mem_buf, int n)
+int m68k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    M68kCPU *cpu = M68K_CPU(cs);
+    CPUM68KState *env = &cpu->env;
     uint32_t tmp;
 
     tmp = ldl_p(mem_buf);
diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs
index 985330e..f3d7b44 100644
--- a/target-microblaze/Makefile.objs
+++ b/target-microblaze/Makefile.objs
@@ -1,2 +1,3 @@
 obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
 obj-$(CONFIG_SOFTMMU) += mmu.o
diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index 1318a36..35a12b4 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -75,5 +75,7 @@ void mb_cpu_do_interrupt(CPUState *cs);
 void mb_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                        int flags);
 hwaddr mb_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int mb_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 758b0cb..c75d1bd 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -141,6 +141,8 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = mb_cpu_do_interrupt;
     cc->dump_state = mb_cpu_dump_state;
     cc->set_pc = mb_cpu_set_pc;
+    cc->gdb_read_register = mb_cpu_gdb_read_register;
+    cc->gdb_write_register = mb_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->do_unassigned_access = mb_cpu_unassigned_access;
     cc->get_phys_page_debug = mb_cpu_get_phys_page_debug;
diff --git a/target-microblaze/gdbstub.c b/target-microblaze/gdbstub.c
index 678de21..a70e2ee 100644
--- a/target-microblaze/gdbstub.c
+++ b/target-microblaze/gdbstub.c
@@ -17,9 +17,15 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
-static int cpu_gdb_read_register(CPUMBState *env, uint8_t *mem_buf, int n)
+int mb_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+    CPUMBState *env = &cpu->env;
+
     if (n < 32) {
         return gdb_get_reg32(mem_buf, env->regs[n]);
     } else {
@@ -28,10 +34,11 @@ static int cpu_gdb_read_register(CPUMBState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUMBState *env, uint8_t *mem_buf, int n)
+int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
-    MicroBlazeCPU *cpu = mb_env_get_cpu(env);
-    CPUClass *cc = CPU_GET_CLASS(cpu);
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+    CPUClass *cc = CPU_GET_CLASS(cs);
+    CPUMBState *env = &cpu->env;
     uint32_t tmp;
 
     if (n > cc->gdb_num_core_regs) {
diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
index 119c816..0277d56 100644
--- a/target-mips/Makefile.objs
+++ b/target-mips/Makefile.objs
@@ -1,2 +1,3 @@
 obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
+obj-y += gdbstub.o
 obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index 7c8e616..8877f81 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -78,5 +78,7 @@ void mips_cpu_do_interrupt(CPUState *cpu);
 void mips_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
 hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index e667fb7..f81f9e9 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -100,6 +100,8 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
     cc->dump_state = mips_cpu_dump_state;
     cc->set_pc = mips_cpu_set_pc;
     cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
+    cc->gdb_read_register = mips_cpu_gdb_read_register;
+    cc->gdb_write_register = mips_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->do_unassigned_access = mips_cpu_unassigned_access;
     cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
diff --git a/target-mips/gdbstub.c b/target-mips/gdbstub.c
index db826d8..5b72d58 100644
--- a/target-mips/gdbstub.c
+++ b/target-mips/gdbstub.c
@@ -17,9 +17,15 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
-static int cpu_gdb_read_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
+int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+
     if (n < 32) {
         return gdb_get_regl(mem_buf, env->active_tc.gpr[n]);
     }
@@ -78,8 +84,10 @@ static unsigned int ieee_rm[] = {
     set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \
                             &env->active_fpu.fp_status)
 
-static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
+int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
     target_ulong tmp;
 
     tmp = ldtul_p(mem_buf);
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 44dc539..397d016 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -2,3 +2,4 @@ obj-$(CONFIG_SOFTMMU) += machine.o
 obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
 obj-y += exception_helper.o fpu_helper.o int_helper.o \
          interrupt_helper.o mmu_helper.o sys_helper.o
+obj-y += gdbstub.o
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 9b042e1..aa269fb 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -155,6 +155,8 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = openrisc_cpu_do_interrupt;
     cc->dump_state = openrisc_cpu_dump_state;
     cc->set_pc = openrisc_cpu_set_pc;
+    cc->gdb_read_register = openrisc_cpu_gdb_read_register;
+    cc->gdb_write_register = openrisc_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug;
     dc->vmsd = &vmstate_openrisc_cpu;
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 3ddb767..8fd0bc0 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -350,6 +350,8 @@ void openrisc_cpu_do_interrupt(CPUState *cpu);
 void openrisc_cpu_dump_state(CPUState *cpu, FILE *f,
                              fprintf_function cpu_fprintf, int flags);
 hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 void openrisc_translate_init(void);
 int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
                                   target_ulong address,
diff --git a/target-openrisc/gdbstub.c b/target-openrisc/gdbstub.c
index bdb8d2c..18bcc46 100644
--- a/target-openrisc/gdbstub.c
+++ b/target-openrisc/gdbstub.c
@@ -17,9 +17,15 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
-static int cpu_gdb_read_register(CPUOpenRISCState *env, uint8_t *mem_buf, int n)
+int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+    CPUOpenRISCState *env = &cpu->env;
+
     if (n < 32) {
         return gdb_get_reg32(mem_buf, env->gpr[n]);
     } else {
@@ -40,11 +46,11 @@ static int cpu_gdb_read_register(CPUOpenRISCState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUOpenRISCState *env,
-                                  uint8_t *mem_buf, int n)
+int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-    CPUClass *cc = CPU_GET_CLASS(cpu);
+    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+    CPUClass *cc = CPU_GET_CLASS(cs);
+    CPUOpenRISCState *env = &cpu->env;
     uint32_t tmp;
 
     if (n > cc->gdb_num_core_regs) {
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 6e78cb3..f72e399 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -13,3 +13,4 @@ obj-y += timebase_helper.o
 obj-y += misc_helper.o
 obj-y += mem_helper.o
 obj-$(CONFIG_USER_ONLY) += user_only_helper.o
+obj-y += gdbstub.o
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 3341c51..fc0d737 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -106,5 +106,7 @@ void ppc_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
 void ppc_cpu_dump_statistics(CPUState *cpu, FILE *f,
                              fprintf_function cpu_fprintf, int flags);
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-ppc/gdbstub.c b/target-ppc/gdbstub.c
index 40a9d7b..1c91090 100644
--- a/target-ppc/gdbstub.c
+++ b/target-ppc/gdbstub.c
@@ -17,6 +17,9 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
 /* Old gdb always expects FP registers.  Newer (xml-aware) gdb only
  * expects whatever the target description contains.  Due to a
@@ -25,8 +28,11 @@
  * FP regs zero size when talking to a newer gdb.
  */
 
-static int cpu_gdb_read_register(CPUPPCState *env, uint8_t *mem_buf, int n)
+int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+
     if (n < 32) {
         /* gprs */
         return gdb_get_regl(mem_buf, env->gpr[n]);
@@ -70,8 +76,11 @@ static int cpu_gdb_read_register(CPUPPCState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUPPCState *env, uint8_t *mem_buf, int n)
+int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+
     if (n < 32) {
         /* gprs */
         env->gpr[n] = ldtul_p(mem_buf);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 9116193..370d243 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8458,6 +8458,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     cc->dump_state = ppc_cpu_dump_state;
     cc->dump_statistics = ppc_cpu_dump_statistics;
     cc->set_pc = ppc_cpu_set_pc;
+    cc->gdb_read_register = ppc_cpu_gdb_read_register;
+    cc->gdb_write_register = ppc_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug;
 #endif
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 4e63417..ab938e7 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,4 +1,5 @@
 obj-y += translate.o helper.o cpu.o interrupt.o
 obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
+obj-y += gdbstub.o
 obj-$(CONFIG_SOFTMMU) += ioinst.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
index a4fe8fb..0d63b1c 100644
--- a/target-s390x/cpu-qom.h
+++ b/target-s390x/cpu-qom.h
@@ -75,5 +75,7 @@ void s390_cpu_do_interrupt(CPUState *cpu);
 void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
                          int flags);
 hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 8f99d7c..1d16da3 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -173,6 +173,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = s390_cpu_do_interrupt;
     cc->dump_state = s390_cpu_dump_state;
     cc->set_pc = s390_cpu_set_pc;
+    cc->gdb_read_register = s390_cpu_gdb_read_register;
+    cc->gdb_write_register = s390_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
 #endif
diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c
index ee3e984..a129742 100644
--- a/target-s390x/gdbstub.c
+++ b/target-s390x/gdbstub.c
@@ -17,9 +17,15 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+#include "qemu/bitops.h"
 
-static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n)
+int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
     uint64_t val;
     int cc_op;
 
@@ -43,8 +49,10 @@ static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUS390XState *env, uint8_t *mem_buf, int n)
+int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
     target_ulong tmpl;
     uint32_t tmp32;
     int r = 8;
diff --git a/target-sh4/Makefile.objs b/target-sh4/Makefile.objs
index cb448a8..a285358 100644
--- a/target-sh4/Makefile.objs
+++ b/target-sh4/Makefile.objs
@@ -1 +1,2 @@
 obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index 7c9160b..c04e786 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -87,5 +87,7 @@ void superh_cpu_do_interrupt(CPUState *cpu);
 void superh_cpu_dump_state(CPUState *cpu, FILE *f,
                            fprintf_function cpu_fprintf, int flags);
 hwaddr superh_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int superh_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int superh_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 35f0535..bda3c51 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -286,6 +286,8 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
     cc->dump_state = superh_cpu_dump_state;
     cc->set_pc = superh_cpu_set_pc;
     cc->synchronize_from_tb = superh_cpu_synchronize_from_tb;
+    cc->gdb_read_register = superh_cpu_gdb_read_register;
+    cc->gdb_write_register = superh_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = superh_cpu_get_phys_page_debug;
 #endif
diff --git a/target-sh4/gdbstub.c b/target-sh4/gdbstub.c
index fb85718..df4fa2a 100644
--- a/target-sh4/gdbstub.c
+++ b/target-sh4/gdbstub.c
@@ -17,12 +17,18 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
 /* Hint: Use "set architecture sh4" in GDB to see fpu registers */
 /* FIXME: We should use XML for this.  */
 
-static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n)
+int superh_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    SuperHCPU *cpu = SUPERH_CPU(cs);
+    CPUSH4State *env = &cpu->env;
+
     switch (n) {
     case 0 ... 7:
         if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
@@ -70,8 +76,11 @@ static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUSH4State *env, uint8_t *mem_buf, int n)
+int superh_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    SuperHCPU *cpu = SUPERH_CPU(cs);
+    CPUSH4State *env = &cpu->env;
+
     switch (n) {
     case 0 ... 7:
         if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
diff --git a/target-sparc/Makefile.objs b/target-sparc/Makefile.objs
index 9fc42ea..1cd81cc 100644
--- a/target-sparc/Makefile.objs
+++ b/target-sparc/Makefile.objs
@@ -4,3 +4,4 @@ obj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
 obj-$(TARGET_SPARC) += int32_helper.o
 obj-$(TARGET_SPARC64) += int64_helper.o
 obj-$(TARGET_SPARC64) += vis_helper.o
+obj-y += gdbstub.o
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index 39d975b..8e3e0de 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -79,5 +79,7 @@ void sparc_cpu_do_interrupt(CPUState *cpu);
 void sparc_cpu_dump_state(CPUState *cpu, FILE *f,
                           fprintf_function cpu_fprintf, int flags);
 hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int sparc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 388a632..c7b4a90 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -787,6 +787,8 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
 #endif
     cc->set_pc = sparc_cpu_set_pc;
     cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
+    cc->gdb_read_register = sparc_cpu_gdb_read_register;
+    cc->gdb_write_register = sparc_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->do_unassigned_access = sparc_cpu_unassigned_access;
     cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
diff --git a/target-sparc/gdbstub.c b/target-sparc/gdbstub.c
index 460c0b7..3de3242 100644
--- a/target-sparc/gdbstub.c
+++ b/target-sparc/gdbstub.c
@@ -17,6 +17,9 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
 #ifdef TARGET_ABI32
 #define gdb_get_rega(buf, val) gdb_get_reg32(buf, val)
@@ -24,8 +27,11 @@
 #define gdb_get_rega(buf, val) gdb_get_regl(buf, val)
 #endif
 
-static int cpu_gdb_read_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
+int sparc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
+
     if (n < 8) {
         /* g0..g7 */
         return gdb_get_rega(mem_buf, env->gregs[n]);
@@ -98,8 +104,10 @@ static int cpu_gdb_read_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
     return 0;
 }
 
-static int cpu_gdb_write_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
+int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
 #if defined(TARGET_ABI32)
     abi_ulong tmp;
 
diff --git a/target-xtensa/Makefile.objs b/target-xtensa/Makefile.objs
index 644b7f9..5c150a8 100644
--- a/target-xtensa/Makefile.objs
+++ b/target-xtensa/Makefile.objs
@@ -3,3 +3,4 @@ obj-y += core-dc232b.o
 obj-y += core-dc233c.o
 obj-y += core-fsf.o
 obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index 1b9479e..c6cc2d9 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -87,5 +87,7 @@ void xtensa_cpu_do_interrupt(CPUState *cpu);
 void xtensa_cpu_dump_state(CPUState *cpu, FILE *f,
                            fprintf_function cpu_fprintf, int flags);
 hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
 #endif
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 560fa0c..e966aa0 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -133,6 +133,8 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = xtensa_cpu_do_interrupt;
     cc->dump_state = xtensa_cpu_dump_state;
     cc->set_pc = xtensa_cpu_set_pc;
+    cc->gdb_read_register = xtensa_cpu_gdb_read_register;
+    cc->gdb_write_register = xtensa_cpu_gdb_write_register;
 #ifndef CONFIG_USER_ONLY
     cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug;
 #endif
diff --git a/target-xtensa/gdbstub.c b/target-xtensa/gdbstub.c
index c963563..9e13b20 100644
--- a/target-xtensa/gdbstub.c
+++ b/target-xtensa/gdbstub.c
@@ -17,9 +17,14 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
 
-static int cpu_gdb_read_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
+int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    XtensaCPU *cpu = XTENSA_CPU(cs);
+    CPUXtensaState *env = &cpu->env;
     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
 
     if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
@@ -55,8 +60,10 @@ static int cpu_gdb_read_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
     }
 }
 
-static int cpu_gdb_write_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
+int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
+    XtensaCPU *cpu = XTENSA_CPU(cs);
+    CPUXtensaState *env = &cpu->env;
     uint32_t tmp;
     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
 
