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