diff mbox

[RFC,11/12] target-sparc: QOM'ify CPU

Message ID 1331747617-7837-12-git-send-email-afaerber@suse.de
State New
Headers show

Commit Message

Andreas Färber March 14, 2012, 5:53 p.m. UTC
Let sparc_cpu_list() enumerate CPU classes alphabetically.

Introduce sparc_env_get_features() to workaround a circular dependency.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 Makefile.target             |    2 +-
 target-sparc/cpu-qom.h      |   95 +++++
 target-sparc/cpu.c          |  949 +++++++++++++++++++++++++++++++++++++++++++
 target-sparc/cpu.h          |   29 +-
 target-sparc/cpu_init.c     |  848 --------------------------------------
 target-sparc/int32_helper.c |    5 +-
 target-sparc/ldst_helper.c  |   19 +-
 target-sparc/mmu_helper.c   |    4 +-
 target-sparc/translate.c    |    4 +-
 target-sparc/win_helper.c   |    3 +-
 10 files changed, 1075 insertions(+), 883 deletions(-)
 create mode 100644 target-sparc/cpu-qom.h
 create mode 100644 target-sparc/cpu.c
 delete mode 100644 target-sparc/cpu_init.c

Comments

Blue Swirl March 14, 2012, 8:16 p.m. UTC | #1
On Wed, Mar 14, 2012 at 17:53, Andreas Färber <afaerber@suse.de> wrote:
> Let sparc_cpu_list() enumerate CPU classes alphabetically.
>
> Introduce sparc_env_get_features() to workaround a circular dependency.
>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
>  Makefile.target             |    2 +-
>  target-sparc/cpu-qom.h      |   95 +++++
>  target-sparc/cpu.c          |  949 +++++++++++++++++++++++++++++++++++++++++++
>  target-sparc/cpu.h          |   29 +-
>  target-sparc/cpu_init.c     |  848 --------------------------------------
>  target-sparc/int32_helper.c |    5 +-
>  target-sparc/ldst_helper.c  |   19 +-
>  target-sparc/mmu_helper.c   |    4 +-
>  target-sparc/translate.c    |    4 +-
>  target-sparc/win_helper.c   |    3 +-
>  10 files changed, 1075 insertions(+), 883 deletions(-)
>  create mode 100644 target-sparc/cpu-qom.h
>  create mode 100644 target-sparc/cpu.c
>  delete mode 100644 target-sparc/cpu_init.c
>
> diff --git a/Makefile.target b/Makefile.target
> index 82171ca..1c6ed12 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -100,7 +100,7 @@ libobj-$(TARGET_S390X) += cpu.o
>  libobj-$(TARGET_SH4) += 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/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
> new file mode 100644
> index 0000000..15dcf84
> --- /dev/null
> +++ b/target-sparc/cpu-qom.h
> @@ -0,0 +1,95 @@
> +/*
> + * 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"
> +
> +#define TYPE_SPARC_CPU "sparc-cpu"
> +
> +#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);
> +
> +    target_ulong iu_version;
> +    uint32_t fpu_version;
> +    uint32_t mmu_version;
> +    uint32_t mmu_bm;
> +    uint32_t mmu_ctpr_mask;
> +    uint32_t mmu_cxr_mask;
> +    uint32_t mmu_sfsr_mask;
> +    uint32_t mmu_trcr_mask;
> +    uint32_t mxcc_version;
> +    uint32_t features;
> +    uint32_t nwindows;
> +    uint32_t maxtl;
> +} SPARCCPUClass;
> +
> +/**
> + * SPARCCPU:
> + * @env: Legacy CPU state.
> + *
> + * A SPARC CPU.
> + */
> +typedef struct SPARCCPU {
> +    /*< private >*/
> +    CPUState parent_obj;
> +    /*< public >*/
> +
> +    CPUSPARCState env;
> +
> +    target_ulong iu_version;
> +    uint32_t fpu_version;
> +    uint32_t mmu_version;
> +    uint32_t features;
> +    uint32_t nwindows;
> +} SPARCCPU;

The fields do not look correct at all, the same fields are in both
structs. Moreover Sparc32 and Sparc64 fields are mixed. Maybe I don't
fully understand the conversion.

Would it be possible to make a common parent class which is then
specialized by Sparc32 and Sparc64 classes? There are many common
fields but also many 32/64 specific ones. Also cpu_common.c, cpu32.c
and cpu64.c to avoid #ifdeffery?

> +
> +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))
> +
> +static inline uint32_t sparc_env_get_features(CPUSPARCState *env)
> +{
> +    return sparc_env_get_cpu(env)->features;
> +}
> +
> +
> +#endif
> diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
> new file mode 100644
> index 0000000..4c960a9
> --- /dev/null
> +++ b/target-sparc/cpu.c
> @@ -0,0 +1,949 @@
> +/*
> + * Sparc CPU init helpers
> + *
> + *  Copyright (c) 2003-2005 Fabrice Bellard
> + *  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 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/>.
> + */
> +
> +#include "cpu-qom.h"
> +
> +//#define DEBUG_FEATURES
> +
> +void cpu_state_reset(CPUSPARCState *env)
> +{
> +    cpu_reset(ENV_GET_CPU(env));
> +}
> +
> +static void sparc_cpu_reset(CPUState *c)
> +{
> +    SPARCCPU *cpu = SPARC_CPU(c);
> +    SPARCCPUClass *klass = 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);
> +    }
> +
> +    klass->parent_reset(c);
> +
> +    tlb_flush(env, 1);
> +    env->cwp = 0;
> +#ifndef TARGET_SPARC64
> +    env->wim = 1;
> +#endif
> +    env->regwptr = env->regbase + (env->cwp * 16);
> +    CC_OP = CC_OP_FLAGS;
> +#if defined(CONFIG_USER_ONLY)
> +#ifdef TARGET_SPARC64
> +    env->cleanwin = env->nwindows - 2;
> +    env->cansave = env->nwindows - 2;
> +    env->pstate = PS_RMO | PS_PEF | PS_IE;
> +    env->asi = 0x82; /* Primary no-fault */
> +#endif
> +#else
> +#if !defined(TARGET_SPARC64)
> +    env->psret = 0;
> +    env->psrs = 1;
> +    env->psrps = 1;
> +#endif
> +#ifdef TARGET_SPARC64
> +    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
> +    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
> +    env->tl = env->maxtl;
> +    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
> +    env->lsu = 0;
> +#else
> +    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
> +    env->mmuregs[0] |= klass->mmu_bm;
> +#endif
> +    env->pc = 0;
> +    env->npc = env->pc + 4;
> +#endif
> +    env->cache_control = 0;
> +}
> +
> +static void sparc_cpu_initfn(Object *obj)
> +{
> +    SPARCCPU *cpu = SPARC_CPU(obj);
> +    SPARCCPUClass *klass = SPARC_CPU_GET_CLASS(cpu);
> +    CPUSPARCState *env = &cpu->env;
> +
> +    memset(env, 0, sizeof(*env));
> +    cpu_exec_init(env);
> +
> +#if defined(CONFIG_USER_ONLY)
> +    if ((cpu->features & CPU_FEATURE_FLOAT)) {
> +        cpu->features |= CPU_FEATURE_FLOAT128;
> +    }
> +#endif
> +    env->version = cpu->iu_version;
> +    env->fsr = cpu->fpu_version;
> +    env->nwindows = cpu->nwindows;
> +#if !defined(TARGET_SPARC64)
> +    env->mmuregs[0] |= cpu->mmu_version;
> +    cpu_sparc_set_id(env, 0);
> +    env->mxccregs[7] |= klass->mxcc_version;
> +#else
> +    env->mmu_version = cpu->mmu_version;
> +    env->maxtl = klass->maxtl;
> +    env->version |= klass->maxtl << 8;
> +    env->version |= cpu->nwindows - 1;
> +#endif
> +}
> +
> +void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
> +{
> +#if !defined(TARGET_SPARC64)
> +    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
> +#endif
> +}
> +
> +/* CPU models */
> +
> +typedef struct SPARCCPUInfo {
> +    const char *name;
> +    target_ulong iu_version;
> +    uint32_t fpu_version;
> +    uint32_t mmu_version;
> +    uint32_t mmu_bm;
> +    uint32_t mmu_ctpr_mask;
> +    uint32_t mmu_cxr_mask;
> +    uint32_t mmu_sfsr_mask;
> +    uint32_t mmu_trcr_mask;
> +    uint32_t mxcc_version;
> +    uint32_t features;
> +    uint32_t nwindows;
> +    uint32_t maxtl;
> +} SPARCCPUInfo;
> +
> +static void sparc_cpu_class_init(ObjectClass *klass, void *data)
> +{
> +    CPUClass *cpu_class = CPU_CLASS(klass);
> +    SPARCCPUClass *k = SPARC_CPU_CLASS(klass);
> +    const SPARCCPUInfo *info = data;
> +
> +    k->parent_reset = cpu_class->reset;
> +    cpu_class->reset = sparc_cpu_reset;
> +
> +    k->iu_version = info->iu_version;
> +    k->fpu_version = info->fpu_version;
> +    k->mmu_version = info->mmu_version;
> +    k->mmu_bm = info->mmu_bm;
> +    k->mmu_ctpr_mask = info->mmu_ctpr_mask;
> +    k->mmu_cxr_mask = info->mmu_cxr_mask;
> +    k->mmu_sfsr_mask = info->mmu_sfsr_mask;
> +    k->mmu_trcr_mask = info->mmu_trcr_mask;
> +    k->mxcc_version = info->mxcc_version;
> +    k->features = info->features;
> +    k->nwindows = info->nwindows;
> +    k->maxtl = info->maxtl;
> +}
> +
> +static const SPARCCPUInfo sparc_cpus[] = {
> +#ifdef TARGET_SPARC64
> +    {
> +        .name = "Fujitsu Sparc64",
> +        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 4,
> +        .maxtl = 4,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Fujitsu Sparc64 III",
> +        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 5,
> +        .maxtl = 4,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Fujitsu Sparc64 IV",
> +        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Fujitsu Sparc64 V",
> +        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI UltraSparc I",
> +        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI UltraSparc II",
> +        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI UltraSparc IIi",
> +        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI UltraSparc IIe",
> +        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Sun UltraSparc III",
> +        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Sun UltraSparc III Cu",
> +        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_3,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Sun UltraSparc IIIi",
> +        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Sun UltraSparc IV",
> +        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_4,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Sun UltraSparc IV+",
> +        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
> +    },
> +    {
> +        .name = "Sun UltraSparc IIIi+",
> +        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_3,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Sun UltraSparc T1",
> +        /* defined in sparc_ifu_fdp.v and ctu.h */
> +        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_sun4v,
> +        .nwindows = 8,
> +        .maxtl = 6,
> +        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
> +        | CPU_FEATURE_GL,
> +    },
> +    {
> +        .name = "Sun UltraSparc T2",
> +        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
> +        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_sun4v,
> +        .nwindows = 8,
> +        .maxtl = 6,
> +        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
> +        | CPU_FEATURE_GL,
> +    },
> +    {
> +        .name = "NEC UltraSparc I",
> +        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
> +        .fpu_version = 0x00000000,
> +        .mmu_version = mmu_us_12,
> +        .nwindows = 8,
> +        .maxtl = 5,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +#else
> +    {
> +        .name = "Fujitsu MB86900",
> +        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
> +        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> +        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 7,
> +        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
> +    },
> +    {
> +        .name = "Fujitsu MB86904",
> +        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
> +        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> +        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x00ffffc0,
> +        .mmu_cxr_mask = 0x000000ff,
> +        .mmu_sfsr_mask = 0x00016fff,
> +        .mmu_trcr_mask = 0x00ffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Fujitsu MB86907",
> +        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
> +        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> +        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0xffffffc0,
> +        .mmu_cxr_mask = 0x000000ff,
> +        .mmu_sfsr_mask = 0x00016fff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "LSI L64811",
> +        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
> +        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
> +        .mmu_version = 0x10 << 24,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
> +        CPU_FEATURE_FSMULD,
> +    },
> +    {
> +        .name = "Cypress CY7C601",
> +        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
> +        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
> +        .mmu_version = 0x10 << 24,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
> +        CPU_FEATURE_FSMULD,
> +    },
> +    {
> +        .name = "Cypress CY7C611",
> +        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
> +        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
> +        .mmu_version = 0x10 << 24,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
> +        CPU_FEATURE_FSMULD,
> +    },
> +    {
> +        .name = "TI MicroSparc I",
> +        .iu_version = 0x41000000,
> +        .fpu_version = 4 << 17,
> +        .mmu_version = 0x41000000,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0x00016fff,
> +        .mmu_trcr_mask = 0x0000003f,
> +        .nwindows = 7,
> +        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
> +        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
> +        CPU_FEATURE_FMUL,
> +    },
> +    {
> +        .name = "TI MicroSparc II",
> +        .iu_version = 0x42000000,
> +        .fpu_version = 4 << 17,
> +        .mmu_version = 0x02000000,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x00ffffc0,
> +        .mmu_cxr_mask = 0x000000ff,
> +        .mmu_sfsr_mask = 0x00016fff,
> +        .mmu_trcr_mask = 0x00ffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI MicroSparc IIep",
> +        .iu_version = 0x42000000,
> +        .fpu_version = 4 << 17,
> +        .mmu_version = 0x04000000,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x00ffffc0,
> +        .mmu_cxr_mask = 0x000000ff,
> +        .mmu_sfsr_mask = 0x00016bff,
> +        .mmu_trcr_mask = 0x00ffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI SuperSparc 40", /* STP1020NPGA */
> +        .iu_version = 0x41000000, /* SuperSPARC 2.x */
> +        .fpu_version = 0 << 17,
> +        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
> +        .mmu_bm = 0x00002000,
> +        .mmu_ctpr_mask = 0xffffffc0,
> +        .mmu_cxr_mask = 0x0000ffff,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI SuperSparc 50", /* STP1020PGA */
> +        .iu_version = 0x40000000, /* SuperSPARC 3.x */
> +        .fpu_version = 0 << 17,
> +        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
> +        .mmu_bm = 0x00002000,
> +        .mmu_ctpr_mask = 0xffffffc0,
> +        .mmu_cxr_mask = 0x0000ffff,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI SuperSparc 51",
> +        .iu_version = 0x40000000, /* SuperSPARC 3.x */
> +        .fpu_version = 0 << 17,
> +        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
> +        .mmu_bm = 0x00002000,
> +        .mmu_ctpr_mask = 0xffffffc0,
> +        .mmu_cxr_mask = 0x0000ffff,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .mxcc_version = 0x00000104,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI SuperSparc 60", /* STP1020APGA */
> +        .iu_version = 0x40000000, /* SuperSPARC 3.x */
> +        .fpu_version = 0 << 17,
> +        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
> +        .mmu_bm = 0x00002000,
> +        .mmu_ctpr_mask = 0xffffffc0,
> +        .mmu_cxr_mask = 0x0000ffff,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI SuperSparc 61",
> +        .iu_version = 0x44000000, /* SuperSPARC 3.x */
> +        .fpu_version = 0 << 17,
> +        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
> +        .mmu_bm = 0x00002000,
> +        .mmu_ctpr_mask = 0xffffffc0,
> +        .mmu_cxr_mask = 0x0000ffff,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .mxcc_version = 0x00000104,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "TI SuperSparc II",
> +        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
> +        .fpu_version = 0 << 17,
> +        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
> +        .mmu_bm = 0x00002000,
> +        .mmu_ctpr_mask = 0xffffffc0,
> +        .mmu_cxr_mask = 0x0000ffff,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .mxcc_version = 0x00000104,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Ross RT625",
> +        .iu_version = 0x1e000000,
> +        .fpu_version = 1 << 17,
> +        .mmu_version = 0x1e000000,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "Ross RT620",
> +        .iu_version = 0x1f000000,
> +        .fpu_version = 1 << 17,
> +        .mmu_version = 0x1f000000,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "BIT B5010",
> +        .iu_version = 0x20000000,
> +        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
> +        .mmu_version = 0x20000000,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
> +        CPU_FEATURE_FSMULD,
> +    },
> +    {
> +        .name = "Matsushita MN10501",
> +        .iu_version = 0x50000000,
> +        .fpu_version = 0 << 17,
> +        .mmu_version = 0x50000000,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
> +        CPU_FEATURE_FSMULD,
> +    },
> +    {
> +        .name = "Weitek W8601",
> +        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
> +        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
> +        .mmu_version = 0x10 << 24,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES,
> +    },
> +    {
> +        .name = "LEON2",
> +        .iu_version = 0xf2000000,
> +        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> +        .mmu_version = 0xf2000000,
> +        .mmu_bm = 0x00004000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
> +    },
> +    {
> +        .name = "LEON3",
> +        .iu_version = 0xf3000000,
> +        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> +        .mmu_version = 0xf3000000,
> +        .mmu_bm = 0x00000000,
> +        .mmu_ctpr_mask = 0x007ffff0,
> +        .mmu_cxr_mask = 0x0000003f,
> +        .mmu_sfsr_mask = 0xffffffff,
> +        .mmu_trcr_mask = 0xffffffff,
> +        .nwindows = 8,
> +        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
> +        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
> +    },
> +#endif
> +};
> +
> +static const char * const feature_name[] = {
> +    "float",
> +    "float128",
> +    "swap",
> +    "mul",
> +    "div",
> +    "flush",
> +    "fsqrt",
> +    "fmul",
> +    "vis1",
> +    "vis2",
> +    "fsmuld",
> +    "hypv",
> +    "cmt",
> +    "gl",
> +};
> +
> +static void print_features(FILE *f, fprintf_function cpu_fprintf,
> +                           uint32_t features, const char *prefix)
> +{
> +    unsigned int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
> +        if (feature_name[i] && (features & (1 << i))) {
> +            if (prefix) {
> +                (*cpu_fprintf)(f, "%s", prefix);
> +            }
> +            (*cpu_fprintf)(f, "%s ", feature_name[i]);
> +        }
> +    }
> +}
> +
> +static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
> +{
> +    unsigned int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
> +        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
> +            *features |= 1 << i;
> +            return;
> +        }
> +    }
> +    fprintf(stderr, "CPU feature %s not found\n", flagname);
> +}
> +
> +static SPARCCPU *cpu_sparc_find_by_name(const char *cpu_model)
> +{
> +    SPARCCPU *cpu;
> +    char *s = strdup(cpu_model);
> +    char *featurestr, *name = strtok(s, ",");
> +    uint32_t plus_features = 0;
> +    uint32_t minus_features = 0;
> +    uint64_t iu_version;
> +    uint32_t fpu_version, mmu_version, nwindows;
> +
> +    if (object_class_by_name(name) == NULL) {
> +        goto error;
> +    }
> +    cpu = SPARC_CPU(object_new(name));
> +
> +    featurestr = strtok(NULL, ",");
> +    while (featurestr) {
> +        char *val;
> +
> +        if (featurestr[0] == '+') {
> +            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
> +        } else if (featurestr[0] == '-') {
> +            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
> +        } else if ((val = strchr(featurestr, '='))) {
> +            *val = 0; val++;
> +            if (!strcmp(featurestr, "iu_version")) {
> +                char *err;
> +
> +                iu_version = strtoll(val, &err, 0);
> +                if (!*val || *err) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                cpu->iu_version = iu_version;
> +#ifdef DEBUG_FEATURES
> +                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
> +#endif
> +            } else if (!strcmp(featurestr, "fpu_version")) {
> +                char *err;
> +
> +                fpu_version = strtol(val, &err, 0);
> +                if (!*val || *err) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                cpu->fpu_version = fpu_version;
> +#ifdef DEBUG_FEATURES
> +                fprintf(stderr, "fpu_version %x\n", fpu_version);
> +#endif
> +            } else if (!strcmp(featurestr, "mmu_version")) {
> +                char *err;
> +
> +                mmu_version = strtol(val, &err, 0);
> +                if (!*val || *err) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                cpu->mmu_version = mmu_version;
> +#ifdef DEBUG_FEATURES
> +                fprintf(stderr, "mmu_version %x\n", mmu_version);
> +#endif
> +            } else if (!strcmp(featurestr, "nwindows")) {
> +                char *err;
> +
> +                nwindows = strtol(val, &err, 0);
> +                if (!*val || *err || nwindows > MAX_NWINDOWS ||
> +                    nwindows < MIN_NWINDOWS) {
> +                    fprintf(stderr, "bad numerical value %s\n", val);
> +                    goto error;
> +                }
> +                cpu->nwindows = nwindows;
> +#ifdef DEBUG_FEATURES
> +                fprintf(stderr, "nwindows %d\n", nwindows);
> +#endif
> +            } else {
> +                fprintf(stderr, "unrecognized feature %s\n", featurestr);
> +                goto error;
> +            }
> +        } else {
> +            fprintf(stderr, "feature string `%s' not in format "
> +                    "(+feature|-feature|feature=xyz)\n", featurestr);
> +            goto error;
> +        }
> +        featurestr = strtok(NULL, ",");
> +    }
> +    cpu->features |= plus_features;
> +    cpu->features &= ~minus_features;
> +#ifdef DEBUG_FEATURES
> +    print_features(stderr, fprintf, cpu->features, NULL);
> +#endif
> +    free(s);
> +    return cpu;
> +
> + error:
> +    free(s);
> +    return NULL;
> +}
> +
> +CPUSPARCState *cpu_sparc_init(const char *cpu_model)
> +{
> +    SPARCCPU *cpu;
> +    CPUSPARCState *env;
> +
> +    cpu = cpu_sparc_find_by_name(cpu_model);
> +    if (cpu == NULL) {
> +        return NULL;
> +    }
> +    env = &cpu->env;
> +    env->cpu_model_str = cpu_model;
> +
> +    gen_intermediate_code_init(env);
> +
> +    qemu_init_vcpu(env);
> +
> +    return env;
> +}
> +
> +typedef struct SPARCCPUListState {
> +    fprintf_function cpu_fprintf;
> +    FILE *file;
> +} SPARCCPUListState;
> +
> +/* Sort alphabetically. */
> +static gint sparc_cpu_list_compare(gconstpointer a, gconstpointer b)
> +{
> +    ObjectClass *class_a = (ObjectClass *)a;
> +    ObjectClass *class_b = (ObjectClass *)b;
> +
> +    return strcasecmp(object_class_get_name(class_a),
> +                      object_class_get_name(class_b));
> +}
> +
> +static void sparc_cpu_list_entry(gpointer data, gpointer user_data)
> +{
> +    ObjectClass *klass = data;
> +    SPARCCPUClass *k = SPARC_CPU_CLASS(klass);
> +    SPARCCPUListState *s = user_data;
> +
> +    (*s->cpu_fprintf)(s->file, "Sparc %16s IU " TARGET_FMT_lx
> +                      " FPU %08x MMU %08x NWINS %d ",
> +                      object_class_get_name(klass),
> +                      k->iu_version,
> +                      k->fpu_version,
> +                      k->mmu_version,
> +                      k->nwindows);
> +    print_features(s->file, s->cpu_fprintf, CPU_DEFAULT_FEATURES &
> +                   ~k->features, "-");
> +    print_features(s->file, s->cpu_fprintf, ~CPU_DEFAULT_FEATURES &
> +                   k->features, "+");
> +    (*s->cpu_fprintf)(s->file, "\n");
> +}
> +
> +void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
> +{
> +    SPARCCPUListState s = {
> +        .file = f,
> +        .cpu_fprintf = cpu_fprintf,
> +    };
> +    GSList *list;
> +
> +    list = object_class_get_list(TYPE_SPARC_CPU, false);
> +    list = g_slist_sort(list, sparc_cpu_list_compare);
> +    g_slist_foreach(list, sparc_cpu_list_entry, &s);
> +    g_slist_free(list);
> +    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
> +    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
> +    (*cpu_fprintf)(f, "\n");
> +    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
> +    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
> +    (*cpu_fprintf)(f, "\n");
> +    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
> +                   "fpu_version mmu_version nwindows\n");
> +}
> +
> +static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
> +                         uint32_t cc)
> +{
> +    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
> +                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
> +                cc & PSR_CARRY ? 'C' : '-');
> +}
> +
> +#ifdef TARGET_SPARC64
> +#define REGS_PER_LINE 4
> +#else
> +#define REGS_PER_LINE 8
> +#endif
> +
> +void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
> +                    int flags)
> +{
> +    int i, x;
> +
> +    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
> +                env->npc);
> +    cpu_fprintf(f, "General Registers:\n");
> +
> +    for (i = 0; i < 8; i++) {
> +        if (i % REGS_PER_LINE == 0) {
> +            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
> +        }
> +        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
> +        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
> +            cpu_fprintf(f, "\n");
> +        }
> +    }
> +    cpu_fprintf(f, "\nCurrent Register Window:\n");
> +    for (x = 0; x < 3; x++) {
> +        for (i = 0; i < 8; i++) {
> +            if (i % REGS_PER_LINE == 0) {
> +                cpu_fprintf(f, "%%%c%d-%d: ",
> +                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
> +                            i, i + REGS_PER_LINE - 1);
> +            }
> +            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
> +            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
> +                cpu_fprintf(f, "\n");
> +            }
> +        }
> +    }
> +    cpu_fprintf(f, "\nFloating Point Registers:\n");
> +    for (i = 0; i < TARGET_DPREGS; i++) {
> +        if ((i & 3) == 0) {
> +            cpu_fprintf(f, "%%f%02d:", i * 2);
> +        }
> +        cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
> +        if ((i & 3) == 3) {
> +            cpu_fprintf(f, "\n");
> +        }
> +    }
> +#ifdef TARGET_SPARC64
> +    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
> +                (unsigned)cpu_get_ccr(env));
> +    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
> +    cpu_fprintf(f, " xcc: ");
> +    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
> +    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
> +                env->psrpil);
> +    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
> +                "cleanwin: %d cwp: %d\n",
> +                env->cansave, env->canrestore, env->otherwin, env->wstate,
> +                env->cleanwin, env->nwindows - 1 - env->cwp);
> +    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
> +                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
> +#else
> +    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
> +    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
> +    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
> +                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
> +                env->wim);
> +    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
> +                env->fsr, env->y);
> +#endif
> +}
> +
> +static void cpu_type_register(const SPARCCPUInfo *info)
> +{
> +    TypeInfo type = {
> +        .name = info->name,
> +        .parent = TYPE_SPARC_CPU,
> +        .instance_size = sizeof(SPARCCPU),
> +        .instance_init = sparc_cpu_initfn,
> +        .class_size = sizeof(SPARCCPUClass),
> +        .class_init = sparc_cpu_class_init,
> +        .class_data = (void *)info,
> +    };
> +
> +    type_register_static(&type);
> +}
> +
> +static const TypeInfo sparc_cpu_info = {
> +    .name = TYPE_SPARC_CPU,
> +    .parent = TYPE_CPU,
> +    .instance_size = sizeof(SPARCCPU),
> +    .abstract = true,
> +    .class_size = sizeof(SPARCCPUClass),
> +};
> +
> +static void sparc_cpu_register_types(void)
> +{
> +    int i;
> +
> +    type_register_static(&sparc_cpu_info);
> +    for (i = 0; i < ARRAY_SIZE(sparc_cpus); i++) {
> +        cpu_type_register(&sparc_cpus[i]);
> +    }
> +}
> +
> +type_init(sparc_cpu_register_types)
> diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
> index 86f9de6..10b05ac 100644
> --- a/target-sparc/cpu.h
> +++ b/target-sparc/cpu.h
> @@ -237,22 +237,6 @@ typedef struct trap_state {
>  } trap_state;
>  #endif
>
> -typedef struct sparc_def_t {
> -    const char *name;
> -    target_ulong iu_version;
> -    uint32_t fpu_version;
> -    uint32_t mmu_version;
> -    uint32_t mmu_bm;
> -    uint32_t mmu_ctpr_mask;
> -    uint32_t mmu_cxr_mask;
> -    uint32_t mmu_sfsr_mask;
> -    uint32_t mmu_trcr_mask;
> -    uint32_t mxcc_version;
> -    uint32_t features;
> -    uint32_t nwindows;
> -    uint32_t maxtl;
> -} sparc_def_t;
> -
>  #define CPU_FEATURE_FLOAT        (1 << 0)
>  #define CPU_FEATURE_FLOAT128     (1 << 1)
>  #define CPU_FEATURE_SWAP         (1 << 2)
> @@ -498,7 +482,6 @@ struct CPUSPARCState {
>  #define SOFTINT_INTRMASK (0xFFFE)
>  #define SOFTINT_REG_MASK (SOFTINT_STIMER|SOFTINT_INTRMASK|SOFTINT_TIMER)
>  #endif
> -    sparc_def_t *def;
>
>     void *irq_manager;
>     void (*qemu_irq_ack)(CPUSPARCState *env, void *irq_manager, int intno);
> @@ -507,6 +490,7 @@ struct CPUSPARCState {
>     uint32_t cache_control;
>  };
>
> +
>  #ifndef NO_CPU_IO_DEFS
>  /* cpu_init.c */
>  CPUSPARCState *cpu_sparc_init(const char *cpu_model);
> @@ -616,10 +600,12 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
>  #define MMU_MODE1_SUFFIX _kernel
>  #endif
>
> +static inline uint32_t sparc_env_get_features(CPUSPARCState *env);
> +
>  #if defined (TARGET_SPARC64)
>  static inline int cpu_has_hypervisor(CPUSPARCState *env1)
>  {
> -    return env1->def->features & CPU_FEATURE_HYPV;
> +    return sparc_env_get_features(env1) & CPU_FEATURE_HYPV;
>  }
>
>  static inline int cpu_hypervisor_mode(CPUSPARCState *env1)
> @@ -688,6 +674,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 */
> @@ -714,14 +701,14 @@ static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, target_ulong *pc,
>     if (env->pstate & PS_AM) {
>         *flags |= TB_FLAG_AM_ENABLED;
>     }
> -    if ((env->def->features & CPU_FEATURE_FLOAT) && (env->pstate & PS_PEF)
> -        && (env->fprs & FPRS_FEF)) {
> +    if ((sparc_env_get_features(env) & CPU_FEATURE_FLOAT)
> +        && (env->pstate & PS_PEF) && (env->fprs & FPRS_FEF)) {
>         *flags |= TB_FLAG_FPU_ENABLED;
>     }
>  #else
>     // FPU enable . Supervisor
>     *flags = env->psrs;
> -    if ((env->def->features & CPU_FEATURE_FLOAT) && env->psref) {
> +    if ((sparc_env_get_features(env) & CPU_FEATURE_FLOAT) && env->psref) {
>         *flags |= TB_FLAG_FPU_ENABLED;
>     }
>  #endif
> diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
> deleted file mode 100644
> index 29132fb..0000000
> --- a/target-sparc/cpu_init.c
> +++ /dev/null
> @@ -1,848 +0,0 @@
> -/*
> - * Sparc CPU init helpers
> - *
> - *  Copyright (c) 2003-2005 Fabrice Bellard
> - *
> - * 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 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/>.
> - */
> -
> -#include "cpu.h"
> -
> -//#define DEBUG_FEATURES
> -
> -static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
> -
> -void cpu_state_reset(CPUSPARCState *env)
> -{
> -    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
> -        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
> -        log_cpu_state(env, 0);
> -    }
> -
> -    tlb_flush(env, 1);
> -    env->cwp = 0;
> -#ifndef TARGET_SPARC64
> -    env->wim = 1;
> -#endif
> -    env->regwptr = env->regbase + (env->cwp * 16);
> -    CC_OP = CC_OP_FLAGS;
> -#if defined(CONFIG_USER_ONLY)
> -#ifdef TARGET_SPARC64
> -    env->cleanwin = env->nwindows - 2;
> -    env->cansave = env->nwindows - 2;
> -    env->pstate = PS_RMO | PS_PEF | PS_IE;
> -    env->asi = 0x82; /* Primary no-fault */
> -#endif
> -#else
> -#if !defined(TARGET_SPARC64)
> -    env->psret = 0;
> -    env->psrs = 1;
> -    env->psrps = 1;
> -#endif
> -#ifdef TARGET_SPARC64
> -    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
> -    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
> -    env->tl = env->maxtl;
> -    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
> -    env->lsu = 0;
> -#else
> -    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
> -    env->mmuregs[0] |= env->def->mmu_bm;
> -#endif
> -    env->pc = 0;
> -    env->npc = env->pc + 4;
> -#endif
> -    env->cache_control = 0;
> -}
> -
> -static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
> -{
> -    sparc_def_t def1, *def = &def1;
> -
> -    if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
> -        return -1;
> -    }
> -
> -    env->def = g_new0(sparc_def_t, 1);
> -    memcpy(env->def, def, sizeof(*def));
> -#if defined(CONFIG_USER_ONLY)
> -    if ((env->def->features & CPU_FEATURE_FLOAT)) {
> -        env->def->features |= CPU_FEATURE_FLOAT128;
> -    }
> -#endif
> -    env->cpu_model_str = cpu_model;
> -    env->version = def->iu_version;
> -    env->fsr = def->fpu_version;
> -    env->nwindows = def->nwindows;
> -#if !defined(TARGET_SPARC64)
> -    env->mmuregs[0] |= def->mmu_version;
> -    cpu_sparc_set_id(env, 0);
> -    env->mxccregs[7] |= def->mxcc_version;
> -#else
> -    env->mmu_version = def->mmu_version;
> -    env->maxtl = def->maxtl;
> -    env->version |= def->maxtl << 8;
> -    env->version |= def->nwindows - 1;
> -#endif
> -    return 0;
> -}
> -
> -static void cpu_sparc_close(CPUSPARCState *env)
> -{
> -    g_free(env->def);
> -    g_free(env);
> -}
> -
> -CPUSPARCState *cpu_sparc_init(const char *cpu_model)
> -{
> -    CPUSPARCState *env;
> -
> -    env = g_new0(CPUSPARCState, 1);
> -    cpu_exec_init(env);
> -
> -    gen_intermediate_code_init(env);
> -
> -    if (cpu_sparc_register(env, cpu_model) < 0) {
> -        cpu_sparc_close(env);
> -        return NULL;
> -    }
> -    qemu_init_vcpu(env);
> -
> -    return env;
> -}
> -
> -void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
> -{
> -#if !defined(TARGET_SPARC64)
> -    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
> -#endif
> -}
> -
> -static const sparc_def_t sparc_defs[] = {
> -#ifdef TARGET_SPARC64
> -    {
> -        .name = "Fujitsu Sparc64",
> -        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 4,
> -        .maxtl = 4,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Fujitsu Sparc64 III",
> -        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 5,
> -        .maxtl = 4,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Fujitsu Sparc64 IV",
> -        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Fujitsu Sparc64 V",
> -        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI UltraSparc I",
> -        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI UltraSparc II",
> -        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI UltraSparc IIi",
> -        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI UltraSparc IIe",
> -        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Sun UltraSparc III",
> -        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Sun UltraSparc III Cu",
> -        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_3,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Sun UltraSparc IIIi",
> -        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Sun UltraSparc IV",
> -        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_4,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Sun UltraSparc IV+",
> -        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
> -    },
> -    {
> -        .name = "Sun UltraSparc IIIi+",
> -        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_3,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Sun UltraSparc T1",
> -        /* defined in sparc_ifu_fdp.v and ctu.h */
> -        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_sun4v,
> -        .nwindows = 8,
> -        .maxtl = 6,
> -        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
> -        | CPU_FEATURE_GL,
> -    },
> -    {
> -        .name = "Sun UltraSparc T2",
> -        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
> -        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_sun4v,
> -        .nwindows = 8,
> -        .maxtl = 6,
> -        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
> -        | CPU_FEATURE_GL,
> -    },
> -    {
> -        .name = "NEC UltraSparc I",
> -        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
> -        .fpu_version = 0x00000000,
> -        .mmu_version = mmu_us_12,
> -        .nwindows = 8,
> -        .maxtl = 5,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -#else
> -    {
> -        .name = "Fujitsu MB86900",
> -        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
> -        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> -        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 7,
> -        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
> -    },
> -    {
> -        .name = "Fujitsu MB86904",
> -        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
> -        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> -        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x00ffffc0,
> -        .mmu_cxr_mask = 0x000000ff,
> -        .mmu_sfsr_mask = 0x00016fff,
> -        .mmu_trcr_mask = 0x00ffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Fujitsu MB86907",
> -        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
> -        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> -        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0xffffffc0,
> -        .mmu_cxr_mask = 0x000000ff,
> -        .mmu_sfsr_mask = 0x00016fff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "LSI L64811",
> -        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
> -        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
> -        .mmu_version = 0x10 << 24,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
> -        CPU_FEATURE_FSMULD,
> -    },
> -    {
> -        .name = "Cypress CY7C601",
> -        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
> -        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
> -        .mmu_version = 0x10 << 24,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
> -        CPU_FEATURE_FSMULD,
> -    },
> -    {
> -        .name = "Cypress CY7C611",
> -        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
> -        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
> -        .mmu_version = 0x10 << 24,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
> -        CPU_FEATURE_FSMULD,
> -    },
> -    {
> -        .name = "TI MicroSparc I",
> -        .iu_version = 0x41000000,
> -        .fpu_version = 4 << 17,
> -        .mmu_version = 0x41000000,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0x00016fff,
> -        .mmu_trcr_mask = 0x0000003f,
> -        .nwindows = 7,
> -        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
> -        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
> -        CPU_FEATURE_FMUL,
> -    },
> -    {
> -        .name = "TI MicroSparc II",
> -        .iu_version = 0x42000000,
> -        .fpu_version = 4 << 17,
> -        .mmu_version = 0x02000000,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x00ffffc0,
> -        .mmu_cxr_mask = 0x000000ff,
> -        .mmu_sfsr_mask = 0x00016fff,
> -        .mmu_trcr_mask = 0x00ffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI MicroSparc IIep",
> -        .iu_version = 0x42000000,
> -        .fpu_version = 4 << 17,
> -        .mmu_version = 0x04000000,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x00ffffc0,
> -        .mmu_cxr_mask = 0x000000ff,
> -        .mmu_sfsr_mask = 0x00016bff,
> -        .mmu_trcr_mask = 0x00ffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI SuperSparc 40", /* STP1020NPGA */
> -        .iu_version = 0x41000000, /* SuperSPARC 2.x */
> -        .fpu_version = 0 << 17,
> -        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
> -        .mmu_bm = 0x00002000,
> -        .mmu_ctpr_mask = 0xffffffc0,
> -        .mmu_cxr_mask = 0x0000ffff,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI SuperSparc 50", /* STP1020PGA */
> -        .iu_version = 0x40000000, /* SuperSPARC 3.x */
> -        .fpu_version = 0 << 17,
> -        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
> -        .mmu_bm = 0x00002000,
> -        .mmu_ctpr_mask = 0xffffffc0,
> -        .mmu_cxr_mask = 0x0000ffff,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI SuperSparc 51",
> -        .iu_version = 0x40000000, /* SuperSPARC 3.x */
> -        .fpu_version = 0 << 17,
> -        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
> -        .mmu_bm = 0x00002000,
> -        .mmu_ctpr_mask = 0xffffffc0,
> -        .mmu_cxr_mask = 0x0000ffff,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .mxcc_version = 0x00000104,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI SuperSparc 60", /* STP1020APGA */
> -        .iu_version = 0x40000000, /* SuperSPARC 3.x */
> -        .fpu_version = 0 << 17,
> -        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
> -        .mmu_bm = 0x00002000,
> -        .mmu_ctpr_mask = 0xffffffc0,
> -        .mmu_cxr_mask = 0x0000ffff,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI SuperSparc 61",
> -        .iu_version = 0x44000000, /* SuperSPARC 3.x */
> -        .fpu_version = 0 << 17,
> -        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
> -        .mmu_bm = 0x00002000,
> -        .mmu_ctpr_mask = 0xffffffc0,
> -        .mmu_cxr_mask = 0x0000ffff,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .mxcc_version = 0x00000104,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "TI SuperSparc II",
> -        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
> -        .fpu_version = 0 << 17,
> -        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
> -        .mmu_bm = 0x00002000,
> -        .mmu_ctpr_mask = 0xffffffc0,
> -        .mmu_cxr_mask = 0x0000ffff,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .mxcc_version = 0x00000104,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Ross RT625",
> -        .iu_version = 0x1e000000,
> -        .fpu_version = 1 << 17,
> -        .mmu_version = 0x1e000000,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "Ross RT620",
> -        .iu_version = 0x1f000000,
> -        .fpu_version = 1 << 17,
> -        .mmu_version = 0x1f000000,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "BIT B5010",
> -        .iu_version = 0x20000000,
> -        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
> -        .mmu_version = 0x20000000,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
> -        CPU_FEATURE_FSMULD,
> -    },
> -    {
> -        .name = "Matsushita MN10501",
> -        .iu_version = 0x50000000,
> -        .fpu_version = 0 << 17,
> -        .mmu_version = 0x50000000,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
> -        CPU_FEATURE_FSMULD,
> -    },
> -    {
> -        .name = "Weitek W8601",
> -        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
> -        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
> -        .mmu_version = 0x10 << 24,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES,
> -    },
> -    {
> -        .name = "LEON2",
> -        .iu_version = 0xf2000000,
> -        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> -        .mmu_version = 0xf2000000,
> -        .mmu_bm = 0x00004000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
> -    },
> -    {
> -        .name = "LEON3",
> -        .iu_version = 0xf3000000,
> -        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
> -        .mmu_version = 0xf3000000,
> -        .mmu_bm = 0x00000000,
> -        .mmu_ctpr_mask = 0x007ffff0,
> -        .mmu_cxr_mask = 0x0000003f,
> -        .mmu_sfsr_mask = 0xffffffff,
> -        .mmu_trcr_mask = 0xffffffff,
> -        .nwindows = 8,
> -        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
> -        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
> -    },
> -#endif
> -};
> -
> -static const char * const feature_name[] = {
> -    "float",
> -    "float128",
> -    "swap",
> -    "mul",
> -    "div",
> -    "flush",
> -    "fsqrt",
> -    "fmul",
> -    "vis1",
> -    "vis2",
> -    "fsmuld",
> -    "hypv",
> -    "cmt",
> -    "gl",
> -};
> -
> -static void print_features(FILE *f, fprintf_function cpu_fprintf,
> -                           uint32_t features, const char *prefix)
> -{
> -    unsigned int i;
> -
> -    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
> -        if (feature_name[i] && (features & (1 << i))) {
> -            if (prefix) {
> -                (*cpu_fprintf)(f, "%s", prefix);
> -            }
> -            (*cpu_fprintf)(f, "%s ", feature_name[i]);
> -        }
> -    }
> -}
> -
> -static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
> -{
> -    unsigned int i;
> -
> -    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
> -        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
> -            *features |= 1 << i;
> -            return;
> -        }
> -    }
> -    fprintf(stderr, "CPU feature %s not found\n", flagname);
> -}
> -
> -static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
> -{
> -    unsigned int i;
> -    const sparc_def_t *def = NULL;
> -    char *s = strdup(cpu_model);
> -    char *featurestr, *name = strtok(s, ",");
> -    uint32_t plus_features = 0;
> -    uint32_t minus_features = 0;
> -    uint64_t iu_version;
> -    uint32_t fpu_version, mmu_version, nwindows;
> -
> -    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
> -        if (strcasecmp(name, sparc_defs[i].name) == 0) {
> -            def = &sparc_defs[i];
> -        }
> -    }
> -    if (!def) {
> -        goto error;
> -    }
> -    memcpy(cpu_def, def, sizeof(*def));
> -
> -    featurestr = strtok(NULL, ",");
> -    while (featurestr) {
> -        char *val;
> -
> -        if (featurestr[0] == '+') {
> -            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
> -        } else if (featurestr[0] == '-') {
> -            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
> -        } else if ((val = strchr(featurestr, '='))) {
> -            *val = 0; val++;
> -            if (!strcmp(featurestr, "iu_version")) {
> -                char *err;
> -
> -                iu_version = strtoll(val, &err, 0);
> -                if (!*val || *err) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                cpu_def->iu_version = iu_version;
> -#ifdef DEBUG_FEATURES
> -                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
> -#endif
> -            } else if (!strcmp(featurestr, "fpu_version")) {
> -                char *err;
> -
> -                fpu_version = strtol(val, &err, 0);
> -                if (!*val || *err) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                cpu_def->fpu_version = fpu_version;
> -#ifdef DEBUG_FEATURES
> -                fprintf(stderr, "fpu_version %x\n", fpu_version);
> -#endif
> -            } else if (!strcmp(featurestr, "mmu_version")) {
> -                char *err;
> -
> -                mmu_version = strtol(val, &err, 0);
> -                if (!*val || *err) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                cpu_def->mmu_version = mmu_version;
> -#ifdef DEBUG_FEATURES
> -                fprintf(stderr, "mmu_version %x\n", mmu_version);
> -#endif
> -            } else if (!strcmp(featurestr, "nwindows")) {
> -                char *err;
> -
> -                nwindows = strtol(val, &err, 0);
> -                if (!*val || *err || nwindows > MAX_NWINDOWS ||
> -                    nwindows < MIN_NWINDOWS) {
> -                    fprintf(stderr, "bad numerical value %s\n", val);
> -                    goto error;
> -                }
> -                cpu_def->nwindows = nwindows;
> -#ifdef DEBUG_FEATURES
> -                fprintf(stderr, "nwindows %d\n", nwindows);
> -#endif
> -            } else {
> -                fprintf(stderr, "unrecognized feature %s\n", featurestr);
> -                goto error;
> -            }
> -        } else {
> -            fprintf(stderr, "feature string `%s' not in format "
> -                    "(+feature|-feature|feature=xyz)\n", featurestr);
> -            goto error;
> -        }
> -        featurestr = strtok(NULL, ",");
> -    }
> -    cpu_def->features |= plus_features;
> -    cpu_def->features &= ~minus_features;
> -#ifdef DEBUG_FEATURES
> -    print_features(stderr, fprintf, cpu_def->features, NULL);
> -#endif
> -    free(s);
> -    return 0;
> -
> - error:
> -    free(s);
> -    return -1;
> -}
> -
> -void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
> -{
> -    unsigned int i;
> -
> -    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
> -        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
> -                       " FPU %08x MMU %08x NWINS %d ",
> -                       sparc_defs[i].name,
> -                       sparc_defs[i].iu_version,
> -                       sparc_defs[i].fpu_version,
> -                       sparc_defs[i].mmu_version,
> -                       sparc_defs[i].nwindows);
> -        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
> -                       ~sparc_defs[i].features, "-");
> -        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
> -                       sparc_defs[i].features, "+");
> -        (*cpu_fprintf)(f, "\n");
> -    }
> -    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
> -    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
> -    (*cpu_fprintf)(f, "\n");
> -    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
> -    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
> -    (*cpu_fprintf)(f, "\n");
> -    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
> -                   "fpu_version mmu_version nwindows\n");
> -}
> -
> -static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
> -                         uint32_t cc)
> -{
> -    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
> -                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
> -                cc & PSR_CARRY ? 'C' : '-');
> -}
> -
> -#ifdef TARGET_SPARC64
> -#define REGS_PER_LINE 4
> -#else
> -#define REGS_PER_LINE 8
> -#endif
> -
> -void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
> -                    int flags)
> -{
> -    int i, x;
> -
> -    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
> -                env->npc);
> -    cpu_fprintf(f, "General Registers:\n");
> -
> -    for (i = 0; i < 8; i++) {
> -        if (i % REGS_PER_LINE == 0) {
> -            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
> -        }
> -        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
> -        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
> -            cpu_fprintf(f, "\n");
> -        }
> -    }
> -    cpu_fprintf(f, "\nCurrent Register Window:\n");
> -    for (x = 0; x < 3; x++) {
> -        for (i = 0; i < 8; i++) {
> -            if (i % REGS_PER_LINE == 0) {
> -                cpu_fprintf(f, "%%%c%d-%d: ",
> -                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
> -                            i, i + REGS_PER_LINE - 1);
> -            }
> -            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
> -            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
> -                cpu_fprintf(f, "\n");
> -            }
> -        }
> -    }
> -    cpu_fprintf(f, "\nFloating Point Registers:\n");
> -    for (i = 0; i < TARGET_DPREGS; i++) {
> -        if ((i & 3) == 0) {
> -            cpu_fprintf(f, "%%f%02d:", i * 2);
> -        }
> -        cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
> -        if ((i & 3) == 3) {
> -            cpu_fprintf(f, "\n");
> -        }
> -    }
> -#ifdef TARGET_SPARC64
> -    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
> -                (unsigned)cpu_get_ccr(env));
> -    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
> -    cpu_fprintf(f, " xcc: ");
> -    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
> -    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
> -                env->psrpil);
> -    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
> -                "cleanwin: %d cwp: %d\n",
> -                env->cansave, env->canrestore, env->otherwin, env->wstate,
> -                env->cleanwin, env->nwindows - 1 - env->cwp);
> -    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
> -                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
> -#else
> -    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
> -    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
> -    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
> -                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
> -                env->wim);
> -    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
> -                env->fsr, env->y);
> -#endif
> -}
> diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
> index 5e33d50..8d454ae 100644
> --- a/target-sparc/int32_helper.c
> +++ b/target-sparc/int32_helper.c
> @@ -60,6 +60,9 @@ static const char * const excp_names[0x80] = {
>
>  void do_interrupt(CPUSPARCState *env)
>  {
> +#if !defined(CONFIG_USER_ONLY)
> +    SPARCCPU *cpu = sparc_env_get_cpu(env);
> +#endif
>     int cwp, intno = env->exception_index;
>
>  #ifdef DEBUG_PCALL
> @@ -102,7 +105,7 @@ void do_interrupt(CPUSPARCState *env)
>  #if !defined(CONFIG_USER_ONLY)
>     if (env->psret == 0) {
>         if (env->exception_index == 0x80 &&
> -            env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
> +            cpu->features & CPU_FEATURE_TA0_SHUTDOWN) {
>             qemu_system_shutdown_request();
>         } else {
>             cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
> diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
> index 48d433c..806f45c 100644
> --- a/target-sparc/ldst_helper.c
> +++ b/target-sparc/ldst_helper.c
> @@ -438,6 +438,7 @@ static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
>
>  uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
>  {
> +    SPARCCPU *cpu = sparc_env_get_cpu(env);
>     uint64_t ret = 0;
>  #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
>     uint32_t last_addr = addr;
> @@ -450,7 +451,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
>         case 0x00:          /* Leon3 Cache Control */
>         case 0x08:          /* Leon3 Instruction Cache config */
>         case 0x0C:          /* Leon3 Date Cache config */
> -            if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
> +            if (cpu->features & CPU_FEATURE_CACHE_CTRL) {
>                 ret = leon3_cache_control_ld(addr, size);
>             }
>             break;
> @@ -696,6 +697,8 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
>
>  void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
>  {
> +    SPARCCPU *cpu = sparc_env_get_cpu(env);
> +    SPARCCPUClass *klass = SPARC_CPU_GET_CLASS(cpu);
>     helper_check_align(addr, size - 1);
>     switch (asi) {
>     case 2: /* SuperSparc MXCC registers and Leon3 cache control */
> @@ -703,7 +706,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
>         case 0x00:          /* Leon3 Cache Control */
>         case 0x08:          /* Leon3 Instruction Cache config */
>         case 0x0C:          /* Leon3 Date Cache config */
> -            if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
> +            if (cpu->features & CPU_FEATURE_CACHE_CTRL) {
>                 leon3_cache_control_st(addr, val, size);
>             }
>             break;
> @@ -853,16 +856,16 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
>                     (val & 0x00ffffff);
>                 /* Mappings generated during no-fault mode or MMU
>                    disabled mode are invalid in normal mode */
> -                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
> -                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) {
> +                if ((oldreg & (MMU_E | MMU_NF | klass->mmu_bm)) !=
> +                    (env->mmuregs[reg] & (MMU_E | MMU_NF | klass->mmu_bm))) {
>                     tlb_flush(env, 1);
>                 }
>                 break;
>             case 1: /* Context Table Pointer Register */
> -                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
> +                env->mmuregs[reg] = val & klass->mmu_ctpr_mask;
>                 break;
>             case 2: /* Context Register */
> -                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
> +                env->mmuregs[reg] = val & klass->mmu_cxr_mask;
>                 if (oldreg != env->mmuregs[reg]) {
>                     /* we flush when the MMU context changes because
>                        QEMU has no MMU context support */
> @@ -873,11 +876,11 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
>             case 4: /* Synchronous Fault Address Register */
>                 break;
>             case 0x10: /* TLB Replacement Control Register */
> -                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
> +                env->mmuregs[reg] = val & klass->mmu_trcr_mask;
>                 break;
>             case 0x13: /* Synchronous Fault Status Register with Read
>                           and Clear */
> -                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
> +                env->mmuregs[3] = val & klass->mmu_sfsr_mask;
>                 break;
>             case 0x14: /* Synchronous Fault Address Register */
>                 env->mmuregs[4] = val;
> diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
> index 11fb9f5..83b050e 100644
> --- a/target-sparc/mmu_helper.c
> +++ b/target-sparc/mmu_helper.c
> @@ -81,6 +81,8 @@ static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical
>                                 target_ulong address, int rw, int mmu_idx,
>                                 target_ulong *page_size)
>  {
> +    SPARCCPU *cpu = sparc_env_get_cpu(env);
> +    SPARCCPUClass *klass = SPARC_CPU_GET_CLASS(cpu);
>     int access_perms = 0;
>     target_phys_addr_t pde_ptr;
>     uint32_t pde;
> @@ -92,7 +94,7 @@ static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical
>     if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
>         *page_size = TARGET_PAGE_SIZE;
>         /* Boot mode: instruction fetches are taken from PROM */
> -        if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
> +        if (rw == 2 && (env->mmuregs[0] & klass->mmu_bm)) {
>             *physical = env->prom_addr | (address & 0x7ffffULL);
>             *prot = PAGE_READ | PAGE_EXEC;
>             return 0;
> diff --git a/target-sparc/translate.c b/target-sparc/translate.c
> index ef176e9..a737279 100644
> --- a/target-sparc/translate.c
> +++ b/target-sparc/translate.c
> @@ -81,7 +81,7 @@ typedef struct DisasContext {
>     int singlestep;
>     uint32_t cc_op;  /* current CC operation */
>     struct TranslationBlock *tb;
> -    sparc_def_t *def;
> +    SPARCCPU *def;
>     TCGv_i32 t32[3];
>     int n_t32;
>  } DisasContext;
> @@ -5247,7 +5247,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
>     dc->npc = (target_ulong) tb->cs_base;
>     dc->cc_op = CC_OP_DYNAMIC;
>     dc->mem_idx = cpu_mmu_index(env);
> -    dc->def = env->def;
> +    dc->def = sparc_env_get_cpu(env);
>     dc->fpu_enabled = tb_fpu_enabled(tb->flags);
>     dc->address_mask_32bit = tb_am_enabled(tb->flags);
>     dc->singlestep = (env->singlestep_enabled || singlestep);
> diff --git a/target-sparc/win_helper.c b/target-sparc/win_helper.c
> index 3e82eb7..02376fc 100644
> --- a/target-sparc/win_helper.c
> +++ b/target-sparc/win_helper.c
> @@ -300,10 +300,11 @@ static inline uint64_t *get_gregset(CPUSPARCState *env, uint32_t pstate)
>
>  void cpu_change_pstate(CPUSPARCState *env, uint32_t new_pstate)
>  {
> +    SPARCCPU *cpu = sparc_env_get_cpu(env);
>     uint32_t pstate_regs, new_pstate_regs;
>     uint64_t *src, *dst;
>
> -    if (env->def->features & CPU_FEATURE_GL) {
> +    if (cpu->features & CPU_FEATURE_GL) {
>         /* PS_AG is not implemented in this case */
>         new_pstate &= ~PS_AG;
>     }
> --
> 1.7.7
>
Andreas Färber March 23, 2012, 5:27 p.m. UTC | #2
Am 14.03.2012 21:16, schrieb Blue Swirl:
> On Wed, Mar 14, 2012 at 17:53, Andreas Färber <afaerber@suse.de> wrote:
>> diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
>> new file mode 100644
>> index 0000000..15dcf84
>> --- /dev/null
>> +++ b/target-sparc/cpu-qom.h
[...]
>> +/**
>> + * 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);
>> +
>> +    target_ulong iu_version;
>> +    uint32_t fpu_version;
>> +    uint32_t mmu_version;
>> +    uint32_t mmu_bm;
>> +    uint32_t mmu_ctpr_mask;
>> +    uint32_t mmu_cxr_mask;
>> +    uint32_t mmu_sfsr_mask;
>> +    uint32_t mmu_trcr_mask;
>> +    uint32_t mxcc_version;
>> +    uint32_t features;
>> +    uint32_t nwindows;
>> +    uint32_t maxtl;
>> +} SPARCCPUClass;
>> +
>> +/**
>> + * SPARCCPU:
>> + * @env: Legacy CPU state.
>> + *
>> + * A SPARC CPU.
>> + */
>> +typedef struct SPARCCPU {
>> +    /*< private >*/
>> +    CPUState parent_obj;
>> +    /*< public >*/
>> +
>> +    CPUSPARCState env;
>> +
>> +    target_ulong iu_version;
>> +    uint32_t fpu_version;
>> +    uint32_t mmu_version;
>> +    uint32_t features;
>> +    uint32_t nwindows;
>> +} SPARCCPU;
> 
> The fields do not look correct at all, the same fields are in both
> structs.

Formerly you had the model of an array of sparc_def_t structs, which you
would duplicate and then associate with CPUSPARCState, modifying the
duplicate.
SPARCCPUClass exists only once though. Therefore we cannot modify
classes based on command line parameters and must do so on the instance
instead. I have therefore duplicated some fields from class to instance
as you have noticed, initialized the object's value from the class' and
let any -cpu options modify the latter.
The same pattern has been used for arm and i386. On arm my v5 postpones
this by doing a bare-bones conversion for now; on x86 the only request
so far was to set the values via QOM properties.

> Moreover Sparc32 and Sparc64 fields are mixed. Maybe I don't
> fully understand the conversion.

Mixed fields likely means they were mixed in your original code. It is a
mostly mechanical conversion.

> Would it be possible to make a common parent class which is then
> specialized by Sparc32 and Sparc64 classes? There are many common
> fields but also many 32/64 specific ones. Also cpu_common.c, cpu32.c
> and cpu64.c to avoid #ifdeffery?

That is possible, but I would ask that you do such split-ups later.
Discussions for arm and ppc have shown that the structure of subclasses
in lack of multi-inheritence can be a tricky and controversial issue and
requires a lot of target knowledge that I do not posses for sparc.
Also, restructuring target code, e.g., into multiple files is orthogonal
to the goal of QOM'ifying all target CPUs and doing cleanups in common code.

If you think this is heading into a totally wrong direction due to some
in-progress work of yours, we could strip it down like target-arm v5,
but ATM I don't believe so. ;)

Andreas
Blue Swirl March 24, 2012, 1:19 p.m. UTC | #3
On Fri, Mar 23, 2012 at 17:27, Andreas Färber <afaerber@suse.de> wrote:
> Am 14.03.2012 21:16, schrieb Blue Swirl:
>> On Wed, Mar 14, 2012 at 17:53, Andreas Färber <afaerber@suse.de> wrote:
>>> diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
>>> new file mode 100644
>>> index 0000000..15dcf84
>>> --- /dev/null
>>> +++ b/target-sparc/cpu-qom.h
> [...]
>>> +/**
>>> + * 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);
>>> +
>>> +    target_ulong iu_version;
>>> +    uint32_t fpu_version;
>>> +    uint32_t mmu_version;
>>> +    uint32_t mmu_bm;
>>> +    uint32_t mmu_ctpr_mask;
>>> +    uint32_t mmu_cxr_mask;
>>> +    uint32_t mmu_sfsr_mask;
>>> +    uint32_t mmu_trcr_mask;
>>> +    uint32_t mxcc_version;
>>> +    uint32_t features;
>>> +    uint32_t nwindows;
>>> +    uint32_t maxtl;
>>> +} SPARCCPUClass;
>>> +
>>> +/**
>>> + * SPARCCPU:
>>> + * @env: Legacy CPU state.
>>> + *
>>> + * A SPARC CPU.
>>> + */
>>> +typedef struct SPARCCPU {
>>> +    /*< private >*/
>>> +    CPUState parent_obj;
>>> +    /*< public >*/
>>> +
>>> +    CPUSPARCState env;
>>> +
>>> +    target_ulong iu_version;
>>> +    uint32_t fpu_version;
>>> +    uint32_t mmu_version;
>>> +    uint32_t features;
>>> +    uint32_t nwindows;
>>> +} SPARCCPU;
>>
>> The fields do not look correct at all, the same fields are in both
>> structs.
>
> Formerly you had the model of an array of sparc_def_t structs, which you
> would duplicate and then associate with CPUSPARCState, modifying the
> duplicate.
> SPARCCPUClass exists only once though. Therefore we cannot modify
> classes based on command line parameters and must do so on the instance
> instead. I have therefore duplicated some fields from class to instance
> as you have noticed, initialized the object's value from the class' and
> let any -cpu options modify the latter.
> The same pattern has been used for arm and i386. On arm my v5 postpones
> this by doing a bare-bones conversion for now; on x86 the only request
> so far was to set the values via QOM properties.
>
>> Moreover Sparc32 and Sparc64 fields are mixed. Maybe I don't
>> fully understand the conversion.
>
> Mixed fields likely means they were mixed in your original code. It is a
> mostly mechanical conversion.

I see, this is only for the sparc_def_t structure.

>> Would it be possible to make a common parent class which is then
>> specialized by Sparc32 and Sparc64 classes? There are many common
>> fields but also many 32/64 specific ones. Also cpu_common.c, cpu32.c
>> and cpu64.c to avoid #ifdeffery?
>
> That is possible, but I would ask that you do such split-ups later.
> Discussions for arm and ppc have shown that the structure of subclasses
> in lack of multi-inheritence can be a tricky and controversial issue and
> requires a lot of target knowledge that I do not posses for sparc.
> Also, restructuring target code, e.g., into multiple files is orthogonal
> to the goal of QOM'ifying all target CPUs and doing cleanups in common code.
>
> If you think this is heading into a totally wrong direction due to some
> in-progress work of yours, we could strip it down like target-arm v5,
> but ATM I don't believe so. ;)

No, the patch is fine as is.

> Andreas
>
> --
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
diff mbox

Patch

diff --git a/Makefile.target b/Makefile.target
index 82171ca..1c6ed12 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -100,7 +100,7 @@  libobj-$(TARGET_S390X) += cpu.o
 libobj-$(TARGET_SH4) += 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/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
new file mode 100644
index 0000000..15dcf84
--- /dev/null
+++ b/target-sparc/cpu-qom.h
@@ -0,0 +1,95 @@ 
+/*
+ * 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"
+
+#define TYPE_SPARC_CPU "sparc-cpu"
+
+#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);
+
+    target_ulong iu_version;
+    uint32_t fpu_version;
+    uint32_t mmu_version;
+    uint32_t mmu_bm;
+    uint32_t mmu_ctpr_mask;
+    uint32_t mmu_cxr_mask;
+    uint32_t mmu_sfsr_mask;
+    uint32_t mmu_trcr_mask;
+    uint32_t mxcc_version;
+    uint32_t features;
+    uint32_t nwindows;
+    uint32_t maxtl;
+} SPARCCPUClass;
+
+/**
+ * SPARCCPU:
+ * @env: Legacy CPU state.
+ *
+ * A SPARC CPU.
+ */
+typedef struct SPARCCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUSPARCState env;
+
+    target_ulong iu_version;
+    uint32_t fpu_version;
+    uint32_t mmu_version;
+    uint32_t features;
+    uint32_t nwindows;
+} 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))
+
+static inline uint32_t sparc_env_get_features(CPUSPARCState *env)
+{
+    return sparc_env_get_cpu(env)->features;
+}
+
+
+#endif
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
new file mode 100644
index 0000000..4c960a9
--- /dev/null
+++ b/target-sparc/cpu.c
@@ -0,0 +1,949 @@ 
+/*
+ * Sparc CPU init helpers
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *  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 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/>.
+ */
+
+#include "cpu-qom.h"
+
+//#define DEBUG_FEATURES
+
+void cpu_state_reset(CPUSPARCState *env)
+{
+    cpu_reset(ENV_GET_CPU(env));
+}
+
+static void sparc_cpu_reset(CPUState *c)
+{
+    SPARCCPU *cpu = SPARC_CPU(c);
+    SPARCCPUClass *klass = 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);
+    }
+
+    klass->parent_reset(c);
+
+    tlb_flush(env, 1);
+    env->cwp = 0;
+#ifndef TARGET_SPARC64
+    env->wim = 1;
+#endif
+    env->regwptr = env->regbase + (env->cwp * 16);
+    CC_OP = CC_OP_FLAGS;
+#if defined(CONFIG_USER_ONLY)
+#ifdef TARGET_SPARC64
+    env->cleanwin = env->nwindows - 2;
+    env->cansave = env->nwindows - 2;
+    env->pstate = PS_RMO | PS_PEF | PS_IE;
+    env->asi = 0x82; /* Primary no-fault */
+#endif
+#else
+#if !defined(TARGET_SPARC64)
+    env->psret = 0;
+    env->psrs = 1;
+    env->psrps = 1;
+#endif
+#ifdef TARGET_SPARC64
+    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
+    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
+    env->tl = env->maxtl;
+    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
+    env->lsu = 0;
+#else
+    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
+    env->mmuregs[0] |= klass->mmu_bm;
+#endif
+    env->pc = 0;
+    env->npc = env->pc + 4;
+#endif
+    env->cache_control = 0;
+}
+
+static void sparc_cpu_initfn(Object *obj)
+{
+    SPARCCPU *cpu = SPARC_CPU(obj);
+    SPARCCPUClass *klass = SPARC_CPU_GET_CLASS(cpu);
+    CPUSPARCState *env = &cpu->env;
+
+    memset(env, 0, sizeof(*env));
+    cpu_exec_init(env);
+
+#if defined(CONFIG_USER_ONLY)
+    if ((cpu->features & CPU_FEATURE_FLOAT)) {
+        cpu->features |= CPU_FEATURE_FLOAT128;
+    }
+#endif
+    env->version = cpu->iu_version;
+    env->fsr = cpu->fpu_version;
+    env->nwindows = cpu->nwindows;
+#if !defined(TARGET_SPARC64)
+    env->mmuregs[0] |= cpu->mmu_version;
+    cpu_sparc_set_id(env, 0);
+    env->mxccregs[7] |= klass->mxcc_version;
+#else
+    env->mmu_version = cpu->mmu_version;
+    env->maxtl = klass->maxtl;
+    env->version |= klass->maxtl << 8;
+    env->version |= cpu->nwindows - 1;
+#endif
+}
+
+void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
+{
+#if !defined(TARGET_SPARC64)
+    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
+#endif
+}
+
+/* CPU models */
+
+typedef struct SPARCCPUInfo {
+    const char *name;
+    target_ulong iu_version;
+    uint32_t fpu_version;
+    uint32_t mmu_version;
+    uint32_t mmu_bm;
+    uint32_t mmu_ctpr_mask;
+    uint32_t mmu_cxr_mask;
+    uint32_t mmu_sfsr_mask;
+    uint32_t mmu_trcr_mask;
+    uint32_t mxcc_version;
+    uint32_t features;
+    uint32_t nwindows;
+    uint32_t maxtl;
+} SPARCCPUInfo;
+
+static void sparc_cpu_class_init(ObjectClass *klass, void *data)
+{
+    CPUClass *cpu_class = CPU_CLASS(klass);
+    SPARCCPUClass *k = SPARC_CPU_CLASS(klass);
+    const SPARCCPUInfo *info = data;
+
+    k->parent_reset = cpu_class->reset;
+    cpu_class->reset = sparc_cpu_reset;
+
+    k->iu_version = info->iu_version;
+    k->fpu_version = info->fpu_version;
+    k->mmu_version = info->mmu_version;
+    k->mmu_bm = info->mmu_bm;
+    k->mmu_ctpr_mask = info->mmu_ctpr_mask;
+    k->mmu_cxr_mask = info->mmu_cxr_mask;
+    k->mmu_sfsr_mask = info->mmu_sfsr_mask;
+    k->mmu_trcr_mask = info->mmu_trcr_mask;
+    k->mxcc_version = info->mxcc_version;
+    k->features = info->features;
+    k->nwindows = info->nwindows;
+    k->maxtl = info->maxtl;
+}
+
+static const SPARCCPUInfo sparc_cpus[] = {
+#ifdef TARGET_SPARC64
+    {
+        .name = "Fujitsu Sparc64",
+        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 4,
+        .maxtl = 4,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 III",
+        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 5,
+        .maxtl = 4,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 IV",
+        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 V",
+        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc I",
+        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc II",
+        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc IIi",
+        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc IIe",
+        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc III",
+        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc III Cu",
+        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_3,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IIIi",
+        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IV",
+        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_4,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IV+",
+        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
+    },
+    {
+        .name = "Sun UltraSparc IIIi+",
+        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_3,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc T1",
+        /* defined in sparc_ifu_fdp.v and ctu.h */
+        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_sun4v,
+        .nwindows = 8,
+        .maxtl = 6,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
+        | CPU_FEATURE_GL,
+    },
+    {
+        .name = "Sun UltraSparc T2",
+        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
+        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_sun4v,
+        .nwindows = 8,
+        .maxtl = 6,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
+        | CPU_FEATURE_GL,
+    },
+    {
+        .name = "NEC UltraSparc I",
+        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+#else
+    {
+        .name = "Fujitsu MB86900",
+        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 7,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Fujitsu MB86904",
+        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu MB86907",
+        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "LSI L64811",
+        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
+        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Cypress CY7C601",
+        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Cypress CY7C611",
+        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "TI MicroSparc I",
+        .iu_version = 0x41000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x41000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x0000003f,
+        .nwindows = 7,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
+        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FMUL,
+    },
+    {
+        .name = "TI MicroSparc II",
+        .iu_version = 0x42000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x02000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI MicroSparc IIep",
+        .iu_version = 0x42000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x04000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016bff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 40", /* STP1020NPGA */
+        .iu_version = 0x41000000, /* SuperSPARC 2.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 50", /* STP1020PGA */
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 51",
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 60", /* STP1020APGA */
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 61",
+        .iu_version = 0x44000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc II",
+        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Ross RT625",
+        .iu_version = 0x1e000000,
+        .fpu_version = 1 << 17,
+        .mmu_version = 0x1e000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Ross RT620",
+        .iu_version = 0x1f000000,
+        .fpu_version = 1 << 17,
+        .mmu_version = 0x1f000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "BIT B5010",
+        .iu_version = 0x20000000,
+        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
+        .mmu_version = 0x20000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Matsushita MN10501",
+        .iu_version = 0x50000000,
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x50000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Weitek W8601",
+        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "LEON2",
+        .iu_version = 0xf2000000,
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0xf2000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
+    },
+    {
+        .name = "LEON3",
+        .iu_version = 0xf3000000,
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0xf3000000,
+        .mmu_bm = 0x00000000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
+        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
+    },
+#endif
+};
+
+static const char * const feature_name[] = {
+    "float",
+    "float128",
+    "swap",
+    "mul",
+    "div",
+    "flush",
+    "fsqrt",
+    "fmul",
+    "vis1",
+    "vis2",
+    "fsmuld",
+    "hypv",
+    "cmt",
+    "gl",
+};
+
+static void print_features(FILE *f, fprintf_function cpu_fprintf,
+                           uint32_t features, const char *prefix)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
+        if (feature_name[i] && (features & (1 << i))) {
+            if (prefix) {
+                (*cpu_fprintf)(f, "%s", prefix);
+            }
+            (*cpu_fprintf)(f, "%s ", feature_name[i]);
+        }
+    }
+}
+
+static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
+        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
+            *features |= 1 << i;
+            return;
+        }
+    }
+    fprintf(stderr, "CPU feature %s not found\n", flagname);
+}
+
+static SPARCCPU *cpu_sparc_find_by_name(const char *cpu_model)
+{
+    SPARCCPU *cpu;
+    char *s = strdup(cpu_model);
+    char *featurestr, *name = strtok(s, ",");
+    uint32_t plus_features = 0;
+    uint32_t minus_features = 0;
+    uint64_t iu_version;
+    uint32_t fpu_version, mmu_version, nwindows;
+
+    if (object_class_by_name(name) == NULL) {
+        goto error;
+    }
+    cpu = SPARC_CPU(object_new(name));
+
+    featurestr = strtok(NULL, ",");
+    while (featurestr) {
+        char *val;
+
+        if (featurestr[0] == '+') {
+            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
+        } else if (featurestr[0] == '-') {
+            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
+        } else if ((val = strchr(featurestr, '='))) {
+            *val = 0; val++;
+            if (!strcmp(featurestr, "iu_version")) {
+                char *err;
+
+                iu_version = strtoll(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu->iu_version = iu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
+#endif
+            } else if (!strcmp(featurestr, "fpu_version")) {
+                char *err;
+
+                fpu_version = strtol(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu->fpu_version = fpu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "fpu_version %x\n", fpu_version);
+#endif
+            } else if (!strcmp(featurestr, "mmu_version")) {
+                char *err;
+
+                mmu_version = strtol(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu->mmu_version = mmu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "mmu_version %x\n", mmu_version);
+#endif
+            } else if (!strcmp(featurestr, "nwindows")) {
+                char *err;
+
+                nwindows = strtol(val, &err, 0);
+                if (!*val || *err || nwindows > MAX_NWINDOWS ||
+                    nwindows < MIN_NWINDOWS) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu->nwindows = nwindows;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "nwindows %d\n", nwindows);
+#endif
+            } else {
+                fprintf(stderr, "unrecognized feature %s\n", featurestr);
+                goto error;
+            }
+        } else {
+            fprintf(stderr, "feature string `%s' not in format "
+                    "(+feature|-feature|feature=xyz)\n", featurestr);
+            goto error;
+        }
+        featurestr = strtok(NULL, ",");
+    }
+    cpu->features |= plus_features;
+    cpu->features &= ~minus_features;
+#ifdef DEBUG_FEATURES
+    print_features(stderr, fprintf, cpu->features, NULL);
+#endif
+    free(s);
+    return cpu;
+
+ error:
+    free(s);
+    return NULL;
+}
+
+CPUSPARCState *cpu_sparc_init(const char *cpu_model)
+{
+    SPARCCPU *cpu;
+    CPUSPARCState *env;
+
+    cpu = cpu_sparc_find_by_name(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    env = &cpu->env;
+    env->cpu_model_str = cpu_model;
+
+    gen_intermediate_code_init(env);
+
+    qemu_init_vcpu(env);
+
+    return env;
+}
+
+typedef struct SPARCCPUListState {
+    fprintf_function cpu_fprintf;
+    FILE *file;
+} SPARCCPUListState;
+
+/* Sort alphabetically. */
+static gint sparc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+    ObjectClass *class_a = (ObjectClass *)a;
+    ObjectClass *class_b = (ObjectClass *)b;
+
+    return strcasecmp(object_class_get_name(class_a),
+                      object_class_get_name(class_b));
+}
+
+static void sparc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    ObjectClass *klass = data;
+    SPARCCPUClass *k = SPARC_CPU_CLASS(klass);
+    SPARCCPUListState *s = user_data;
+
+    (*s->cpu_fprintf)(s->file, "Sparc %16s IU " TARGET_FMT_lx
+                      " FPU %08x MMU %08x NWINS %d ",
+                      object_class_get_name(klass),
+                      k->iu_version,
+                      k->fpu_version,
+                      k->mmu_version,
+                      k->nwindows);
+    print_features(s->file, s->cpu_fprintf, CPU_DEFAULT_FEATURES &
+                   ~k->features, "-");
+    print_features(s->file, s->cpu_fprintf, ~CPU_DEFAULT_FEATURES &
+                   k->features, "+");
+    (*s->cpu_fprintf)(s->file, "\n");
+}
+
+void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    SPARCCPUListState s = {
+        .file = f,
+        .cpu_fprintf = cpu_fprintf,
+    };
+    GSList *list;
+
+    list = object_class_get_list(TYPE_SPARC_CPU, false);
+    list = g_slist_sort(list, sparc_cpu_list_compare);
+    g_slist_foreach(list, sparc_cpu_list_entry, &s);
+    g_slist_free(list);
+    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
+    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
+    (*cpu_fprintf)(f, "\n");
+    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
+    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
+    (*cpu_fprintf)(f, "\n");
+    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
+                   "fpu_version mmu_version nwindows\n");
+}
+
+static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
+                         uint32_t cc)
+{
+    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
+                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
+                cc & PSR_CARRY ? 'C' : '-');
+}
+
+#ifdef TARGET_SPARC64
+#define REGS_PER_LINE 4
+#else
+#define REGS_PER_LINE 8
+#endif
+
+void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
+                    int flags)
+{
+    int i, x;
+
+    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
+                env->npc);
+    cpu_fprintf(f, "General Registers:\n");
+
+    for (i = 0; i < 8; i++) {
+        if (i % REGS_PER_LINE == 0) {
+            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
+        }
+        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
+        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+    cpu_fprintf(f, "\nCurrent Register Window:\n");
+    for (x = 0; x < 3; x++) {
+        for (i = 0; i < 8; i++) {
+            if (i % REGS_PER_LINE == 0) {
+                cpu_fprintf(f, "%%%c%d-%d: ",
+                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
+                            i, i + REGS_PER_LINE - 1);
+            }
+            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
+            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+                cpu_fprintf(f, "\n");
+            }
+        }
+    }
+    cpu_fprintf(f, "\nFloating Point Registers:\n");
+    for (i = 0; i < TARGET_DPREGS; i++) {
+        if ((i & 3) == 0) {
+            cpu_fprintf(f, "%%f%02d:", i * 2);
+        }
+        cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
+        if ((i & 3) == 3) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+#ifdef TARGET_SPARC64
+    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
+                (unsigned)cpu_get_ccr(env));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
+    cpu_fprintf(f, " xcc: ");
+    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
+    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
+                env->psrpil);
+    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
+                "cleanwin: %d cwp: %d\n",
+                env->cansave, env->canrestore, env->otherwin, env->wstate,
+                env->cleanwin, env->nwindows - 1 - env->cwp);
+    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
+                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
+#else
+    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
+    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
+                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
+                env->wim);
+    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
+                env->fsr, env->y);
+#endif
+}
+
+static void cpu_type_register(const SPARCCPUInfo *info)
+{
+    TypeInfo type = {
+        .name = info->name,
+        .parent = TYPE_SPARC_CPU,
+        .instance_size = sizeof(SPARCCPU),
+        .instance_init = sparc_cpu_initfn,
+        .class_size = sizeof(SPARCCPUClass),
+        .class_init = sparc_cpu_class_init,
+        .class_data = (void *)info,
+    };
+
+    type_register_static(&type);
+}
+
+static const TypeInfo sparc_cpu_info = {
+    .name = TYPE_SPARC_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(SPARCCPU),
+    .abstract = true,
+    .class_size = sizeof(SPARCCPUClass),
+};
+
+static void sparc_cpu_register_types(void)
+{
+    int i;
+
+    type_register_static(&sparc_cpu_info);
+    for (i = 0; i < ARRAY_SIZE(sparc_cpus); i++) {
+        cpu_type_register(&sparc_cpus[i]);
+    }
+}
+
+type_init(sparc_cpu_register_types)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 86f9de6..10b05ac 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -237,22 +237,6 @@  typedef struct trap_state {
 } trap_state;
 #endif
 
-typedef struct sparc_def_t {
-    const char *name;
-    target_ulong iu_version;
-    uint32_t fpu_version;
-    uint32_t mmu_version;
-    uint32_t mmu_bm;
-    uint32_t mmu_ctpr_mask;
-    uint32_t mmu_cxr_mask;
-    uint32_t mmu_sfsr_mask;
-    uint32_t mmu_trcr_mask;
-    uint32_t mxcc_version;
-    uint32_t features;
-    uint32_t nwindows;
-    uint32_t maxtl;
-} sparc_def_t;
-
 #define CPU_FEATURE_FLOAT        (1 << 0)
 #define CPU_FEATURE_FLOAT128     (1 << 1)
 #define CPU_FEATURE_SWAP         (1 << 2)
@@ -498,7 +482,6 @@  struct CPUSPARCState {
 #define SOFTINT_INTRMASK (0xFFFE)
 #define SOFTINT_REG_MASK (SOFTINT_STIMER|SOFTINT_INTRMASK|SOFTINT_TIMER)
 #endif
-    sparc_def_t *def;
 
     void *irq_manager;
     void (*qemu_irq_ack)(CPUSPARCState *env, void *irq_manager, int intno);
@@ -507,6 +490,7 @@  struct CPUSPARCState {
     uint32_t cache_control;
 };
 
+
 #ifndef NO_CPU_IO_DEFS
 /* cpu_init.c */
 CPUSPARCState *cpu_sparc_init(const char *cpu_model);
@@ -616,10 +600,12 @@  int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 #define MMU_MODE1_SUFFIX _kernel
 #endif
 
+static inline uint32_t sparc_env_get_features(CPUSPARCState *env);
+
 #if defined (TARGET_SPARC64)
 static inline int cpu_has_hypervisor(CPUSPARCState *env1)
 {
-    return env1->def->features & CPU_FEATURE_HYPV;
+    return sparc_env_get_features(env1) & CPU_FEATURE_HYPV;
 }
 
 static inline int cpu_hypervisor_mode(CPUSPARCState *env1)
@@ -688,6 +674,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 */
@@ -714,14 +701,14 @@  static inline void cpu_get_tb_cpu_state(CPUSPARCState *env, target_ulong *pc,
     if (env->pstate & PS_AM) {
         *flags |= TB_FLAG_AM_ENABLED;
     }
-    if ((env->def->features & CPU_FEATURE_FLOAT) && (env->pstate & PS_PEF)
-        && (env->fprs & FPRS_FEF)) {
+    if ((sparc_env_get_features(env) & CPU_FEATURE_FLOAT)
+        && (env->pstate & PS_PEF) && (env->fprs & FPRS_FEF)) {
         *flags |= TB_FLAG_FPU_ENABLED;
     }
 #else
     // FPU enable . Supervisor
     *flags = env->psrs;
-    if ((env->def->features & CPU_FEATURE_FLOAT) && env->psref) {
+    if ((sparc_env_get_features(env) & CPU_FEATURE_FLOAT) && env->psref) {
         *flags |= TB_FLAG_FPU_ENABLED;
     }
 #endif
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
deleted file mode 100644
index 29132fb..0000000
--- a/target-sparc/cpu_init.c
+++ /dev/null
@@ -1,848 +0,0 @@ 
-/*
- * Sparc CPU init helpers
- *
- *  Copyright (c) 2003-2005 Fabrice Bellard
- *
- * 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 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/>.
- */
-
-#include "cpu.h"
-
-//#define DEBUG_FEATURES
-
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
-
-void cpu_state_reset(CPUSPARCState *env)
-{
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
-    tlb_flush(env, 1);
-    env->cwp = 0;
-#ifndef TARGET_SPARC64
-    env->wim = 1;
-#endif
-    env->regwptr = env->regbase + (env->cwp * 16);
-    CC_OP = CC_OP_FLAGS;
-#if defined(CONFIG_USER_ONLY)
-#ifdef TARGET_SPARC64
-    env->cleanwin = env->nwindows - 2;
-    env->cansave = env->nwindows - 2;
-    env->pstate = PS_RMO | PS_PEF | PS_IE;
-    env->asi = 0x82; /* Primary no-fault */
-#endif
-#else
-#if !defined(TARGET_SPARC64)
-    env->psret = 0;
-    env->psrs = 1;
-    env->psrps = 1;
-#endif
-#ifdef TARGET_SPARC64
-    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
-    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
-    env->tl = env->maxtl;
-    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
-    env->lsu = 0;
-#else
-    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
-    env->mmuregs[0] |= env->def->mmu_bm;
-#endif
-    env->pc = 0;
-    env->npc = env->pc + 4;
-#endif
-    env->cache_control = 0;
-}
-
-static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
-{
-    sparc_def_t def1, *def = &def1;
-
-    if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
-        return -1;
-    }
-
-    env->def = g_new0(sparc_def_t, 1);
-    memcpy(env->def, def, sizeof(*def));
-#if defined(CONFIG_USER_ONLY)
-    if ((env->def->features & CPU_FEATURE_FLOAT)) {
-        env->def->features |= CPU_FEATURE_FLOAT128;
-    }
-#endif
-    env->cpu_model_str = cpu_model;
-    env->version = def->iu_version;
-    env->fsr = def->fpu_version;
-    env->nwindows = def->nwindows;
-#if !defined(TARGET_SPARC64)
-    env->mmuregs[0] |= def->mmu_version;
-    cpu_sparc_set_id(env, 0);
-    env->mxccregs[7] |= def->mxcc_version;
-#else
-    env->mmu_version = def->mmu_version;
-    env->maxtl = def->maxtl;
-    env->version |= def->maxtl << 8;
-    env->version |= def->nwindows - 1;
-#endif
-    return 0;
-}
-
-static void cpu_sparc_close(CPUSPARCState *env)
-{
-    g_free(env->def);
-    g_free(env);
-}
-
-CPUSPARCState *cpu_sparc_init(const char *cpu_model)
-{
-    CPUSPARCState *env;
-
-    env = g_new0(CPUSPARCState, 1);
-    cpu_exec_init(env);
-
-    gen_intermediate_code_init(env);
-
-    if (cpu_sparc_register(env, cpu_model) < 0) {
-        cpu_sparc_close(env);
-        return NULL;
-    }
-    qemu_init_vcpu(env);
-
-    return env;
-}
-
-void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
-{
-#if !defined(TARGET_SPARC64)
-    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
-#endif
-}
-
-static const sparc_def_t sparc_defs[] = {
-#ifdef TARGET_SPARC64
-    {
-        .name = "Fujitsu Sparc64",
-        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 4,
-        .maxtl = 4,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 III",
-        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 5,
-        .maxtl = 4,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 IV",
-        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 V",
-        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc I",
-        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc II",
-        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc IIi",
-        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc IIe",
-        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc III",
-        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc III Cu",
-        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_3,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IIIi",
-        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IV",
-        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_4,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IV+",
-        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
-    },
-    {
-        .name = "Sun UltraSparc IIIi+",
-        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_3,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc T1",
-        /* defined in sparc_ifu_fdp.v and ctu.h */
-        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_sun4v,
-        .nwindows = 8,
-        .maxtl = 6,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
-        | CPU_FEATURE_GL,
-    },
-    {
-        .name = "Sun UltraSparc T2",
-        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
-        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_sun4v,
-        .nwindows = 8,
-        .maxtl = 6,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
-        | CPU_FEATURE_GL,
-    },
-    {
-        .name = "NEC UltraSparc I",
-        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-#else
-    {
-        .name = "Fujitsu MB86900",
-        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 7,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Fujitsu MB86904",
-        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu MB86907",
-        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "LSI L64811",
-        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
-        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Cypress CY7C601",
-        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Cypress CY7C611",
-        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "TI MicroSparc I",
-        .iu_version = 0x41000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x41000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x0000003f,
-        .nwindows = 7,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
-        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FMUL,
-    },
-    {
-        .name = "TI MicroSparc II",
-        .iu_version = 0x42000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x02000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI MicroSparc IIep",
-        .iu_version = 0x42000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x04000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016bff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 40", /* STP1020NPGA */
-        .iu_version = 0x41000000, /* SuperSPARC 2.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 50", /* STP1020PGA */
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 51",
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 60", /* STP1020APGA */
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 61",
-        .iu_version = 0x44000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc II",
-        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Ross RT625",
-        .iu_version = 0x1e000000,
-        .fpu_version = 1 << 17,
-        .mmu_version = 0x1e000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Ross RT620",
-        .iu_version = 0x1f000000,
-        .fpu_version = 1 << 17,
-        .mmu_version = 0x1f000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "BIT B5010",
-        .iu_version = 0x20000000,
-        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
-        .mmu_version = 0x20000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Matsushita MN10501",
-        .iu_version = 0x50000000,
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x50000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Weitek W8601",
-        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "LEON2",
-        .iu_version = 0xf2000000,
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0xf2000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
-    },
-    {
-        .name = "LEON3",
-        .iu_version = 0xf3000000,
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0xf3000000,
-        .mmu_bm = 0x00000000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
-        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
-    },
-#endif
-};
-
-static const char * const feature_name[] = {
-    "float",
-    "float128",
-    "swap",
-    "mul",
-    "div",
-    "flush",
-    "fsqrt",
-    "fmul",
-    "vis1",
-    "vis2",
-    "fsmuld",
-    "hypv",
-    "cmt",
-    "gl",
-};
-
-static void print_features(FILE *f, fprintf_function cpu_fprintf,
-                           uint32_t features, const char *prefix)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
-        if (feature_name[i] && (features & (1 << i))) {
-            if (prefix) {
-                (*cpu_fprintf)(f, "%s", prefix);
-            }
-            (*cpu_fprintf)(f, "%s ", feature_name[i]);
-        }
-    }
-}
-
-static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
-        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
-            *features |= 1 << i;
-            return;
-        }
-    }
-    fprintf(stderr, "CPU feature %s not found\n", flagname);
-}
-
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
-{
-    unsigned int i;
-    const sparc_def_t *def = NULL;
-    char *s = strdup(cpu_model);
-    char *featurestr, *name = strtok(s, ",");
-    uint32_t plus_features = 0;
-    uint32_t minus_features = 0;
-    uint64_t iu_version;
-    uint32_t fpu_version, mmu_version, nwindows;
-
-    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
-        if (strcasecmp(name, sparc_defs[i].name) == 0) {
-            def = &sparc_defs[i];
-        }
-    }
-    if (!def) {
-        goto error;
-    }
-    memcpy(cpu_def, def, sizeof(*def));
-
-    featurestr = strtok(NULL, ",");
-    while (featurestr) {
-        char *val;
-
-        if (featurestr[0] == '+') {
-            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
-        } else if (featurestr[0] == '-') {
-            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
-        } else if ((val = strchr(featurestr, '='))) {
-            *val = 0; val++;
-            if (!strcmp(featurestr, "iu_version")) {
-                char *err;
-
-                iu_version = strtoll(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->iu_version = iu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
-#endif
-            } else if (!strcmp(featurestr, "fpu_version")) {
-                char *err;
-
-                fpu_version = strtol(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->fpu_version = fpu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "fpu_version %x\n", fpu_version);
-#endif
-            } else if (!strcmp(featurestr, "mmu_version")) {
-                char *err;
-
-                mmu_version = strtol(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->mmu_version = mmu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "mmu_version %x\n", mmu_version);
-#endif
-            } else if (!strcmp(featurestr, "nwindows")) {
-                char *err;
-
-                nwindows = strtol(val, &err, 0);
-                if (!*val || *err || nwindows > MAX_NWINDOWS ||
-                    nwindows < MIN_NWINDOWS) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->nwindows = nwindows;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "nwindows %d\n", nwindows);
-#endif
-            } else {
-                fprintf(stderr, "unrecognized feature %s\n", featurestr);
-                goto error;
-            }
-        } else {
-            fprintf(stderr, "feature string `%s' not in format "
-                    "(+feature|-feature|feature=xyz)\n", featurestr);
-            goto error;
-        }
-        featurestr = strtok(NULL, ",");
-    }
-    cpu_def->features |= plus_features;
-    cpu_def->features &= ~minus_features;
-#ifdef DEBUG_FEATURES
-    print_features(stderr, fprintf, cpu_def->features, NULL);
-#endif
-    free(s);
-    return 0;
-
- error:
-    free(s);
-    return -1;
-}
-
-void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
-        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
-                       " FPU %08x MMU %08x NWINS %d ",
-                       sparc_defs[i].name,
-                       sparc_defs[i].iu_version,
-                       sparc_defs[i].fpu_version,
-                       sparc_defs[i].mmu_version,
-                       sparc_defs[i].nwindows);
-        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
-                       ~sparc_defs[i].features, "-");
-        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
-                       sparc_defs[i].features, "+");
-        (*cpu_fprintf)(f, "\n");
-    }
-    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
-    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
-    (*cpu_fprintf)(f, "\n");
-    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
-    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
-    (*cpu_fprintf)(f, "\n");
-    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
-                   "fpu_version mmu_version nwindows\n");
-}
-
-static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
-                         uint32_t cc)
-{
-    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
-                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
-                cc & PSR_CARRY ? 'C' : '-');
-}
-
-#ifdef TARGET_SPARC64
-#define REGS_PER_LINE 4
-#else
-#define REGS_PER_LINE 8
-#endif
-
-void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
-                    int flags)
-{
-    int i, x;
-
-    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
-                env->npc);
-    cpu_fprintf(f, "General Registers:\n");
-
-    for (i = 0; i < 8; i++) {
-        if (i % REGS_PER_LINE == 0) {
-            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
-        }
-        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
-        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
-            cpu_fprintf(f, "\n");
-        }
-    }
-    cpu_fprintf(f, "\nCurrent Register Window:\n");
-    for (x = 0; x < 3; x++) {
-        for (i = 0; i < 8; i++) {
-            if (i % REGS_PER_LINE == 0) {
-                cpu_fprintf(f, "%%%c%d-%d: ",
-                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
-                            i, i + REGS_PER_LINE - 1);
-            }
-            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
-            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
-                cpu_fprintf(f, "\n");
-            }
-        }
-    }
-    cpu_fprintf(f, "\nFloating Point Registers:\n");
-    for (i = 0; i < TARGET_DPREGS; i++) {
-        if ((i & 3) == 0) {
-            cpu_fprintf(f, "%%f%02d:", i * 2);
-        }
-        cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
-        if ((i & 3) == 3) {
-            cpu_fprintf(f, "\n");
-        }
-    }
-#ifdef TARGET_SPARC64
-    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
-                (unsigned)cpu_get_ccr(env));
-    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
-    cpu_fprintf(f, " xcc: ");
-    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
-    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
-                env->psrpil);
-    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
-                "cleanwin: %d cwp: %d\n",
-                env->cansave, env->canrestore, env->otherwin, env->wstate,
-                env->cleanwin, env->nwindows - 1 - env->cwp);
-    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
-                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
-#else
-    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
-    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
-    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
-                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
-                env->wim);
-    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
-                env->fsr, env->y);
-#endif
-}
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index 5e33d50..8d454ae 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -60,6 +60,9 @@  static const char * const excp_names[0x80] = {
 
 void do_interrupt(CPUSPARCState *env)
 {
+#if !defined(CONFIG_USER_ONLY)
+    SPARCCPU *cpu = sparc_env_get_cpu(env);
+#endif
     int cwp, intno = env->exception_index;
 
 #ifdef DEBUG_PCALL
@@ -102,7 +105,7 @@  void do_interrupt(CPUSPARCState *env)
 #if !defined(CONFIG_USER_ONLY)
     if (env->psret == 0) {
         if (env->exception_index == 0x80 &&
-            env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
+            cpu->features & CPU_FEATURE_TA0_SHUTDOWN) {
             qemu_system_shutdown_request();
         } else {
             cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 48d433c..806f45c 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -438,6 +438,7 @@  static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
 
 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 {
+    SPARCCPU *cpu = sparc_env_get_cpu(env);
     uint64_t ret = 0;
 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
     uint32_t last_addr = addr;
@@ -450,7 +451,7 @@  uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         case 0x00:          /* Leon3 Cache Control */
         case 0x08:          /* Leon3 Instruction Cache config */
         case 0x0C:          /* Leon3 Date Cache config */
-            if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
+            if (cpu->features & CPU_FEATURE_CACHE_CTRL) {
                 ret = leon3_cache_control_ld(addr, size);
             }
             break;
@@ -696,6 +697,8 @@  uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 
 void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
 {
+    SPARCCPU *cpu = sparc_env_get_cpu(env);
+    SPARCCPUClass *klass = SPARC_CPU_GET_CLASS(cpu);
     helper_check_align(addr, size - 1);
     switch (asi) {
     case 2: /* SuperSparc MXCC registers and Leon3 cache control */
@@ -703,7 +706,7 @@  void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
         case 0x00:          /* Leon3 Cache Control */
         case 0x08:          /* Leon3 Instruction Cache config */
         case 0x0C:          /* Leon3 Date Cache config */
-            if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
+            if (cpu->features & CPU_FEATURE_CACHE_CTRL) {
                 leon3_cache_control_st(addr, val, size);
             }
             break;
@@ -853,16 +856,16 @@  void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
                     (val & 0x00ffffff);
                 /* Mappings generated during no-fault mode or MMU
                    disabled mode are invalid in normal mode */
-                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
-                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) {
+                if ((oldreg & (MMU_E | MMU_NF | klass->mmu_bm)) !=
+                    (env->mmuregs[reg] & (MMU_E | MMU_NF | klass->mmu_bm))) {
                     tlb_flush(env, 1);
                 }
                 break;
             case 1: /* Context Table Pointer Register */
-                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
+                env->mmuregs[reg] = val & klass->mmu_ctpr_mask;
                 break;
             case 2: /* Context Register */
-                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
+                env->mmuregs[reg] = val & klass->mmu_cxr_mask;
                 if (oldreg != env->mmuregs[reg]) {
                     /* we flush when the MMU context changes because
                        QEMU has no MMU context support */
@@ -873,11 +876,11 @@  void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
             case 4: /* Synchronous Fault Address Register */
                 break;
             case 0x10: /* TLB Replacement Control Register */
-                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
+                env->mmuregs[reg] = val & klass->mmu_trcr_mask;
                 break;
             case 0x13: /* Synchronous Fault Status Register with Read
                           and Clear */
-                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
+                env->mmuregs[3] = val & klass->mmu_sfsr_mask;
                 break;
             case 0x14: /* Synchronous Fault Address Register */
                 env->mmuregs[4] = val;
diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index 11fb9f5..83b050e 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -81,6 +81,8 @@  static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical
                                 target_ulong address, int rw, int mmu_idx,
                                 target_ulong *page_size)
 {
+    SPARCCPU *cpu = sparc_env_get_cpu(env);
+    SPARCCPUClass *klass = SPARC_CPU_GET_CLASS(cpu);
     int access_perms = 0;
     target_phys_addr_t pde_ptr;
     uint32_t pde;
@@ -92,7 +94,7 @@  static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical
     if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
         *page_size = TARGET_PAGE_SIZE;
         /* Boot mode: instruction fetches are taken from PROM */
-        if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
+        if (rw == 2 && (env->mmuregs[0] & klass->mmu_bm)) {
             *physical = env->prom_addr | (address & 0x7ffffULL);
             *prot = PAGE_READ | PAGE_EXEC;
             return 0;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index ef176e9..a737279 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -81,7 +81,7 @@  typedef struct DisasContext {
     int singlestep;
     uint32_t cc_op;  /* current CC operation */
     struct TranslationBlock *tb;
-    sparc_def_t *def;
+    SPARCCPU *def;
     TCGv_i32 t32[3];
     int n_t32;
 } DisasContext;
@@ -5247,7 +5247,7 @@  static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     dc->npc = (target_ulong) tb->cs_base;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->mem_idx = cpu_mmu_index(env);
-    dc->def = env->def;
+    dc->def = sparc_env_get_cpu(env);
     dc->fpu_enabled = tb_fpu_enabled(tb->flags);
     dc->address_mask_32bit = tb_am_enabled(tb->flags);
     dc->singlestep = (env->singlestep_enabled || singlestep);
diff --git a/target-sparc/win_helper.c b/target-sparc/win_helper.c
index 3e82eb7..02376fc 100644
--- a/target-sparc/win_helper.c
+++ b/target-sparc/win_helper.c
@@ -300,10 +300,11 @@  static inline uint64_t *get_gregset(CPUSPARCState *env, uint32_t pstate)
 
 void cpu_change_pstate(CPUSPARCState *env, uint32_t new_pstate)
 {
+    SPARCCPU *cpu = sparc_env_get_cpu(env);
     uint32_t pstate_regs, new_pstate_regs;
     uint64_t *src, *dst;
 
-    if (env->def->features & CPU_FEATURE_GL) {
+    if (cpu->features & CPU_FEATURE_GL) {
         /* PS_AG is not implemented in this case */
         new_pstate &= ~PS_AG;
     }