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