summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile.target2
-rwxr-xr-xconfigure12
-rw-r--r--exec-all.h33
-rw-r--r--exec.c6
-rw-r--r--fpu/softfloat.c12
-rw-r--r--main-loop.c147
-rw-r--r--main-loop.h1
-rw-r--r--oslib-win32.c3
-rw-r--r--target-sparc/cpu-qom.h75
-rw-r--r--target-sparc/cpu.c (renamed from target-sparc/cpu_init.c)68
-rw-r--r--target-sparc/cpu.h1
-rw-r--r--translate-all.c6
12 files changed, 263 insertions, 103 deletions
diff --git a/Makefile.target b/Makefile.target
index 999a968abe..14c8fa18fc 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ libobj-$(TARGET_ARM) += cpu.o
 libobj-$(TARGET_S390X) += cpu.o
 ifeq ($(TARGET_BASE_ARCH), sparc)
 libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
-libobj-y += cpu_init.o
+libobj-y += cpu.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
diff --git a/configure b/configure
index 4b3adc9bd4..6f850a66c3 100755
--- a/configure
+++ b/configure
@@ -1993,13 +1993,21 @@ fi
 
 ##########################################
 # glib support probe
-if $pkg_config --modversion gthread-2.0 > /dev/null 2>&1 ; then
+
+if test "$mingw32" = yes; then
+    # g_poll is required in order to integrate with the glib main loop.
+    glib_req_ver=2.20
+else
+    glib_req_ver=2.12
+fi
+if $pkg_config --atleast-version=$glib_req_ver gthread-2.0 > /dev/null 2>&1
+then
     glib_cflags=`$pkg_config --cflags gthread-2.0 2>/dev/null`
     glib_libs=`$pkg_config --libs gthread-2.0 2>/dev/null`
     LIBS="$glib_libs $LIBS"
     libs_qga="$glib_libs $libs_qga"
 else
-    echo "glib-2.0 required to compile QEMU"
+    echo "glib-$glib_req_ver required to compile QEMU"
     exit 1
 fi
 
diff --git a/exec-all.h b/exec-all.h
index 93a5b22c1c..a6d6519891 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -85,7 +85,7 @@ void cpu_gen_init(void);
 int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
                  int *gen_code_size_ptr);
 int cpu_restore_state(struct TranslationBlock *tb,
-                      CPUArchState *env, unsigned long searched_pc);
+                      CPUArchState *env, uintptr_t searched_pc);
 void cpu_resume_from_signal(CPUArchState *env1, void *puc);
 void cpu_io_recompile(CPUArchState *env, void *retaddr);
 TranslationBlock *tb_gen_code(CPUArchState *env, 
@@ -93,7 +93,7 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
                               int cflags);
 void cpu_exec_init(CPUArchState *env);
 void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1);
-int page_unprotect(target_ulong address, unsigned long pc, void *puc);
+int page_unprotect(target_ulong address, uintptr_t pc, void *puc);
 void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
                                    int is_cpu_write_access);
 void tlb_flush_page(CPUArchState *env, target_ulong addr);
@@ -150,7 +150,7 @@ struct TranslationBlock {
 #ifdef USE_DIRECT_JUMP
     uint16_t tb_jmp_offset[2]; /* offset of jump instruction */
 #else
-    unsigned long tb_next[2]; /* address of jump generated code */
+    uintptr_t tb_next[2]; /* address of jump generated code */
 #endif
     /* list of TBs jumping to this one. This is a circular list using
        the two least significant bits of the pointers to tell what is
@@ -202,14 +202,14 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
 void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
 #define tb_set_jmp_target1 ppc_tb_set_jmp_target
 #elif defined(__i386__) || defined(__x86_64__)
-static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
+static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
 {
     /* patch the branch destination */
     *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
     /* no need to flush icache explicitly */
 }
 #elif defined(__arm__)
-static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
+static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
 {
 #if !QEMU_GNUC_PREREQ(4, 1)
     register unsigned long _beg __asm ("a1");
@@ -237,19 +237,17 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
 #endif
 
 static inline void tb_set_jmp_target(TranslationBlock *tb,
-                                     int n, unsigned long addr)
+                                     int n, uintptr_t addr)
 {
-    unsigned long offset;
-
-    offset = tb->tb_jmp_offset[n];
-    tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
+    uint16_t offset = tb->tb_jmp_offset[n];
+    tb_set_jmp_target1((uintptr_t)(tb->tc_ptr + offset), addr);
 }
 
 #else
 
 /* set the jump target */
 static inline void tb_set_jmp_target(TranslationBlock *tb,
-                                     int n, unsigned long addr)
+                                     int n, uintptr_t addr)
 {
     tb->tb_next[n] = addr;
 }
@@ -262,15 +260,15 @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
     /* NOTE: this test is only needed for thread safety */
     if (!tb->jmp_next[n]) {
         /* patch the native jump address */
-        tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
+        tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc_ptr);
 
         /* add in TB jmp circular list */
         tb->jmp_next[n] = tb_next->jmp_first;
-        tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
+        tb_next->jmp_first = (TranslationBlock *)((uintptr_t)(tb) | (n));
     }
 }
 
-TranslationBlock *tb_find_pc(unsigned long pc_ptr);
+TranslationBlock *tb_find_pc(uintptr_t pc_ptr);
 
 #include "qemu-lock.h"
 
@@ -288,13 +286,14 @@ extern void *tci_tb_ptr;
 #  define GETPC() tci_tb_ptr
 # endif
 #elif defined(__s390__) && !defined(__s390x__)
-# define GETPC() ((void*)(((unsigned long)__builtin_return_address(0) & 0x7fffffffUL) - 1))
+# define GETPC() \
+    ((void *)(((uintptr_t)__builtin_return_address(0) & 0x7fffffffUL) - 1))
 #elif defined(__arm__)
 /* Thumb return addresses have the low bit set, so we need to subtract two.
    This is still safe in ARM mode because instructions are 4 bytes.  */
-# define GETPC() ((void *)((unsigned long)__builtin_return_address(0) - 2))
+# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 2))
 #else
-# define GETPC() ((void *)((unsigned long)__builtin_return_address(0) - 1))
+# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 1))
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
diff --git a/exec.c b/exec.c
index 6731ab8c4b..03d3a6b609 100644
--- a/exec.c
+++ b/exec.c
@@ -1380,7 +1380,7 @@ void tb_link_page(TranslationBlock *tb,
 
 /* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
    tb[1].tc_ptr. Return NULL if not found */
-TranslationBlock *tb_find_pc(unsigned long tc_ptr)
+TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
 {
     int m_min, m_max, m;
     unsigned long v;
@@ -2502,7 +2502,7 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
 
 /* called from signal handler: invalidate the code and unprotect the
    page. Return TRUE if the fault was successfully handled. */
-int page_unprotect(target_ulong address, unsigned long pc, void *puc)
+int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
 {
     unsigned int prot;
     PageDesc *p;
@@ -4484,7 +4484,7 @@ void cpu_io_recompile(CPUArchState *env, void *retaddr)
     target_ulong pc, cs_base;
     uint64_t flags;
 
-    tb = tb_find_pc((unsigned long)retaddr);
+    tb = tb_find_pc((uintptr_t)retaddr);
     if (!tb) {
         cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", 
                   retaddr);
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 81a7d1ae09..d37090ac53 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -117,7 +117,7 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM)
     int8 roundingMode;
     flag roundNearestEven;
     int8 roundIncrement, roundBits;
-    int32 z;
+    int32_t z;
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
@@ -166,7 +166,7 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU
 {
     int8 roundingMode;
     flag roundNearestEven, increment;
-    int64 z;
+    int64_t z;
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
@@ -1378,7 +1378,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
     flag aSign;
     int16 aExp, shiftCount;
     uint32_t aSig;
-    int32 z;
+    int32_t z;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat32Frac( a );
@@ -2762,7 +2762,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
     flag aSign;
     int16 aExp, shiftCount;
     uint64_t aSig, savedASig;
-    int32 z;
+    int32_t z;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat64Frac( a );
@@ -4248,7 +4248,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM )
     flag aSign;
     int32 aExp, shiftCount;
     uint64_t aSig, savedASig;
-    int32 z;
+    int32_t z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5277,7 +5277,7 @@ int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM )
     flag aSign;
     int32 aExp, shiftCount;
     uint64_t aSig0, aSig1, savedASig;
-    int32 z;
+    int32_t z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
diff --git a/main-loop.c b/main-loop.c
index db23de0497..7e163f9428 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -218,17 +218,19 @@ int main_loop_init(void)
     return 0;
 }
 
-
+static fd_set rfds, wfds, xfds;
+static int nfds;
 static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
 static int n_poll_fds;
 static int max_priority;
 
+#ifndef _WIN32
 static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
-                             fd_set *xfds, struct timeval *tv)
+                             fd_set *xfds, int *cur_timeout)
 {
     GMainContext *context = g_main_context_default();
     int i;
-    int timeout = 0, cur_timeout;
+    int timeout = 0;
 
     g_main_context_prepare(context, &max_priority);
 
@@ -253,10 +255,8 @@ static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
         }
     }
 
-    cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000);
-    if (timeout >= 0 && timeout < cur_timeout) {
-        tv->tv_sec = timeout / 1000;
-        tv->tv_usec = (timeout % 1000) * 1000;
+    if (timeout >= 0 && timeout < *cur_timeout) {
+        *cur_timeout = timeout;
     }
 }
 
@@ -288,7 +288,29 @@ static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds,
     }
 }
 
-#ifdef _WIN32
+static int os_host_main_loop_wait(int timeout)
+{
+    struct timeval tv;
+    int ret;
+
+    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout);
+
+    if (timeout > 0) {
+        qemu_mutex_unlock_iothread();
+    }
+
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
+    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+
+    if (timeout > 0) {
+        qemu_mutex_lock_iothread();
+    }
+
+    glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+    return ret;
+}
+#else
 /***********************************************************/
 /* Polling handling */
 
@@ -328,6 +350,7 @@ void qemu_del_polling_cb(PollingFunc *func, void *opaque)
 /* Wait objects support */
 typedef struct WaitObjects {
     int num;
+    int revents[MAXIMUM_WAIT_OBJECTS + 1];
     HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
     WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
     void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
@@ -344,6 +367,7 @@ int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
     w->events[w->num] = handle;
     w->func[w->num] = func;
     w->opaque[w->num] = opaque;
+    w->revents[w->num] = 0;
     w->num++;
     return 0;
 }
@@ -362,6 +386,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
             w->events[i] = w->events[i + 1];
             w->func[i] = w->func[i + 1];
             w->opaque[i] = w->opaque[i + 1];
+            w->revents[i] = w->revents[i + 1];
         }
     }
     if (found) {
@@ -369,61 +394,76 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
     }
 }
 
-static void os_host_main_loop_wait(int *timeout)
+void qemu_fd_register(int fd)
 {
-    int ret, ret2, i;
+    WSAEventSelect(fd, qemu_event_handle, FD_READ | FD_ACCEPT | FD_CLOSE |
+                   FD_CONNECT | FD_WRITE | FD_OOB);
+}
+
+static int os_host_main_loop_wait(int timeout)
+{
+    GMainContext *context = g_main_context_default();
+    int ret, i;
     PollingEntry *pe;
+    WaitObjects *w = &wait_objects;
+    static struct timeval tv0;
 
     /* XXX: need to suppress polling by better using win32 events */
     ret = 0;
     for (pe = first_polling_entry; pe != NULL; pe = pe->next) {
         ret |= pe->func(pe->opaque);
     }
-    if (ret == 0) {
-        int err;
-        WaitObjects *w = &wait_objects;
+    if (ret != 0) {
+        return ret;
+    }
 
-        qemu_mutex_unlock_iothread();
-        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
-        qemu_mutex_lock_iothread();
-        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
-            if (w->func[ret - WAIT_OBJECT_0]) {
-                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-            }
+    if (nfds >= 0) {
+        ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
+        if (ret != 0) {
+            timeout = 0;
+        }
+    }
+
+    g_main_context_prepare(context, &max_priority);
+    n_poll_fds = g_main_context_query(context, max_priority, &timeout,
+                                      poll_fds, ARRAY_SIZE(poll_fds));
+    g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
 
-            /* Check for additional signaled events */
-            for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-                /* Check if event is signaled */
-                ret2 = WaitForSingleObject(w->events[i], 0);
-                if (ret2 == WAIT_OBJECT_0) {
-                    if (w->func[i]) {
-                        w->func[i](w->opaque[i]);
-                    }
-                } else if (ret2 != WAIT_TIMEOUT) {
-                    err = GetLastError();
-                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
-                }
+    for (i = 0; i < w->num; i++) {
+        poll_fds[n_poll_fds + i].fd = (DWORD) w->events[i];
+        poll_fds[n_poll_fds + i].events = G_IO_IN;
+    }
+
+    qemu_mutex_unlock_iothread();
+    ret = g_poll(poll_fds, n_poll_fds + w->num, timeout);
+    qemu_mutex_lock_iothread();
+    if (ret > 0) {
+        for (i = 0; i < w->num; i++) {
+            w->revents[i] = poll_fds[n_poll_fds + i].revents;
+        }
+        for (i = 0; i < w->num; i++) {
+            if (w->revents[i] && w->func[i]) {
+                w->func[i](w->opaque[i]);
             }
-        } else if (ret != WAIT_TIMEOUT) {
-            err = GetLastError();
-            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
         }
     }
 
-    *timeout = 0;
-}
-#else
-static inline void os_host_main_loop_wait(int *timeout)
-{
+    if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) {
+        g_main_context_dispatch(context);
+    }
+
+    /* If an edge-triggered socket event occurred, select will return a
+     * positive result on the next iteration.  We do not need to do anything
+     * here.
+     */
+
+    return ret;
 }
 #endif
 
 int main_loop_wait(int nonblocking)
 {
-    fd_set rfds, wfds, xfds;
-    int ret, nfds;
-    struct timeval tv;
-    int timeout;
+    int ret, timeout;
 
     if (nonblocking) {
         timeout = 0;
@@ -432,11 +472,6 @@ int main_loop_wait(int nonblocking)
         qemu_bh_update_timeout(&timeout);
     }
 
-    os_host_main_loop_wait(&timeout);
-
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
-
     /* poll any events */
     /* XXX: separate device handlers from system ones */
     nfds = -1;
@@ -448,19 +483,7 @@ int main_loop_wait(int nonblocking)
     slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
 #endif
     qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
-    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv);
-
-    if (timeout > 0) {
-        qemu_mutex_unlock_iothread();
-    }
-
-    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
-
-    if (timeout > 0) {
-        qemu_mutex_lock_iothread();
-    }
-
-    glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+    ret = os_host_main_loop_wait(timeout);
     qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
 #ifdef CONFIG_SLIRP
     slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
diff --git a/main-loop.h b/main-loop.h
index 4987041ce7..e743aa0cf6 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -359,6 +359,7 @@ void qemu_mutex_unlock_iothread(void);
 
 /* internal interfaces */
 
+void qemu_fd_register(int fd);
 void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
 void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
 
diff --git a/oslib-win32.c b/oslib-win32.c
index ce3021e6c7..ffbc6d0c9f 100644
--- a/oslib-win32.c
+++ b/oslib-win32.c
@@ -28,6 +28,7 @@
 #include <windows.h>
 #include "config-host.h"
 #include "sysemu.h"
+#include "main-loop.h"
 #include "trace.h"
 #include "qemu_socket.h"
 
@@ -76,6 +77,7 @@ void qemu_vfree(void *ptr)
 void socket_set_block(int fd)
 {
     unsigned long opt = 0;
+    WSAEventSelect(fd, NULL, 0);
     ioctlsocket(fd, FIONBIO, &opt);
 }
 
@@ -83,6 +85,7 @@ void socket_set_nonblock(int fd)
 {
     unsigned long opt = 1;
     ioctlsocket(fd, FIONBIO, &opt);
+    qemu_fd_register(fd);
 }
 
 int inet_aton(const char *cp, struct in_addr *ia)
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
new file mode 100644
index 0000000000..3d3ac0fcef
--- /dev/null
+++ b/target-sparc/cpu-qom.h
@@ -0,0 +1,75 @@
+/*
+ * QEMU SPARC CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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/lgpl-2.1.html>
+ */
+#ifndef QEMU_SPARC_CPU_QOM_H
+#define QEMU_SPARC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#ifdef TARGET_SPARC64
+#define TYPE_SPARC_CPU "sparc64-cpu"
+#else
+#define TYPE_SPARC_CPU "sparc-cpu"
+#endif
+
+#define SPARC_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(SPARCCPUClass, (klass), TYPE_SPARC_CPU)
+#define SPARC_CPU(obj) \
+    OBJECT_CHECK(SPARCCPU, (obj), TYPE_SPARC_CPU)
+#define SPARC_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(SPARCCPUClass, (obj), TYPE_SPARC_CPU)
+
+/**
+ * SPARCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A SPARC CPU model.
+ */
+typedef struct SPARCCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} SPARCCPUClass;
+
+/**
+ * SPARCCPU:
+ * @env: #CPUSPARCState
+ *
+ * A SPARC CPU.
+ */
+typedef struct SPARCCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUSPARCState env;
+} SPARCCPU;
+
+static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env)
+{
+    return SPARC_CPU(container_of(env, SPARCCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e))
+
+
+#endif
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu.c
index 5c03f0b893..24f90f1ded 100644
--- a/target-sparc/cpu_init.c
+++ b/target-sparc/cpu.c
@@ -25,11 +25,23 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 
 void cpu_state_reset(CPUSPARCState *env)
 {
+    cpu_reset(ENV_GET_CPU(env));
+}
+
+/* CPUClass::reset() */
+static void sparc_cpu_reset(CPUState *s)
+{
+    SPARCCPU *cpu = SPARC_CPU(s);
+    SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
+    CPUSPARCState *env = &cpu->env;
+
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
         log_cpu_state(env, 0);
     }
 
+    scc->parent_reset(s);
+
     memset(env, 0, offsetof(CPUSPARCState, breakpoints));
     tlb_flush(env, 1);
     env->cwp = 0;
@@ -99,23 +111,18 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
     return 0;
 }
 
-static void cpu_sparc_close(CPUSPARCState *env)
-{
-    g_free(env->def);
-    g_free(env);
-}
-
 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
 {
+    SPARCCPU *cpu;
     CPUSPARCState *env;
 
-    env = g_new0(CPUSPARCState, 1);
-    cpu_exec_init(env);
+    cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
+    env = &cpu->env;
 
     gen_intermediate_code_init(env);
 
     if (cpu_sparc_register(env, cpu_model) < 0) {
-        cpu_sparc_close(env);
+        object_delete(OBJECT(cpu));
         return NULL;
     }
     qemu_init_vcpu(env);
@@ -847,3 +854,46 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
                 env->fsr, env->y);
 #endif
 }
+
+static void sparc_cpu_initfn(Object *obj)
+{
+    SPARCCPU *cpu = SPARC_CPU(obj);
+    CPUSPARCState *env = &cpu->env;
+
+    cpu_exec_init(env);
+}
+
+static void sparc_cpu_uninitfn(Object *obj)
+{
+    SPARCCPU *cpu = SPARC_CPU(obj);
+    CPUSPARCState *env = &cpu->env;
+
+    g_free(env->def);
+}
+
+static void sparc_cpu_class_init(ObjectClass *oc, void *data)
+{
+    SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(oc);
+
+    scc->parent_reset = cc->reset;
+    cc->reset = sparc_cpu_reset;
+}
+
+static const TypeInfo sparc_cpu_type_info = {
+    .name = TYPE_SPARC_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(SPARCCPU),
+    .instance_init = sparc_cpu_initfn,
+    .instance_finalize = sparc_cpu_uninitfn,
+    .abstract = false,
+    .class_size = sizeof(SPARCCPUClass),
+    .class_init = sparc_cpu_class_init,
+};
+
+static void sparc_cpu_register_types(void)
+{
+    type_register_static(&sparc_cpu_type_info);
+}
+
+type_init(sparc_cpu_register_types)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 885ad45c3a..865288cc94 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -691,6 +691,7 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
 #endif
 
 #include "cpu-all.h"
+#include "cpu-qom.h"
 
 #ifdef TARGET_SPARC64
 /* sun4u.c */
diff --git a/translate-all.c b/translate-all.c
index 8c7d303d86..5bd2d3711a 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -109,11 +109,11 @@ int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr
 /* The cpu state corresponding to 'searched_pc' is restored.
  */
 int cpu_restore_state(TranslationBlock *tb,
-                      CPUArchState *env, unsigned long searched_pc)
+                      CPUArchState *env, uintptr_t searched_pc)
 {
     TCGContext *s = &tcg_ctx;
     int j;
-    unsigned long tc_ptr;
+    uintptr_t tc_ptr;
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
@@ -133,7 +133,7 @@ int cpu_restore_state(TranslationBlock *tb,
     }
 
     /* find opc index corresponding to search_pc */
-    tc_ptr = (unsigned long)tb->tc_ptr;
+    tc_ptr = (uintptr_t)tb->tc_ptr;
     if (searched_pc < tc_ptr)
         return -1;