qemu/target-sparc/cpu.c
<<
>>
Prefs
   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 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/error-report.h"
  24
  25//#define DEBUG_FEATURES
  26
  27static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
  28
  29/* CPUClass::reset() */
  30static void sparc_cpu_reset(CPUState *s)
  31{
  32    SPARCCPU *cpu = SPARC_CPU(s);
  33    SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
  34    CPUSPARCState *env = &cpu->env;
  35
  36    scc->parent_reset(s);
  37
  38    memset(env, 0, offsetof(CPUSPARCState, version));
  39    tlb_flush(s, 1);
  40    env->cwp = 0;
  41#ifndef TARGET_SPARC64
  42    env->wim = 1;
  43#endif
  44    env->regwptr = env->regbase + (env->cwp * 16);
  45    CC_OP = CC_OP_FLAGS;
  46#if defined(CONFIG_USER_ONLY)
  47#ifdef TARGET_SPARC64
  48    env->cleanwin = env->nwindows - 2;
  49    env->cansave = env->nwindows - 2;
  50    env->pstate = PS_RMO | PS_PEF | PS_IE;
  51    env->asi = 0x82; /* Primary no-fault */
  52#endif
  53#else
  54#if !defined(TARGET_SPARC64)
  55    env->psret = 0;
  56    env->psrs = 1;
  57    env->psrps = 1;
  58#endif
  59#ifdef TARGET_SPARC64
  60    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
  61    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
  62    env->tl = env->maxtl;
  63    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
  64    env->lsu = 0;
  65#else
  66    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
  67    env->mmuregs[0] |= env->def->mmu_bm;
  68#endif
  69    env->pc = 0;
  70    env->npc = env->pc + 4;
  71#endif
  72    env->cache_control = 0;
  73}
  74
  75static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
  76{
  77    if (interrupt_request & CPU_INTERRUPT_HARD) {
  78        SPARCCPU *cpu = SPARC_CPU(cs);
  79        CPUSPARCState *env = &cpu->env;
  80
  81        if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
  82            int pil = env->interrupt_index & 0xf;
  83            int type = env->interrupt_index & 0xf0;
  84
  85            if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
  86                cs->exception_index = env->interrupt_index;
  87                sparc_cpu_do_interrupt(cs);
  88                return true;
  89            }
  90        }
  91    }
  92    return false;
  93}
  94
  95static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
  96{
  97    info->print_insn = print_insn_sparc;
  98#ifdef TARGET_SPARC64
  99    info->mach = bfd_mach_sparc_v9b;
 100#endif
 101}
 102
 103static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
 104{
 105    CPUClass *cc = CPU_GET_CLASS(cpu);
 106    CPUSPARCState *env = &cpu->env;
 107    char *s = g_strdup(cpu_model);
 108    char *featurestr, *name = strtok(s, ",");
 109    sparc_def_t def1, *def = &def1;
 110    Error *err = NULL;
 111
 112    if (cpu_sparc_find_by_name(def, name) < 0) {
 113        g_free(s);
 114        return -1;
 115    }
 116
 117    env->def = g_new0(sparc_def_t, 1);
 118    memcpy(env->def, def, sizeof(*def));
 119
 120    featurestr = strtok(NULL, ",");
 121    cc->parse_features(CPU(cpu), featurestr, &err);
 122    g_free(s);
 123    if (err) {
 124        error_report_err(err);
 125        return -1;
 126    }
 127
 128    env->version = def->iu_version;
 129    env->fsr = def->fpu_version;
 130    env->nwindows = def->nwindows;
 131#if !defined(TARGET_SPARC64)
 132    env->mmuregs[0] |= def->mmu_version;
 133    cpu_sparc_set_id(env, 0);
 134    env->mxccregs[7] |= def->mxcc_version;
 135#else
 136    env->mmu_version = def->mmu_version;
 137    env->maxtl = def->maxtl;
 138    env->version |= def->maxtl << 8;
 139    env->version |= def->nwindows - 1;
 140#endif
 141    return 0;
 142}
 143
 144SPARCCPU *cpu_sparc_init(const char *cpu_model)
 145{
 146    SPARCCPU *cpu;
 147
 148    cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
 149
 150    if (cpu_sparc_register(cpu, cpu_model) < 0) {
 151        object_unref(OBJECT(cpu));
 152        return NULL;
 153    }
 154
 155    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
 156
 157    return cpu;
 158}
 159
 160void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
 161{
 162#if !defined(TARGET_SPARC64)
 163    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
 164#endif
 165}
 166
 167static const sparc_def_t sparc_defs[] = {
 168#ifdef TARGET_SPARC64
 169    {
 170        .name = "Fujitsu Sparc64",
 171        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
 172        .fpu_version = 0x00000000,
 173        .mmu_version = mmu_us_12,
 174        .nwindows = 4,
 175        .maxtl = 4,
 176        .features = CPU_DEFAULT_FEATURES,
 177    },
 178    {
 179        .name = "Fujitsu Sparc64 III",
 180        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
 181        .fpu_version = 0x00000000,
 182        .mmu_version = mmu_us_12,
 183        .nwindows = 5,
 184        .maxtl = 4,
 185        .features = CPU_DEFAULT_FEATURES,
 186    },
 187    {
 188        .name = "Fujitsu Sparc64 IV",
 189        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
 190        .fpu_version = 0x00000000,
 191        .mmu_version = mmu_us_12,
 192        .nwindows = 8,
 193        .maxtl = 5,
 194        .features = CPU_DEFAULT_FEATURES,
 195    },
 196    {
 197        .name = "Fujitsu Sparc64 V",
 198        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
 199        .fpu_version = 0x00000000,
 200        .mmu_version = mmu_us_12,
 201        .nwindows = 8,
 202        .maxtl = 5,
 203        .features = CPU_DEFAULT_FEATURES,
 204    },
 205    {
 206        .name = "TI UltraSparc I",
 207        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
 208        .fpu_version = 0x00000000,
 209        .mmu_version = mmu_us_12,
 210        .nwindows = 8,
 211        .maxtl = 5,
 212        .features = CPU_DEFAULT_FEATURES,
 213    },
 214    {
 215        .name = "TI UltraSparc II",
 216        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
 217        .fpu_version = 0x00000000,
 218        .mmu_version = mmu_us_12,
 219        .nwindows = 8,
 220        .maxtl = 5,
 221        .features = CPU_DEFAULT_FEATURES,
 222    },
 223    {
 224        .name = "TI UltraSparc IIi",
 225        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
 226        .fpu_version = 0x00000000,
 227        .mmu_version = mmu_us_12,
 228        .nwindows = 8,
 229        .maxtl = 5,
 230        .features = CPU_DEFAULT_FEATURES,
 231    },
 232    {
 233        .name = "TI UltraSparc IIe",
 234        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
 235        .fpu_version = 0x00000000,
 236        .mmu_version = mmu_us_12,
 237        .nwindows = 8,
 238        .maxtl = 5,
 239        .features = CPU_DEFAULT_FEATURES,
 240    },
 241    {
 242        .name = "Sun UltraSparc III",
 243        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
 244        .fpu_version = 0x00000000,
 245        .mmu_version = mmu_us_12,
 246        .nwindows = 8,
 247        .maxtl = 5,
 248        .features = CPU_DEFAULT_FEATURES,
 249    },
 250    {
 251        .name = "Sun UltraSparc III Cu",
 252        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
 253        .fpu_version = 0x00000000,
 254        .mmu_version = mmu_us_3,
 255        .nwindows = 8,
 256        .maxtl = 5,
 257        .features = CPU_DEFAULT_FEATURES,
 258    },
 259    {
 260        .name = "Sun UltraSparc IIIi",
 261        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
 262        .fpu_version = 0x00000000,
 263        .mmu_version = mmu_us_12,
 264        .nwindows = 8,
 265        .maxtl = 5,
 266        .features = CPU_DEFAULT_FEATURES,
 267    },
 268    {
 269        .name = "Sun UltraSparc IV",
 270        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
 271        .fpu_version = 0x00000000,
 272        .mmu_version = mmu_us_4,
 273        .nwindows = 8,
 274        .maxtl = 5,
 275        .features = CPU_DEFAULT_FEATURES,
 276    },
 277    {
 278        .name = "Sun UltraSparc IV+",
 279        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
 280        .fpu_version = 0x00000000,
 281        .mmu_version = mmu_us_12,
 282        .nwindows = 8,
 283        .maxtl = 5,
 284        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
 285    },
 286    {
 287        .name = "Sun UltraSparc IIIi+",
 288        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
 289        .fpu_version = 0x00000000,
 290        .mmu_version = mmu_us_3,
 291        .nwindows = 8,
 292        .maxtl = 5,
 293        .features = CPU_DEFAULT_FEATURES,
 294    },
 295    {
 296        .name = "Sun UltraSparc T1",
 297        /* defined in sparc_ifu_fdp.v and ctu.h */
 298        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
 299        .fpu_version = 0x00000000,
 300        .mmu_version = mmu_sun4v,
 301        .nwindows = 8,
 302        .maxtl = 6,
 303        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
 304        | CPU_FEATURE_GL,
 305    },
 306    {
 307        .name = "Sun UltraSparc T2",
 308        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
 309        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
 310        .fpu_version = 0x00000000,
 311        .mmu_version = mmu_sun4v,
 312        .nwindows = 8,
 313        .maxtl = 6,
 314        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
 315        | CPU_FEATURE_GL,
 316    },
 317    {
 318        .name = "NEC UltraSparc I",
 319        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
 320        .fpu_version = 0x00000000,
 321        .mmu_version = mmu_us_12,
 322        .nwindows = 8,
 323        .maxtl = 5,
 324        .features = CPU_DEFAULT_FEATURES,
 325    },
 326#else
 327    {
 328        .name = "Fujitsu MB86904",
 329        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
 330        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 331        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
 332        .mmu_bm = 0x00004000,
 333        .mmu_ctpr_mask = 0x00ffffc0,
 334        .mmu_cxr_mask = 0x000000ff,
 335        .mmu_sfsr_mask = 0x00016fff,
 336        .mmu_trcr_mask = 0x00ffffff,
 337        .nwindows = 8,
 338        .features = CPU_DEFAULT_FEATURES,
 339    },
 340    {
 341        .name = "Fujitsu MB86907",
 342        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
 343        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 344        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
 345        .mmu_bm = 0x00004000,
 346        .mmu_ctpr_mask = 0xffffffc0,
 347        .mmu_cxr_mask = 0x000000ff,
 348        .mmu_sfsr_mask = 0x00016fff,
 349        .mmu_trcr_mask = 0xffffffff,
 350        .nwindows = 8,
 351        .features = CPU_DEFAULT_FEATURES,
 352    },
 353    {
 354        .name = "TI MicroSparc I",
 355        .iu_version = 0x41000000,
 356        .fpu_version = 4 << 17,
 357        .mmu_version = 0x41000000,
 358        .mmu_bm = 0x00004000,
 359        .mmu_ctpr_mask = 0x007ffff0,
 360        .mmu_cxr_mask = 0x0000003f,
 361        .mmu_sfsr_mask = 0x00016fff,
 362        .mmu_trcr_mask = 0x0000003f,
 363        .nwindows = 7,
 364        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
 365        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
 366        CPU_FEATURE_FMUL,
 367    },
 368    {
 369        .name = "TI MicroSparc II",
 370        .iu_version = 0x42000000,
 371        .fpu_version = 4 << 17,
 372        .mmu_version = 0x02000000,
 373        .mmu_bm = 0x00004000,
 374        .mmu_ctpr_mask = 0x00ffffc0,
 375        .mmu_cxr_mask = 0x000000ff,
 376        .mmu_sfsr_mask = 0x00016fff,
 377        .mmu_trcr_mask = 0x00ffffff,
 378        .nwindows = 8,
 379        .features = CPU_DEFAULT_FEATURES,
 380    },
 381    {
 382        .name = "TI MicroSparc IIep",
 383        .iu_version = 0x42000000,
 384        .fpu_version = 4 << 17,
 385        .mmu_version = 0x04000000,
 386        .mmu_bm = 0x00004000,
 387        .mmu_ctpr_mask = 0x00ffffc0,
 388        .mmu_cxr_mask = 0x000000ff,
 389        .mmu_sfsr_mask = 0x00016bff,
 390        .mmu_trcr_mask = 0x00ffffff,
 391        .nwindows = 8,
 392        .features = CPU_DEFAULT_FEATURES,
 393    },
 394    {
 395        .name = "TI SuperSparc 40", /* STP1020NPGA */
 396        .iu_version = 0x41000000, /* SuperSPARC 2.x */
 397        .fpu_version = 0 << 17,
 398        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
 399        .mmu_bm = 0x00002000,
 400        .mmu_ctpr_mask = 0xffffffc0,
 401        .mmu_cxr_mask = 0x0000ffff,
 402        .mmu_sfsr_mask = 0xffffffff,
 403        .mmu_trcr_mask = 0xffffffff,
 404        .nwindows = 8,
 405        .features = CPU_DEFAULT_FEATURES,
 406    },
 407    {
 408        .name = "TI SuperSparc 50", /* STP1020PGA */
 409        .iu_version = 0x40000000, /* SuperSPARC 3.x */
 410        .fpu_version = 0 << 17,
 411        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
 412        .mmu_bm = 0x00002000,
 413        .mmu_ctpr_mask = 0xffffffc0,
 414        .mmu_cxr_mask = 0x0000ffff,
 415        .mmu_sfsr_mask = 0xffffffff,
 416        .mmu_trcr_mask = 0xffffffff,
 417        .nwindows = 8,
 418        .features = CPU_DEFAULT_FEATURES,
 419    },
 420    {
 421        .name = "TI SuperSparc 51",
 422        .iu_version = 0x40000000, /* SuperSPARC 3.x */
 423        .fpu_version = 0 << 17,
 424        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
 425        .mmu_bm = 0x00002000,
 426        .mmu_ctpr_mask = 0xffffffc0,
 427        .mmu_cxr_mask = 0x0000ffff,
 428        .mmu_sfsr_mask = 0xffffffff,
 429        .mmu_trcr_mask = 0xffffffff,
 430        .mxcc_version = 0x00000104,
 431        .nwindows = 8,
 432        .features = CPU_DEFAULT_FEATURES,
 433    },
 434    {
 435        .name = "TI SuperSparc 60", /* STP1020APGA */
 436        .iu_version = 0x40000000, /* SuperSPARC 3.x */
 437        .fpu_version = 0 << 17,
 438        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
 439        .mmu_bm = 0x00002000,
 440        .mmu_ctpr_mask = 0xffffffc0,
 441        .mmu_cxr_mask = 0x0000ffff,
 442        .mmu_sfsr_mask = 0xffffffff,
 443        .mmu_trcr_mask = 0xffffffff,
 444        .nwindows = 8,
 445        .features = CPU_DEFAULT_FEATURES,
 446    },
 447    {
 448        .name = "TI SuperSparc 61",
 449        .iu_version = 0x44000000, /* SuperSPARC 3.x */
 450        .fpu_version = 0 << 17,
 451        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
 452        .mmu_bm = 0x00002000,
 453        .mmu_ctpr_mask = 0xffffffc0,
 454        .mmu_cxr_mask = 0x0000ffff,
 455        .mmu_sfsr_mask = 0xffffffff,
 456        .mmu_trcr_mask = 0xffffffff,
 457        .mxcc_version = 0x00000104,
 458        .nwindows = 8,
 459        .features = CPU_DEFAULT_FEATURES,
 460    },
 461    {
 462        .name = "TI SuperSparc II",
 463        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
 464        .fpu_version = 0 << 17,
 465        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
 466        .mmu_bm = 0x00002000,
 467        .mmu_ctpr_mask = 0xffffffc0,
 468        .mmu_cxr_mask = 0x0000ffff,
 469        .mmu_sfsr_mask = 0xffffffff,
 470        .mmu_trcr_mask = 0xffffffff,
 471        .mxcc_version = 0x00000104,
 472        .nwindows = 8,
 473        .features = CPU_DEFAULT_FEATURES,
 474    },
 475    {
 476        .name = "LEON2",
 477        .iu_version = 0xf2000000,
 478        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 479        .mmu_version = 0xf2000000,
 480        .mmu_bm = 0x00004000,
 481        .mmu_ctpr_mask = 0x007ffff0,
 482        .mmu_cxr_mask = 0x0000003f,
 483        .mmu_sfsr_mask = 0xffffffff,
 484        .mmu_trcr_mask = 0xffffffff,
 485        .nwindows = 8,
 486        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
 487    },
 488    {
 489        .name = "LEON3",
 490        .iu_version = 0xf3000000,
 491        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
 492        .mmu_version = 0xf3000000,
 493        .mmu_bm = 0x00000000,
 494        .mmu_ctpr_mask = 0xfffffffc,
 495        .mmu_cxr_mask = 0x000000ff,
 496        .mmu_sfsr_mask = 0xffffffff,
 497        .mmu_trcr_mask = 0xffffffff,
 498        .nwindows = 8,
 499        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
 500        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
 501        CPU_FEATURE_CASA,
 502    },
 503#endif
 504};
 505
 506static const char * const feature_name[] = {
 507    "float",
 508    "float128",
 509    "swap",
 510    "mul",
 511    "div",
 512    "flush",
 513    "fsqrt",
 514    "fmul",
 515    "vis1",
 516    "vis2",
 517    "fsmuld",
 518    "hypv",
 519    "cmt",
 520    "gl",
 521};
 522
 523static void print_features(FILE *f, fprintf_function cpu_fprintf,
 524                           uint32_t features, const char *prefix)
 525{
 526    unsigned int i;
 527
 528    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
 529        if (feature_name[i] && (features & (1 << i))) {
 530            if (prefix) {
 531                (*cpu_fprintf)(f, "%s", prefix);
 532            }
 533            (*cpu_fprintf)(f, "%s ", feature_name[i]);
 534        }
 535    }
 536}
 537
 538static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
 539{
 540    unsigned int i;
 541
 542    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
 543        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
 544            *features |= 1 << i;
 545            return;
 546        }
 547    }
 548    error_report("CPU feature %s not found", flagname);
 549}
 550
 551static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
 552{
 553    unsigned int i;
 554    const sparc_def_t *def = NULL;
 555
 556    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
 557        if (strcasecmp(name, sparc_defs[i].name) == 0) {
 558            def = &sparc_defs[i];
 559        }
 560    }
 561    if (!def) {
 562        return -1;
 563    }
 564    memcpy(cpu_def, def, sizeof(*def));
 565    return 0;
 566}
 567
 568static void sparc_cpu_parse_features(CPUState *cs, char *features,
 569                                     Error **errp)
 570{
 571    SPARCCPU *cpu = SPARC_CPU(cs);
 572    sparc_def_t *cpu_def = cpu->env.def;
 573    char *featurestr;
 574    uint32_t plus_features = 0;
 575    uint32_t minus_features = 0;
 576    uint64_t iu_version;
 577    uint32_t fpu_version, mmu_version, nwindows;
 578
 579    featurestr = features ? strtok(features, ",") : NULL;
 580    while (featurestr) {
 581        char *val;
 582
 583        if (featurestr[0] == '+') {
 584            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
 585        } else if (featurestr[0] == '-') {
 586            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
 587        } else if ((val = strchr(featurestr, '='))) {
 588            *val = 0; val++;
 589            if (!strcmp(featurestr, "iu_version")) {
 590                char *err;
 591
 592                iu_version = strtoll(val, &err, 0);
 593                if (!*val || *err) {
 594                    error_setg(errp, "bad numerical value %s", val);
 595                    return;
 596                }
 597                cpu_def->iu_version = iu_version;
 598#ifdef DEBUG_FEATURES
 599                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
 600#endif
 601            } else if (!strcmp(featurestr, "fpu_version")) {
 602                char *err;
 603
 604                fpu_version = strtol(val, &err, 0);
 605                if (!*val || *err) {
 606                    error_setg(errp, "bad numerical value %s", val);
 607                    return;
 608                }
 609                cpu_def->fpu_version = fpu_version;
 610#ifdef DEBUG_FEATURES
 611                fprintf(stderr, "fpu_version %x\n", fpu_version);
 612#endif
 613            } else if (!strcmp(featurestr, "mmu_version")) {
 614                char *err;
 615
 616                mmu_version = strtol(val, &err, 0);
 617                if (!*val || *err) {
 618                    error_setg(errp, "bad numerical value %s", val);
 619                    return;
 620                }
 621                cpu_def->mmu_version = mmu_version;
 622#ifdef DEBUG_FEATURES
 623                fprintf(stderr, "mmu_version %x\n", mmu_version);
 624#endif
 625            } else if (!strcmp(featurestr, "nwindows")) {
 626                char *err;
 627
 628                nwindows = strtol(val, &err, 0);
 629                if (!*val || *err || nwindows > MAX_NWINDOWS ||
 630                    nwindows < MIN_NWINDOWS) {
 631                    error_setg(errp, "bad numerical value %s", val);
 632                    return;
 633                }
 634                cpu_def->nwindows = nwindows;
 635#ifdef DEBUG_FEATURES
 636                fprintf(stderr, "nwindows %d\n", nwindows);
 637#endif
 638            } else {
 639                error_setg(errp, "unrecognized feature %s", featurestr);
 640                return;
 641            }
 642        } else {
 643            error_setg(errp, "feature string `%s' not in format "
 644                             "(+feature|-feature|feature=xyz)", featurestr);
 645            return;
 646        }
 647        featurestr = strtok(NULL, ",");
 648    }
 649    cpu_def->features |= plus_features;
 650    cpu_def->features &= ~minus_features;
 651#ifdef DEBUG_FEATURES
 652    print_features(stderr, fprintf, cpu_def->features, NULL);
 653#endif
 654}
 655
 656void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
 657{
 658    unsigned int i;
 659
 660    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
 661        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
 662                       " FPU %08x MMU %08x NWINS %d ",
 663                       sparc_defs[i].name,
 664                       sparc_defs[i].iu_version,
 665                       sparc_defs[i].fpu_version,
 666                       sparc_defs[i].mmu_version,
 667                       sparc_defs[i].nwindows);
 668        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
 669                       ~sparc_defs[i].features, "-");
 670        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
 671                       sparc_defs[i].features, "+");
 672        (*cpu_fprintf)(f, "\n");
 673    }
 674    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
 675    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
 676    (*cpu_fprintf)(f, "\n");
 677    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
 678    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
 679    (*cpu_fprintf)(f, "\n");
 680    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
 681                   "fpu_version mmu_version nwindows\n");
 682}
 683
 684static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
 685                         uint32_t cc)
 686{
 687    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
 688                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
 689                cc & PSR_CARRY ? 'C' : '-');
 690}
 691
 692#ifdef TARGET_SPARC64
 693#define REGS_PER_LINE 4
 694#else
 695#define REGS_PER_LINE 8
 696#endif
 697
 698void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 699                          int flags)
 700{
 701    SPARCCPU *cpu = SPARC_CPU(cs);
 702    CPUSPARCState *env = &cpu->env;
 703    int i, x;
 704
 705    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
 706                env->npc);
 707
 708    for (i = 0; i < 8; i++) {
 709        if (i % REGS_PER_LINE == 0) {
 710            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
 711        }
 712        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
 713        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
 714            cpu_fprintf(f, "\n");
 715        }
 716    }
 717    for (x = 0; x < 3; x++) {
 718        for (i = 0; i < 8; i++) {
 719            if (i % REGS_PER_LINE == 0) {
 720                cpu_fprintf(f, "%%%c%d-%d: ",
 721                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
 722                            i, i + REGS_PER_LINE - 1);
 723            }
 724            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
 725            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
 726                cpu_fprintf(f, "\n");
 727            }
 728        }
 729    }
 730
 731    for (i = 0; i < TARGET_DPREGS; i++) {
 732        if ((i & 3) == 0) {
 733            cpu_fprintf(f, "%%f%02d: ", i * 2);
 734        }
 735        cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
 736        if ((i & 3) == 3) {
 737            cpu_fprintf(f, "\n");
 738        }
 739    }
 740#ifdef TARGET_SPARC64
 741    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
 742                (unsigned)cpu_get_ccr(env));
 743    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
 744    cpu_fprintf(f, " xcc: ");
 745    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
 746    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
 747                env->psrpil);
 748    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
 749                "cleanwin: %d cwp: %d\n",
 750                env->cansave, env->canrestore, env->otherwin, env->wstate,
 751                env->cleanwin, env->nwindows - 1 - env->cwp);
 752    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
 753                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
 754#else
 755    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
 756    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
 757    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
 758                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
 759                env->wim);
 760    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
 761                env->fsr, env->y);
 762#endif
 763    cpu_fprintf(f, "\n");
 764}
 765
 766static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
 767{
 768    SPARCCPU *cpu = SPARC_CPU(cs);
 769
 770    cpu->env.pc = value;
 771    cpu->env.npc = value + 4;
 772}
 773
 774static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
 775{
 776    SPARCCPU *cpu = SPARC_CPU(cs);
 777
 778    cpu->env.pc = tb->pc;
 779    cpu->env.npc = tb->cs_base;
 780}
 781
 782static bool sparc_cpu_has_work(CPUState *cs)
 783{
 784    SPARCCPU *cpu = SPARC_CPU(cs);
 785    CPUSPARCState *env = &cpu->env;
 786
 787    return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
 788           cpu_interrupts_enabled(env);
 789}
 790
 791static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
 792{
 793    SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
 794#if defined(CONFIG_USER_ONLY)
 795    SPARCCPU *cpu = SPARC_CPU(dev);
 796    CPUSPARCState *env = &cpu->env;
 797
 798    if ((env->def->features & CPU_FEATURE_FLOAT)) {
 799        env->def->features |= CPU_FEATURE_FLOAT128;
 800    }
 801#endif
 802
 803    qemu_init_vcpu(CPU(dev));
 804
 805    scc->parent_realize(dev, errp);
 806}
 807
 808static void sparc_cpu_initfn(Object *obj)
 809{
 810    CPUState *cs = CPU(obj);
 811    SPARCCPU *cpu = SPARC_CPU(obj);
 812    CPUSPARCState *env = &cpu->env;
 813
 814    cs->env_ptr = env;
 815    cpu_exec_init(cs, &error_abort);
 816
 817    if (tcg_enabled()) {
 818        gen_intermediate_code_init(env);
 819    }
 820}
 821
 822static void sparc_cpu_uninitfn(Object *obj)
 823{
 824    SPARCCPU *cpu = SPARC_CPU(obj);
 825    CPUSPARCState *env = &cpu->env;
 826
 827    g_free(env->def);
 828}
 829
 830static void sparc_cpu_class_init(ObjectClass *oc, void *data)
 831{
 832    SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
 833    CPUClass *cc = CPU_CLASS(oc);
 834    DeviceClass *dc = DEVICE_CLASS(oc);
 835
 836    scc->parent_realize = dc->realize;
 837    dc->realize = sparc_cpu_realizefn;
 838
 839    scc->parent_reset = cc->reset;
 840    cc->reset = sparc_cpu_reset;
 841
 842    cc->parse_features = sparc_cpu_parse_features;
 843    cc->has_work = sparc_cpu_has_work;
 844    cc->do_interrupt = sparc_cpu_do_interrupt;
 845    cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
 846    cc->dump_state = sparc_cpu_dump_state;
 847#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
 848    cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
 849#endif
 850    cc->set_pc = sparc_cpu_set_pc;
 851    cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
 852    cc->gdb_read_register = sparc_cpu_gdb_read_register;
 853    cc->gdb_write_register = sparc_cpu_gdb_write_register;
 854#ifdef CONFIG_USER_ONLY
 855    cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
 856#else
 857    cc->do_unassigned_access = sparc_cpu_unassigned_access;
 858    cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
 859    cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
 860    cc->vmsd = &vmstate_sparc_cpu;
 861#endif
 862    cc->disas_set_info = cpu_sparc_disas_set_info;
 863
 864#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
 865    cc->gdb_num_core_regs = 86;
 866#else
 867    cc->gdb_num_core_regs = 72;
 868#endif
 869
 870    /*
 871     * Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
 872     * the object in cpus -> dangling pointer after final
 873     * object_unref().
 874     */
 875    dc->cannot_destroy_with_object_finalize_yet = true;
 876}
 877
 878static const TypeInfo sparc_cpu_type_info = {
 879    .name = TYPE_SPARC_CPU,
 880    .parent = TYPE_CPU,
 881    .instance_size = sizeof(SPARCCPU),
 882    .instance_init = sparc_cpu_initfn,
 883    .instance_finalize = sparc_cpu_uninitfn,
 884    .abstract = false,
 885    .class_size = sizeof(SPARCCPUClass),
 886    .class_init = sparc_cpu_class_init,
 887};
 888
 889static void sparc_cpu_register_types(void)
 890{
 891    type_register_static(&sparc_cpu_type_info);
 892}
 893
 894type_init(sparc_cpu_register_types)
 895