qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

cpu.c (30137B)


      1 /*
      2  * Sparc CPU init helpers
      3  *
      4  *  Copyright (c) 2003-2005 Fabrice Bellard
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2.1 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Lesser General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Lesser General Public
     17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 #include "qemu/osdep.h"
     21 #include "qapi/error.h"
     22 #include "cpu.h"
     23 #include "qemu/module.h"
     24 #include "qemu/qemu-print.h"
     25 #include "exec/exec-all.h"
     26 #include "hw/qdev-properties.h"
     27 #include "qapi/visitor.h"
     28 
     29 //#define DEBUG_FEATURES
     30 
     31 static void sparc_cpu_reset(DeviceState *dev)
     32 {
     33     CPUState *s = CPU(dev);
     34     SPARCCPU *cpu = SPARC_CPU(s);
     35     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
     36     CPUSPARCState *env = &cpu->env;
     37 
     38     scc->parent_reset(dev);
     39 
     40     memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
     41     env->cwp = 0;
     42 #ifndef TARGET_SPARC64
     43     env->wim = 1;
     44 #endif
     45     env->regwptr = env->regbase + (env->cwp * 16);
     46     CC_OP = CC_OP_FLAGS;
     47 #if defined(CONFIG_USER_ONLY)
     48 #ifdef TARGET_SPARC64
     49     env->cleanwin = env->nwindows - 2;
     50     env->cansave = env->nwindows - 2;
     51     env->pstate = PS_RMO | PS_PEF | PS_IE;
     52     env->asi = 0x82; /* Primary no-fault */
     53 #endif
     54 #else
     55 #if !defined(TARGET_SPARC64)
     56     env->psret = 0;
     57     env->psrs = 1;
     58     env->psrps = 1;
     59 #endif
     60 #ifdef TARGET_SPARC64
     61     env->pstate = PS_PRIV | PS_RED | PS_PEF;
     62     if (!cpu_has_hypervisor(env)) {
     63         env->pstate |= PS_AG;
     64     }
     65     env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
     66     env->tl = env->maxtl;
     67     env->gl = 2;
     68     cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
     69     env->lsu = 0;
     70 #else
     71     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
     72     env->mmuregs[0] |= env->def.mmu_bm;
     73 #endif
     74     env->pc = 0;
     75     env->npc = env->pc + 4;
     76 #endif
     77     env->cache_control = 0;
     78 }
     79 
     80 #ifndef CONFIG_USER_ONLY
     81 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
     82 {
     83     if (interrupt_request & CPU_INTERRUPT_HARD) {
     84         SPARCCPU *cpu = SPARC_CPU(cs);
     85         CPUSPARCState *env = &cpu->env;
     86 
     87         if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
     88             int pil = env->interrupt_index & 0xf;
     89             int type = env->interrupt_index & 0xf0;
     90 
     91             if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
     92                 cs->exception_index = env->interrupt_index;
     93                 sparc_cpu_do_interrupt(cs);
     94                 return true;
     95             }
     96         }
     97     }
     98     return false;
     99 }
    100 #endif /* !CONFIG_USER_ONLY */
    101 
    102 static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
    103 {
    104     info->print_insn = print_insn_sparc;
    105 #ifdef TARGET_SPARC64
    106     info->mach = bfd_mach_sparc_v9b;
    107 #endif
    108 }
    109 
    110 static void
    111 cpu_add_feat_as_prop(const char *typename, const char *name, const char *val)
    112 {
    113     GlobalProperty *prop = g_new0(typeof(*prop), 1);
    114     prop->driver = typename;
    115     prop->property = g_strdup(name);
    116     prop->value = g_strdup(val);
    117     qdev_prop_register_global(prop);
    118 }
    119 
    120 /* Parse "+feature,-feature,feature=foo" CPU feature string */
    121 static void sparc_cpu_parse_features(const char *typename, char *features,
    122                                      Error **errp)
    123 {
    124     GList *l, *plus_features = NULL, *minus_features = NULL;
    125     char *featurestr; /* Single 'key=value" string being parsed */
    126     static bool cpu_globals_initialized;
    127 
    128     if (cpu_globals_initialized) {
    129         return;
    130     }
    131     cpu_globals_initialized = true;
    132 
    133     if (!features) {
    134         return;
    135     }
    136 
    137     for (featurestr = strtok(features, ",");
    138          featurestr;
    139          featurestr = strtok(NULL, ",")) {
    140         const char *name;
    141         const char *val = NULL;
    142         char *eq = NULL;
    143 
    144         /* Compatibility syntax: */
    145         if (featurestr[0] == '+') {
    146             plus_features = g_list_append(plus_features,
    147                                           g_strdup(featurestr + 1));
    148             continue;
    149         } else if (featurestr[0] == '-') {
    150             minus_features = g_list_append(minus_features,
    151                                            g_strdup(featurestr + 1));
    152             continue;
    153         }
    154 
    155         eq = strchr(featurestr, '=');
    156         name = featurestr;
    157         if (eq) {
    158             *eq++ = 0;
    159             val = eq;
    160 
    161             /*
    162              * Temporarily, only +feat/-feat will be supported
    163              * for boolean properties until we remove the
    164              * minus-overrides-plus semantics and just follow
    165              * the order options appear on the command-line.
    166              *
    167              * TODO: warn if user is relying on minus-override-plus semantics
    168              * TODO: remove minus-override-plus semantics after
    169              *       warning for a few releases
    170              */
    171             if (!strcasecmp(val, "on") ||
    172                 !strcasecmp(val, "off") ||
    173                 !strcasecmp(val, "true") ||
    174                 !strcasecmp(val, "false")) {
    175                 error_setg(errp, "Boolean properties in format %s=%s"
    176                                  " are not supported", name, val);
    177                 return;
    178             }
    179         } else {
    180             error_setg(errp, "Unsupported property format: %s", name);
    181             return;
    182         }
    183         cpu_add_feat_as_prop(typename, name, val);
    184     }
    185 
    186     for (l = plus_features; l; l = l->next) {
    187         const char *name = l->data;
    188         cpu_add_feat_as_prop(typename, name, "on");
    189     }
    190     g_list_free_full(plus_features, g_free);
    191 
    192     for (l = minus_features; l; l = l->next) {
    193         const char *name = l->data;
    194         cpu_add_feat_as_prop(typename, name, "off");
    195     }
    196     g_list_free_full(minus_features, g_free);
    197 }
    198 
    199 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
    200 {
    201 #if !defined(TARGET_SPARC64)
    202     env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
    203 #endif
    204 }
    205 
    206 static const sparc_def_t sparc_defs[] = {
    207 #ifdef TARGET_SPARC64
    208     {
    209         .name = "Fujitsu Sparc64",
    210         .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
    211         .fpu_version = 0x00000000,
    212         .mmu_version = mmu_us_12,
    213         .nwindows = 4,
    214         .maxtl = 4,
    215         .features = CPU_DEFAULT_FEATURES,
    216     },
    217     {
    218         .name = "Fujitsu Sparc64 III",
    219         .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
    220         .fpu_version = 0x00000000,
    221         .mmu_version = mmu_us_12,
    222         .nwindows = 5,
    223         .maxtl = 4,
    224         .features = CPU_DEFAULT_FEATURES,
    225     },
    226     {
    227         .name = "Fujitsu Sparc64 IV",
    228         .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
    229         .fpu_version = 0x00000000,
    230         .mmu_version = mmu_us_12,
    231         .nwindows = 8,
    232         .maxtl = 5,
    233         .features = CPU_DEFAULT_FEATURES,
    234     },
    235     {
    236         .name = "Fujitsu Sparc64 V",
    237         .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
    238         .fpu_version = 0x00000000,
    239         .mmu_version = mmu_us_12,
    240         .nwindows = 8,
    241         .maxtl = 5,
    242         .features = CPU_DEFAULT_FEATURES,
    243     },
    244     {
    245         .name = "TI UltraSparc I",
    246         .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
    247         .fpu_version = 0x00000000,
    248         .mmu_version = mmu_us_12,
    249         .nwindows = 8,
    250         .maxtl = 5,
    251         .features = CPU_DEFAULT_FEATURES,
    252     },
    253     {
    254         .name = "TI UltraSparc II",
    255         .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
    256         .fpu_version = 0x00000000,
    257         .mmu_version = mmu_us_12,
    258         .nwindows = 8,
    259         .maxtl = 5,
    260         .features = CPU_DEFAULT_FEATURES,
    261     },
    262     {
    263         .name = "TI UltraSparc IIi",
    264         .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
    265         .fpu_version = 0x00000000,
    266         .mmu_version = mmu_us_12,
    267         .nwindows = 8,
    268         .maxtl = 5,
    269         .features = CPU_DEFAULT_FEATURES,
    270     },
    271     {
    272         .name = "TI UltraSparc IIe",
    273         .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
    274         .fpu_version = 0x00000000,
    275         .mmu_version = mmu_us_12,
    276         .nwindows = 8,
    277         .maxtl = 5,
    278         .features = CPU_DEFAULT_FEATURES,
    279     },
    280     {
    281         .name = "Sun UltraSparc III",
    282         .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
    283         .fpu_version = 0x00000000,
    284         .mmu_version = mmu_us_12,
    285         .nwindows = 8,
    286         .maxtl = 5,
    287         .features = CPU_DEFAULT_FEATURES,
    288     },
    289     {
    290         .name = "Sun UltraSparc III Cu",
    291         .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
    292         .fpu_version = 0x00000000,
    293         .mmu_version = mmu_us_3,
    294         .nwindows = 8,
    295         .maxtl = 5,
    296         .features = CPU_DEFAULT_FEATURES,
    297     },
    298     {
    299         .name = "Sun UltraSparc IIIi",
    300         .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
    301         .fpu_version = 0x00000000,
    302         .mmu_version = mmu_us_12,
    303         .nwindows = 8,
    304         .maxtl = 5,
    305         .features = CPU_DEFAULT_FEATURES,
    306     },
    307     {
    308         .name = "Sun UltraSparc IV",
    309         .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
    310         .fpu_version = 0x00000000,
    311         .mmu_version = mmu_us_4,
    312         .nwindows = 8,
    313         .maxtl = 5,
    314         .features = CPU_DEFAULT_FEATURES,
    315     },
    316     {
    317         .name = "Sun UltraSparc IV+",
    318         .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
    319         .fpu_version = 0x00000000,
    320         .mmu_version = mmu_us_12,
    321         .nwindows = 8,
    322         .maxtl = 5,
    323         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
    324     },
    325     {
    326         .name = "Sun UltraSparc IIIi+",
    327         .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
    328         .fpu_version = 0x00000000,
    329         .mmu_version = mmu_us_3,
    330         .nwindows = 8,
    331         .maxtl = 5,
    332         .features = CPU_DEFAULT_FEATURES,
    333     },
    334     {
    335         .name = "Sun UltraSparc T1",
    336         /* defined in sparc_ifu_fdp.v and ctu.h */
    337         .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
    338         .fpu_version = 0x00000000,
    339         .mmu_version = mmu_sun4v,
    340         .nwindows = 8,
    341         .maxtl = 6,
    342         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
    343         | CPU_FEATURE_GL,
    344     },
    345     {
    346         .name = "Sun UltraSparc T2",
    347         /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
    348         .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
    349         .fpu_version = 0x00000000,
    350         .mmu_version = mmu_sun4v,
    351         .nwindows = 8,
    352         .maxtl = 6,
    353         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
    354         | CPU_FEATURE_GL,
    355     },
    356     {
    357         .name = "NEC UltraSparc I",
    358         .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
    359         .fpu_version = 0x00000000,
    360         .mmu_version = mmu_us_12,
    361         .nwindows = 8,
    362         .maxtl = 5,
    363         .features = CPU_DEFAULT_FEATURES,
    364     },
    365 #else
    366     {
    367         .name = "Fujitsu MB86904",
    368         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
    369         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
    370         .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
    371         .mmu_bm = 0x00004000,
    372         .mmu_ctpr_mask = 0x00ffffc0,
    373         .mmu_cxr_mask = 0x000000ff,
    374         .mmu_sfsr_mask = 0x00016fff,
    375         .mmu_trcr_mask = 0x00ffffff,
    376         .nwindows = 8,
    377         .features = CPU_DEFAULT_FEATURES,
    378     },
    379     {
    380         .name = "Fujitsu MB86907",
    381         .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
    382         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
    383         .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
    384         .mmu_bm = 0x00004000,
    385         .mmu_ctpr_mask = 0xffffffc0,
    386         .mmu_cxr_mask = 0x000000ff,
    387         .mmu_sfsr_mask = 0x00016fff,
    388         .mmu_trcr_mask = 0xffffffff,
    389         .nwindows = 8,
    390         .features = CPU_DEFAULT_FEATURES,
    391     },
    392     {
    393         .name = "TI MicroSparc I",
    394         .iu_version = 0x41000000,
    395         .fpu_version = 4 << 17,
    396         .mmu_version = 0x41000000,
    397         .mmu_bm = 0x00004000,
    398         .mmu_ctpr_mask = 0x007ffff0,
    399         .mmu_cxr_mask = 0x0000003f,
    400         .mmu_sfsr_mask = 0x00016fff,
    401         .mmu_trcr_mask = 0x0000003f,
    402         .nwindows = 7,
    403         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
    404         CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
    405         CPU_FEATURE_FMUL,
    406     },
    407     {
    408         .name = "TI MicroSparc II",
    409         .iu_version = 0x42000000,
    410         .fpu_version = 4 << 17,
    411         .mmu_version = 0x02000000,
    412         .mmu_bm = 0x00004000,
    413         .mmu_ctpr_mask = 0x00ffffc0,
    414         .mmu_cxr_mask = 0x000000ff,
    415         .mmu_sfsr_mask = 0x00016fff,
    416         .mmu_trcr_mask = 0x00ffffff,
    417         .nwindows = 8,
    418         .features = CPU_DEFAULT_FEATURES,
    419     },
    420     {
    421         .name = "TI MicroSparc IIep",
    422         .iu_version = 0x42000000,
    423         .fpu_version = 4 << 17,
    424         .mmu_version = 0x04000000,
    425         .mmu_bm = 0x00004000,
    426         .mmu_ctpr_mask = 0x00ffffc0,
    427         .mmu_cxr_mask = 0x000000ff,
    428         .mmu_sfsr_mask = 0x00016bff,
    429         .mmu_trcr_mask = 0x00ffffff,
    430         .nwindows = 8,
    431         .features = CPU_DEFAULT_FEATURES,
    432     },
    433     {
    434         .name = "TI SuperSparc 40", /* STP1020NPGA */
    435         .iu_version = 0x41000000, /* SuperSPARC 2.x */
    436         .fpu_version = 0 << 17,
    437         .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
    438         .mmu_bm = 0x00002000,
    439         .mmu_ctpr_mask = 0xffffffc0,
    440         .mmu_cxr_mask = 0x0000ffff,
    441         .mmu_sfsr_mask = 0xffffffff,
    442         .mmu_trcr_mask = 0xffffffff,
    443         .nwindows = 8,
    444         .features = CPU_DEFAULT_FEATURES,
    445     },
    446     {
    447         .name = "TI SuperSparc 50", /* STP1020PGA */
    448         .iu_version = 0x40000000, /* SuperSPARC 3.x */
    449         .fpu_version = 0 << 17,
    450         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
    451         .mmu_bm = 0x00002000,
    452         .mmu_ctpr_mask = 0xffffffc0,
    453         .mmu_cxr_mask = 0x0000ffff,
    454         .mmu_sfsr_mask = 0xffffffff,
    455         .mmu_trcr_mask = 0xffffffff,
    456         .nwindows = 8,
    457         .features = CPU_DEFAULT_FEATURES,
    458     },
    459     {
    460         .name = "TI SuperSparc 51",
    461         .iu_version = 0x40000000, /* SuperSPARC 3.x */
    462         .fpu_version = 0 << 17,
    463         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
    464         .mmu_bm = 0x00002000,
    465         .mmu_ctpr_mask = 0xffffffc0,
    466         .mmu_cxr_mask = 0x0000ffff,
    467         .mmu_sfsr_mask = 0xffffffff,
    468         .mmu_trcr_mask = 0xffffffff,
    469         .mxcc_version = 0x00000104,
    470         .nwindows = 8,
    471         .features = CPU_DEFAULT_FEATURES,
    472     },
    473     {
    474         .name = "TI SuperSparc 60", /* STP1020APGA */
    475         .iu_version = 0x40000000, /* SuperSPARC 3.x */
    476         .fpu_version = 0 << 17,
    477         .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
    478         .mmu_bm = 0x00002000,
    479         .mmu_ctpr_mask = 0xffffffc0,
    480         .mmu_cxr_mask = 0x0000ffff,
    481         .mmu_sfsr_mask = 0xffffffff,
    482         .mmu_trcr_mask = 0xffffffff,
    483         .nwindows = 8,
    484         .features = CPU_DEFAULT_FEATURES,
    485     },
    486     {
    487         .name = "TI SuperSparc 61",
    488         .iu_version = 0x44000000, /* SuperSPARC 3.x */
    489         .fpu_version = 0 << 17,
    490         .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
    491         .mmu_bm = 0x00002000,
    492         .mmu_ctpr_mask = 0xffffffc0,
    493         .mmu_cxr_mask = 0x0000ffff,
    494         .mmu_sfsr_mask = 0xffffffff,
    495         .mmu_trcr_mask = 0xffffffff,
    496         .mxcc_version = 0x00000104,
    497         .nwindows = 8,
    498         .features = CPU_DEFAULT_FEATURES,
    499     },
    500     {
    501         .name = "TI SuperSparc II",
    502         .iu_version = 0x40000000, /* SuperSPARC II 1.x */
    503         .fpu_version = 0 << 17,
    504         .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
    505         .mmu_bm = 0x00002000,
    506         .mmu_ctpr_mask = 0xffffffc0,
    507         .mmu_cxr_mask = 0x0000ffff,
    508         .mmu_sfsr_mask = 0xffffffff,
    509         .mmu_trcr_mask = 0xffffffff,
    510         .mxcc_version = 0x00000104,
    511         .nwindows = 8,
    512         .features = CPU_DEFAULT_FEATURES,
    513     },
    514     {
    515         .name = "LEON2",
    516         .iu_version = 0xf2000000,
    517         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
    518         .mmu_version = 0xf2000000,
    519         .mmu_bm = 0x00004000,
    520         .mmu_ctpr_mask = 0x007ffff0,
    521         .mmu_cxr_mask = 0x0000003f,
    522         .mmu_sfsr_mask = 0xffffffff,
    523         .mmu_trcr_mask = 0xffffffff,
    524         .nwindows = 8,
    525         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
    526     },
    527     {
    528         .name = "LEON3",
    529         .iu_version = 0xf3000000,
    530         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
    531         .mmu_version = 0xf3000000,
    532         .mmu_bm = 0x00000000,
    533         .mmu_ctpr_mask = 0xfffffffc,
    534         .mmu_cxr_mask = 0x000000ff,
    535         .mmu_sfsr_mask = 0xffffffff,
    536         .mmu_trcr_mask = 0xffffffff,
    537         .nwindows = 8,
    538         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
    539         CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
    540         CPU_FEATURE_CASA,
    541     },
    542 #endif
    543 };
    544 
    545 static const char * const feature_name[] = {
    546     "float",
    547     "float128",
    548     "swap",
    549     "mul",
    550     "div",
    551     "flush",
    552     "fsqrt",
    553     "fmul",
    554     "vis1",
    555     "vis2",
    556     "fsmuld",
    557     "hypv",
    558     "cmt",
    559     "gl",
    560 };
    561 
    562 static void print_features(uint32_t features, const char *prefix)
    563 {
    564     unsigned int i;
    565 
    566     for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
    567         if (feature_name[i] && (features & (1 << i))) {
    568             if (prefix) {
    569                 qemu_printf("%s", prefix);
    570             }
    571             qemu_printf("%s ", feature_name[i]);
    572         }
    573     }
    574 }
    575 
    576 void sparc_cpu_list(void)
    577 {
    578     unsigned int i;
    579 
    580     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
    581         qemu_printf("Sparc %16s IU " TARGET_FMT_lx
    582                     " FPU %08x MMU %08x NWINS %d ",
    583                     sparc_defs[i].name,
    584                     sparc_defs[i].iu_version,
    585                     sparc_defs[i].fpu_version,
    586                     sparc_defs[i].mmu_version,
    587                     sparc_defs[i].nwindows);
    588         print_features(CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-");
    589         print_features(~CPU_DEFAULT_FEATURES & sparc_defs[i].features, "+");
    590         qemu_printf("\n");
    591     }
    592     qemu_printf("Default CPU feature flags (use '-' to remove): ");
    593     print_features(CPU_DEFAULT_FEATURES, NULL);
    594     qemu_printf("\n");
    595     qemu_printf("Available CPU feature flags (use '+' to add): ");
    596     print_features(~CPU_DEFAULT_FEATURES, NULL);
    597     qemu_printf("\n");
    598     qemu_printf("Numerical features (use '=' to set): iu_version "
    599                 "fpu_version mmu_version nwindows\n");
    600 }
    601 
    602 static void cpu_print_cc(FILE *f, uint32_t cc)
    603 {
    604     qemu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
    605                  cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
    606                  cc & PSR_CARRY ? 'C' : '-');
    607 }
    608 
    609 #ifdef TARGET_SPARC64
    610 #define REGS_PER_LINE 4
    611 #else
    612 #define REGS_PER_LINE 8
    613 #endif
    614 
    615 static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
    616 {
    617     SPARCCPU *cpu = SPARC_CPU(cs);
    618     CPUSPARCState *env = &cpu->env;
    619     int i, x;
    620 
    621     qemu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
    622                  env->npc);
    623 
    624     for (i = 0; i < 8; i++) {
    625         if (i % REGS_PER_LINE == 0) {
    626             qemu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
    627         }
    628         qemu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
    629         if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
    630             qemu_fprintf(f, "\n");
    631         }
    632     }
    633     for (x = 0; x < 3; x++) {
    634         for (i = 0; i < 8; i++) {
    635             if (i % REGS_PER_LINE == 0) {
    636                 qemu_fprintf(f, "%%%c%d-%d: ",
    637                              x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
    638                              i, i + REGS_PER_LINE - 1);
    639             }
    640             qemu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
    641             if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
    642                 qemu_fprintf(f, "\n");
    643             }
    644         }
    645     }
    646 
    647     if (flags & CPU_DUMP_FPU) {
    648         for (i = 0; i < TARGET_DPREGS; i++) {
    649             if ((i & 3) == 0) {
    650                 qemu_fprintf(f, "%%f%02d: ", i * 2);
    651             }
    652             qemu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
    653             if ((i & 3) == 3) {
    654                 qemu_fprintf(f, "\n");
    655             }
    656         }
    657     }
    658 
    659 #ifdef TARGET_SPARC64
    660     qemu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
    661                  (unsigned)cpu_get_ccr(env));
    662     cpu_print_cc(f, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
    663     qemu_fprintf(f, " xcc: ");
    664     cpu_print_cc(f, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
    665     qemu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
    666                  env->psrpil, env->gl);
    667     qemu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
    668                  TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
    669     qemu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
    670                  "cleanwin: %d cwp: %d\n",
    671                  env->cansave, env->canrestore, env->otherwin, env->wstate,
    672                  env->cleanwin, env->nwindows - 1 - env->cwp);
    673     qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
    674                  TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
    675 
    676 #else
    677     qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
    678     cpu_print_cc(f, cpu_get_psr(env));
    679     qemu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
    680                  env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
    681                  env->wim);
    682     qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
    683                  env->fsr, env->y);
    684 #endif
    685     qemu_fprintf(f, "\n");
    686 }
    687 
    688 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
    689 {
    690     SPARCCPU *cpu = SPARC_CPU(cs);
    691 
    692     cpu->env.pc = value;
    693     cpu->env.npc = value + 4;
    694 }
    695 
    696 static vaddr sparc_cpu_get_pc(CPUState *cs)
    697 {
    698     SPARCCPU *cpu = SPARC_CPU(cs);
    699 
    700     return cpu->env.pc;
    701 }
    702 
    703 static void sparc_cpu_synchronize_from_tb(CPUState *cs,
    704                                           const TranslationBlock *tb)
    705 {
    706     SPARCCPU *cpu = SPARC_CPU(cs);
    707 
    708     cpu->env.pc = tb_pc(tb);
    709     cpu->env.npc = tb->cs_base;
    710 }
    711 
    712 static bool sparc_cpu_has_work(CPUState *cs)
    713 {
    714     SPARCCPU *cpu = SPARC_CPU(cs);
    715     CPUSPARCState *env = &cpu->env;
    716 
    717     return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
    718            cpu_interrupts_enabled(env);
    719 }
    720 
    721 static char *sparc_cpu_type_name(const char *cpu_model)
    722 {
    723     char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
    724     char *s = name;
    725 
    726     /* SPARC cpu model names happen to have whitespaces,
    727      * as type names shouldn't have spaces replace them with '-'
    728      */
    729     while ((s = strchr(s, ' '))) {
    730         *s = '-';
    731     }
    732 
    733     return name;
    734 }
    735 
    736 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
    737 {
    738     ObjectClass *oc;
    739     char *typename;
    740 
    741     typename = sparc_cpu_type_name(cpu_model);
    742     oc = object_class_by_name(typename);
    743     g_free(typename);
    744     return oc;
    745 }
    746 
    747 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
    748 {
    749     CPUState *cs = CPU(dev);
    750     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
    751     Error *local_err = NULL;
    752     SPARCCPU *cpu = SPARC_CPU(dev);
    753     CPUSPARCState *env = &cpu->env;
    754 
    755 #if defined(CONFIG_USER_ONLY)
    756     if ((env->def.features & CPU_FEATURE_FLOAT)) {
    757         env->def.features |= CPU_FEATURE_FLOAT128;
    758     }
    759 #endif
    760 
    761     env->version = env->def.iu_version;
    762     env->fsr = env->def.fpu_version;
    763     env->nwindows = env->def.nwindows;
    764 #if !defined(TARGET_SPARC64)
    765     env->mmuregs[0] |= env->def.mmu_version;
    766     cpu_sparc_set_id(env, 0);
    767     env->mxccregs[7] |= env->def.mxcc_version;
    768 #else
    769     env->mmu_version = env->def.mmu_version;
    770     env->maxtl = env->def.maxtl;
    771     env->version |= env->def.maxtl << 8;
    772     env->version |= env->def.nwindows - 1;
    773 #endif
    774 
    775     cpu_exec_realizefn(cs, &local_err);
    776     if (local_err != NULL) {
    777         error_propagate(errp, local_err);
    778         return;
    779     }
    780 
    781     qemu_init_vcpu(cs);
    782 
    783     scc->parent_realize(dev, errp);
    784 }
    785 
    786 static void sparc_cpu_initfn(Object *obj)
    787 {
    788     SPARCCPU *cpu = SPARC_CPU(obj);
    789     SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
    790     CPUSPARCState *env = &cpu->env;
    791 
    792     cpu_set_cpustate_pointers(cpu);
    793 
    794     if (scc->cpu_def) {
    795         env->def = *scc->cpu_def;
    796     }
    797 }
    798 
    799 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
    800                                void *opaque, Error **errp)
    801 {
    802     SPARCCPU *cpu = SPARC_CPU(obj);
    803     int64_t value = cpu->env.def.nwindows;
    804 
    805     visit_type_int(v, name, &value, errp);
    806 }
    807 
    808 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
    809                                void *opaque, Error **errp)
    810 {
    811     const int64_t min = MIN_NWINDOWS;
    812     const int64_t max = MAX_NWINDOWS;
    813     SPARCCPU *cpu = SPARC_CPU(obj);
    814     int64_t value;
    815 
    816     if (!visit_type_int(v, name, &value, errp)) {
    817         return;
    818     }
    819 
    820     if (value < min || value > max) {
    821         error_setg(errp, "Property %s.%s doesn't take value %" PRId64
    822                    " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
    823                    object_get_typename(obj), name ? name : "null",
    824                    value, min, max);
    825         return;
    826     }
    827     cpu->env.def.nwindows = value;
    828 }
    829 
    830 static PropertyInfo qdev_prop_nwindows = {
    831     .name  = "int",
    832     .get   = sparc_get_nwindows,
    833     .set   = sparc_set_nwindows,
    834 };
    835 
    836 static Property sparc_cpu_properties[] = {
    837     DEFINE_PROP_BIT("float",    SPARCCPU, env.def.features, 0, false),
    838     DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
    839     DEFINE_PROP_BIT("swap",     SPARCCPU, env.def.features, 2, false),
    840     DEFINE_PROP_BIT("mul",      SPARCCPU, env.def.features, 3, false),
    841     DEFINE_PROP_BIT("div",      SPARCCPU, env.def.features, 4, false),
    842     DEFINE_PROP_BIT("flush",    SPARCCPU, env.def.features, 5, false),
    843     DEFINE_PROP_BIT("fsqrt",    SPARCCPU, env.def.features, 6, false),
    844     DEFINE_PROP_BIT("fmul",     SPARCCPU, env.def.features, 7, false),
    845     DEFINE_PROP_BIT("vis1",     SPARCCPU, env.def.features, 8, false),
    846     DEFINE_PROP_BIT("vis2",     SPARCCPU, env.def.features, 9, false),
    847     DEFINE_PROP_BIT("fsmuld",   SPARCCPU, env.def.features, 10, false),
    848     DEFINE_PROP_BIT("hypv",     SPARCCPU, env.def.features, 11, false),
    849     DEFINE_PROP_BIT("cmt",      SPARCCPU, env.def.features, 12, false),
    850     DEFINE_PROP_BIT("gl",       SPARCCPU, env.def.features, 13, false),
    851     DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
    852                          qdev_prop_uint64, target_ulong),
    853     DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
    854     DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
    855     DEFINE_PROP("nwindows", SPARCCPU, env.def.nwindows,
    856                 qdev_prop_nwindows, uint32_t),
    857     DEFINE_PROP_END_OF_LIST()
    858 };
    859 
    860 #ifndef CONFIG_USER_ONLY
    861 #include "hw/core/sysemu-cpu-ops.h"
    862 
    863 static const struct SysemuCPUOps sparc_sysemu_ops = {
    864     .get_phys_page_debug = sparc_cpu_get_phys_page_debug,
    865     .legacy_vmsd = &vmstate_sparc_cpu,
    866 };
    867 #endif
    868 
    869 #ifdef CONFIG_TCG
    870 #include "hw/core/tcg-cpu-ops.h"
    871 
    872 static const struct TCGCPUOps sparc_tcg_ops = {
    873     .initialize = sparc_tcg_init,
    874     .synchronize_from_tb = sparc_cpu_synchronize_from_tb,
    875     .restore_state_to_opc = sparc_restore_state_to_opc,
    876 
    877 #ifndef CONFIG_USER_ONLY
    878     .tlb_fill = sparc_cpu_tlb_fill,
    879     .cpu_exec_interrupt = sparc_cpu_exec_interrupt,
    880     .do_interrupt = sparc_cpu_do_interrupt,
    881     .do_transaction_failed = sparc_cpu_do_transaction_failed,
    882     .do_unaligned_access = sparc_cpu_do_unaligned_access,
    883 #endif /* !CONFIG_USER_ONLY */
    884 };
    885 #endif /* CONFIG_TCG */
    886 
    887 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
    888 {
    889     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
    890     CPUClass *cc = CPU_CLASS(oc);
    891     DeviceClass *dc = DEVICE_CLASS(oc);
    892 
    893     device_class_set_parent_realize(dc, sparc_cpu_realizefn,
    894                                     &scc->parent_realize);
    895     device_class_set_props(dc, sparc_cpu_properties);
    896 
    897     device_class_set_parent_reset(dc, sparc_cpu_reset, &scc->parent_reset);
    898 
    899     cc->class_by_name = sparc_cpu_class_by_name;
    900     cc->parse_features = sparc_cpu_parse_features;
    901     cc->has_work = sparc_cpu_has_work;
    902     cc->dump_state = sparc_cpu_dump_state;
    903 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
    904     cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
    905 #endif
    906     cc->set_pc = sparc_cpu_set_pc;
    907     cc->get_pc = sparc_cpu_get_pc;
    908     cc->gdb_read_register = sparc_cpu_gdb_read_register;
    909     cc->gdb_write_register = sparc_cpu_gdb_write_register;
    910 #ifndef CONFIG_USER_ONLY
    911     cc->sysemu_ops = &sparc_sysemu_ops;
    912 #endif
    913     cc->disas_set_info = cpu_sparc_disas_set_info;
    914 
    915 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
    916     cc->gdb_num_core_regs = 86;
    917 #else
    918     cc->gdb_num_core_regs = 72;
    919 #endif
    920     cc->tcg_ops = &sparc_tcg_ops;
    921 }
    922 
    923 static const TypeInfo sparc_cpu_type_info = {
    924     .name = TYPE_SPARC_CPU,
    925     .parent = TYPE_CPU,
    926     .instance_size = sizeof(SPARCCPU),
    927     .instance_init = sparc_cpu_initfn,
    928     .abstract = true,
    929     .class_size = sizeof(SPARCCPUClass),
    930     .class_init = sparc_cpu_class_init,
    931 };
    932 
    933 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
    934 {
    935     SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
    936     scc->cpu_def = data;
    937 }
    938 
    939 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
    940 {
    941     char *typename = sparc_cpu_type_name(def->name);
    942     TypeInfo ti = {
    943         .name = typename,
    944         .parent = TYPE_SPARC_CPU,
    945         .class_init = sparc_cpu_cpudef_class_init,
    946         .class_data = (void *)def,
    947     };
    948 
    949     type_register(&ti);
    950     g_free(typename);
    951 }
    952 
    953 static void sparc_cpu_register_types(void)
    954 {
    955     int i;
    956 
    957     type_register_static(&sparc_cpu_type_info);
    958     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
    959         sparc_register_cpudef_type(&sparc_defs[i]);
    960     }
    961 }
    962 
    963 type_init(sparc_cpu_register_types)