sparc: make cpu feature parsing property based
[qemu/kevin.git] / target / sparc / cpu.c
blob29296b241186687db1a54bc43fb7805076f082a2
1 /*
2 * Sparc CPU init helpers
4 * Copyright (c) 2003-2005 Fabrice Bellard
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.
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.
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/>.
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 #include "hw/qdev-properties.h"
26 #include "qapi/visitor.h"
28 //#define DEBUG_FEATURES
30 /* CPUClass::reset() */
31 static void sparc_cpu_reset(CPUState *s)
33 SPARCCPU *cpu = SPARC_CPU(s);
34 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
35 CPUSPARCState *env = &cpu->env;
37 scc->parent_reset(s);
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;
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;
79 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
81 if (interrupt_request & CPU_INTERRUPT_HARD) {
82 SPARCCPU *cpu = SPARC_CPU(cs);
83 CPUSPARCState *env = &cpu->env;
85 if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
86 int pil = env->interrupt_index & 0xf;
87 int type = env->interrupt_index & 0xf0;
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;
96 return false;
99 static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
101 info->print_insn = print_insn_sparc;
102 #ifdef TARGET_SPARC64
103 info->mach = bfd_mach_sparc_v9b;
104 #endif
107 static void
108 cpu_add_feat_as_prop(const char *typename, const char *name, const char *val)
110 GlobalProperty *prop = g_new0(typeof(*prop), 1);
111 prop->driver = typename;
112 prop->property = g_strdup(name);
113 prop->value = g_strdup(val);
114 prop->errp = &error_fatal;
115 qdev_prop_register_global(prop);
118 /* Parse "+feature,-feature,feature=foo" CPU feature string */
119 static void sparc_cpu_parse_features(const char *typename, char *features,
120 Error **errp)
122 GList *l, *plus_features = NULL, *minus_features = NULL;
123 char *featurestr; /* Single 'key=value" string being parsed */
124 static bool cpu_globals_initialized;
126 if (cpu_globals_initialized) {
127 return;
129 cpu_globals_initialized = true;
131 if (!features) {
132 return;
135 for (featurestr = strtok(features, ",");
136 featurestr;
137 featurestr = strtok(NULL, ",")) {
138 const char *name;
139 const char *val = NULL;
140 char *eq = NULL;
142 /* Compatibility syntax: */
143 if (featurestr[0] == '+') {
144 plus_features = g_list_append(plus_features,
145 g_strdup(featurestr + 1));
146 continue;
147 } else if (featurestr[0] == '-') {
148 minus_features = g_list_append(minus_features,
149 g_strdup(featurestr + 1));
150 continue;
153 eq = strchr(featurestr, '=');
154 name = featurestr;
155 if (eq) {
156 *eq++ = 0;
157 val = eq;
160 * Temporarily, only +feat/-feat will be supported
161 * for boolean properties until we remove the
162 * minus-overrides-plus semantics and just follow
163 * the order options appear on the command-line.
165 * TODO: warn if user is relying on minus-override-plus semantics
166 * TODO: remove minus-override-plus semantics after
167 * warning for a few releases
169 if (!strcasecmp(val, "on") ||
170 !strcasecmp(val, "off") ||
171 !strcasecmp(val, "true") ||
172 !strcasecmp(val, "false")) {
173 error_setg(errp, "Boolean properties in format %s=%s"
174 " are not supported", name, val);
175 return;
177 } else {
178 error_setg(errp, "Unsupported property format: %s", name);
179 return;
181 cpu_add_feat_as_prop(typename, name, val);
184 for (l = plus_features; l; l = l->next) {
185 const char *name = l->data;
186 cpu_add_feat_as_prop(typename, name, "on");
188 g_list_free_full(plus_features, g_free);
190 for (l = minus_features; l; l = l->next) {
191 const char *name = l->data;
192 cpu_add_feat_as_prop(typename, name, "off");
194 g_list_free_full(minus_features, g_free);
197 SPARCCPU *cpu_sparc_init(const char *cpu_model)
199 return SPARC_CPU(cpu_generic_init(TYPE_SPARC_CPU, cpu_model));
202 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
204 #if !defined(TARGET_SPARC64)
205 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
206 #endif
209 static const sparc_def_t sparc_defs[] = {
210 #ifdef TARGET_SPARC64
212 .name = "Fujitsu Sparc64",
213 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
214 .fpu_version = 0x00000000,
215 .mmu_version = mmu_us_12,
216 .nwindows = 4,
217 .maxtl = 4,
218 .features = CPU_DEFAULT_FEATURES,
221 .name = "Fujitsu Sparc64 III",
222 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
223 .fpu_version = 0x00000000,
224 .mmu_version = mmu_us_12,
225 .nwindows = 5,
226 .maxtl = 4,
227 .features = CPU_DEFAULT_FEATURES,
230 .name = "Fujitsu Sparc64 IV",
231 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
232 .fpu_version = 0x00000000,
233 .mmu_version = mmu_us_12,
234 .nwindows = 8,
235 .maxtl = 5,
236 .features = CPU_DEFAULT_FEATURES,
239 .name = "Fujitsu Sparc64 V",
240 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
241 .fpu_version = 0x00000000,
242 .mmu_version = mmu_us_12,
243 .nwindows = 8,
244 .maxtl = 5,
245 .features = CPU_DEFAULT_FEATURES,
248 .name = "TI UltraSparc I",
249 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
250 .fpu_version = 0x00000000,
251 .mmu_version = mmu_us_12,
252 .nwindows = 8,
253 .maxtl = 5,
254 .features = CPU_DEFAULT_FEATURES,
257 .name = "TI UltraSparc II",
258 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
259 .fpu_version = 0x00000000,
260 .mmu_version = mmu_us_12,
261 .nwindows = 8,
262 .maxtl = 5,
263 .features = CPU_DEFAULT_FEATURES,
266 .name = "TI UltraSparc IIi",
267 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
268 .fpu_version = 0x00000000,
269 .mmu_version = mmu_us_12,
270 .nwindows = 8,
271 .maxtl = 5,
272 .features = CPU_DEFAULT_FEATURES,
275 .name = "TI UltraSparc IIe",
276 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
277 .fpu_version = 0x00000000,
278 .mmu_version = mmu_us_12,
279 .nwindows = 8,
280 .maxtl = 5,
281 .features = CPU_DEFAULT_FEATURES,
284 .name = "Sun UltraSparc III",
285 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
286 .fpu_version = 0x00000000,
287 .mmu_version = mmu_us_12,
288 .nwindows = 8,
289 .maxtl = 5,
290 .features = CPU_DEFAULT_FEATURES,
293 .name = "Sun UltraSparc III Cu",
294 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
295 .fpu_version = 0x00000000,
296 .mmu_version = mmu_us_3,
297 .nwindows = 8,
298 .maxtl = 5,
299 .features = CPU_DEFAULT_FEATURES,
302 .name = "Sun UltraSparc IIIi",
303 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
304 .fpu_version = 0x00000000,
305 .mmu_version = mmu_us_12,
306 .nwindows = 8,
307 .maxtl = 5,
308 .features = CPU_DEFAULT_FEATURES,
311 .name = "Sun UltraSparc IV",
312 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
313 .fpu_version = 0x00000000,
314 .mmu_version = mmu_us_4,
315 .nwindows = 8,
316 .maxtl = 5,
317 .features = CPU_DEFAULT_FEATURES,
320 .name = "Sun UltraSparc IV+",
321 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
322 .fpu_version = 0x00000000,
323 .mmu_version = mmu_us_12,
324 .nwindows = 8,
325 .maxtl = 5,
326 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
329 .name = "Sun UltraSparc IIIi+",
330 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
331 .fpu_version = 0x00000000,
332 .mmu_version = mmu_us_3,
333 .nwindows = 8,
334 .maxtl = 5,
335 .features = CPU_DEFAULT_FEATURES,
338 .name = "Sun UltraSparc T1",
339 /* defined in sparc_ifu_fdp.v and ctu.h */
340 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
341 .fpu_version = 0x00000000,
342 .mmu_version = mmu_sun4v,
343 .nwindows = 8,
344 .maxtl = 6,
345 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
346 | CPU_FEATURE_GL,
349 .name = "Sun UltraSparc T2",
350 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
351 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
352 .fpu_version = 0x00000000,
353 .mmu_version = mmu_sun4v,
354 .nwindows = 8,
355 .maxtl = 6,
356 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
357 | CPU_FEATURE_GL,
360 .name = "NEC UltraSparc I",
361 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
362 .fpu_version = 0x00000000,
363 .mmu_version = mmu_us_12,
364 .nwindows = 8,
365 .maxtl = 5,
366 .features = CPU_DEFAULT_FEATURES,
368 #else
370 .name = "Fujitsu MB86904",
371 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
372 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
373 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
374 .mmu_bm = 0x00004000,
375 .mmu_ctpr_mask = 0x00ffffc0,
376 .mmu_cxr_mask = 0x000000ff,
377 .mmu_sfsr_mask = 0x00016fff,
378 .mmu_trcr_mask = 0x00ffffff,
379 .nwindows = 8,
380 .features = CPU_DEFAULT_FEATURES,
383 .name = "Fujitsu MB86907",
384 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
385 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
386 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
387 .mmu_bm = 0x00004000,
388 .mmu_ctpr_mask = 0xffffffc0,
389 .mmu_cxr_mask = 0x000000ff,
390 .mmu_sfsr_mask = 0x00016fff,
391 .mmu_trcr_mask = 0xffffffff,
392 .nwindows = 8,
393 .features = CPU_DEFAULT_FEATURES,
396 .name = "TI MicroSparc I",
397 .iu_version = 0x41000000,
398 .fpu_version = 4 << 17,
399 .mmu_version = 0x41000000,
400 .mmu_bm = 0x00004000,
401 .mmu_ctpr_mask = 0x007ffff0,
402 .mmu_cxr_mask = 0x0000003f,
403 .mmu_sfsr_mask = 0x00016fff,
404 .mmu_trcr_mask = 0x0000003f,
405 .nwindows = 7,
406 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
407 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
408 CPU_FEATURE_FMUL,
411 .name = "TI MicroSparc II",
412 .iu_version = 0x42000000,
413 .fpu_version = 4 << 17,
414 .mmu_version = 0x02000000,
415 .mmu_bm = 0x00004000,
416 .mmu_ctpr_mask = 0x00ffffc0,
417 .mmu_cxr_mask = 0x000000ff,
418 .mmu_sfsr_mask = 0x00016fff,
419 .mmu_trcr_mask = 0x00ffffff,
420 .nwindows = 8,
421 .features = CPU_DEFAULT_FEATURES,
424 .name = "TI MicroSparc IIep",
425 .iu_version = 0x42000000,
426 .fpu_version = 4 << 17,
427 .mmu_version = 0x04000000,
428 .mmu_bm = 0x00004000,
429 .mmu_ctpr_mask = 0x00ffffc0,
430 .mmu_cxr_mask = 0x000000ff,
431 .mmu_sfsr_mask = 0x00016bff,
432 .mmu_trcr_mask = 0x00ffffff,
433 .nwindows = 8,
434 .features = CPU_DEFAULT_FEATURES,
437 .name = "TI SuperSparc 40", /* STP1020NPGA */
438 .iu_version = 0x41000000, /* SuperSPARC 2.x */
439 .fpu_version = 0 << 17,
440 .mmu_version = 0x00000800, /* SuperSPARC 2.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,
450 .name = "TI SuperSparc 50", /* STP1020PGA */
451 .iu_version = 0x40000000, /* SuperSPARC 3.x */
452 .fpu_version = 0 << 17,
453 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no 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 .nwindows = 8,
460 .features = CPU_DEFAULT_FEATURES,
463 .name = "TI SuperSparc 51",
464 .iu_version = 0x40000000, /* SuperSPARC 3.x */
465 .fpu_version = 0 << 17,
466 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
467 .mmu_bm = 0x00002000,
468 .mmu_ctpr_mask = 0xffffffc0,
469 .mmu_cxr_mask = 0x0000ffff,
470 .mmu_sfsr_mask = 0xffffffff,
471 .mmu_trcr_mask = 0xffffffff,
472 .mxcc_version = 0x00000104,
473 .nwindows = 8,
474 .features = CPU_DEFAULT_FEATURES,
477 .name = "TI SuperSparc 60", /* STP1020APGA */
478 .iu_version = 0x40000000, /* SuperSPARC 3.x */
479 .fpu_version = 0 << 17,
480 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
481 .mmu_bm = 0x00002000,
482 .mmu_ctpr_mask = 0xffffffc0,
483 .mmu_cxr_mask = 0x0000ffff,
484 .mmu_sfsr_mask = 0xffffffff,
485 .mmu_trcr_mask = 0xffffffff,
486 .nwindows = 8,
487 .features = CPU_DEFAULT_FEATURES,
490 .name = "TI SuperSparc 61",
491 .iu_version = 0x44000000, /* SuperSPARC 3.x */
492 .fpu_version = 0 << 17,
493 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
494 .mmu_bm = 0x00002000,
495 .mmu_ctpr_mask = 0xffffffc0,
496 .mmu_cxr_mask = 0x0000ffff,
497 .mmu_sfsr_mask = 0xffffffff,
498 .mmu_trcr_mask = 0xffffffff,
499 .mxcc_version = 0x00000104,
500 .nwindows = 8,
501 .features = CPU_DEFAULT_FEATURES,
504 .name = "TI SuperSparc II",
505 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
506 .fpu_version = 0 << 17,
507 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
508 .mmu_bm = 0x00002000,
509 .mmu_ctpr_mask = 0xffffffc0,
510 .mmu_cxr_mask = 0x0000ffff,
511 .mmu_sfsr_mask = 0xffffffff,
512 .mmu_trcr_mask = 0xffffffff,
513 .mxcc_version = 0x00000104,
514 .nwindows = 8,
515 .features = CPU_DEFAULT_FEATURES,
518 .name = "LEON2",
519 .iu_version = 0xf2000000,
520 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
521 .mmu_version = 0xf2000000,
522 .mmu_bm = 0x00004000,
523 .mmu_ctpr_mask = 0x007ffff0,
524 .mmu_cxr_mask = 0x0000003f,
525 .mmu_sfsr_mask = 0xffffffff,
526 .mmu_trcr_mask = 0xffffffff,
527 .nwindows = 8,
528 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
531 .name = "LEON3",
532 .iu_version = 0xf3000000,
533 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
534 .mmu_version = 0xf3000000,
535 .mmu_bm = 0x00000000,
536 .mmu_ctpr_mask = 0xfffffffc,
537 .mmu_cxr_mask = 0x000000ff,
538 .mmu_sfsr_mask = 0xffffffff,
539 .mmu_trcr_mask = 0xffffffff,
540 .nwindows = 8,
541 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
542 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
543 CPU_FEATURE_CASA,
545 #endif
548 static const char * const feature_name[] = {
549 "float",
550 "float128",
551 "swap",
552 "mul",
553 "div",
554 "flush",
555 "fsqrt",
556 "fmul",
557 "vis1",
558 "vis2",
559 "fsmuld",
560 "hypv",
561 "cmt",
562 "gl",
565 static void print_features(FILE *f, fprintf_function cpu_fprintf,
566 uint32_t features, const char *prefix)
568 unsigned int i;
570 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
571 if (feature_name[i] && (features & (1 << i))) {
572 if (prefix) {
573 (*cpu_fprintf)(f, "%s", prefix);
575 (*cpu_fprintf)(f, "%s ", feature_name[i]);
580 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
582 unsigned int i;
584 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
585 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
586 " FPU %08x MMU %08x NWINS %d ",
587 sparc_defs[i].name,
588 sparc_defs[i].iu_version,
589 sparc_defs[i].fpu_version,
590 sparc_defs[i].mmu_version,
591 sparc_defs[i].nwindows);
592 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
593 ~sparc_defs[i].features, "-");
594 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
595 sparc_defs[i].features, "+");
596 (*cpu_fprintf)(f, "\n");
598 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
599 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
600 (*cpu_fprintf)(f, "\n");
601 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
602 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
603 (*cpu_fprintf)(f, "\n");
604 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
605 "fpu_version mmu_version nwindows\n");
608 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
609 uint32_t cc)
611 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
612 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
613 cc & PSR_CARRY ? 'C' : '-');
616 #ifdef TARGET_SPARC64
617 #define REGS_PER_LINE 4
618 #else
619 #define REGS_PER_LINE 8
620 #endif
622 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
623 int flags)
625 SPARCCPU *cpu = SPARC_CPU(cs);
626 CPUSPARCState *env = &cpu->env;
627 int i, x;
629 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
630 env->npc);
632 for (i = 0; i < 8; i++) {
633 if (i % REGS_PER_LINE == 0) {
634 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
636 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
637 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
638 cpu_fprintf(f, "\n");
641 for (x = 0; x < 3; x++) {
642 for (i = 0; i < 8; i++) {
643 if (i % REGS_PER_LINE == 0) {
644 cpu_fprintf(f, "%%%c%d-%d: ",
645 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
646 i, i + REGS_PER_LINE - 1);
648 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
649 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
650 cpu_fprintf(f, "\n");
655 for (i = 0; i < TARGET_DPREGS; i++) {
656 if ((i & 3) == 0) {
657 cpu_fprintf(f, "%%f%02d: ", i * 2);
659 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
660 if ((i & 3) == 3) {
661 cpu_fprintf(f, "\n");
664 #ifdef TARGET_SPARC64
665 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
666 (unsigned)cpu_get_ccr(env));
667 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
668 cpu_fprintf(f, " xcc: ");
669 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
670 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
671 env->psrpil, env->gl);
672 cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
673 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
674 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
675 "cleanwin: %d cwp: %d\n",
676 env->cansave, env->canrestore, env->otherwin, env->wstate,
677 env->cleanwin, env->nwindows - 1 - env->cwp);
678 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
679 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
681 #else
682 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
683 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
684 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
685 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
686 env->wim);
687 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
688 env->fsr, env->y);
689 #endif
690 cpu_fprintf(f, "\n");
693 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
695 SPARCCPU *cpu = SPARC_CPU(cs);
697 cpu->env.pc = value;
698 cpu->env.npc = value + 4;
701 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
703 SPARCCPU *cpu = SPARC_CPU(cs);
705 cpu->env.pc = tb->pc;
706 cpu->env.npc = tb->cs_base;
709 static bool sparc_cpu_has_work(CPUState *cs)
711 SPARCCPU *cpu = SPARC_CPU(cs);
712 CPUSPARCState *env = &cpu->env;
714 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
715 cpu_interrupts_enabled(env);
718 static char *sparc_cpu_type_name(const char *cpu_model)
720 char *name = g_strdup_printf("%s-" TYPE_SPARC_CPU, cpu_model);
721 char *s = name;
723 /* SPARC cpu model names happen to have whitespaces,
724 * as type names shouldn't have spaces replace them with '-'
726 while ((s = strchr(s, ' '))) {
727 *s = '-';
730 return name;
733 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
735 ObjectClass *oc;
736 char *typename;
738 if (cpu_model == NULL) {
739 return NULL;
742 typename = sparc_cpu_type_name(cpu_model);
743 oc = object_class_by_name(typename);
744 g_free(typename);
745 return oc;
748 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
750 CPUState *cs = CPU(dev);
751 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
752 Error *local_err = NULL;
753 SPARCCPU *cpu = SPARC_CPU(dev);
754 CPUSPARCState *env = &cpu->env;
756 #if defined(CONFIG_USER_ONLY)
757 if ((env->def.features & CPU_FEATURE_FLOAT)) {
758 env->def.features |= CPU_FEATURE_FLOAT128;
760 #endif
762 env->version = env->def.iu_version;
763 env->fsr = env->def.fpu_version;
764 env->nwindows = env->def.nwindows;
765 #if !defined(TARGET_SPARC64)
766 env->mmuregs[0] |= env->def.mmu_version;
767 cpu_sparc_set_id(env, 0);
768 env->mxccregs[7] |= env->def.mxcc_version;
769 #else
770 env->mmu_version = env->def.mmu_version;
771 env->maxtl = env->def.maxtl;
772 env->version |= env->def.maxtl << 8;
773 env->version |= env->def.nwindows - 1;
774 #endif
776 cpu_exec_realizefn(cs, &local_err);
777 if (local_err != NULL) {
778 error_propagate(errp, local_err);
779 return;
782 qemu_init_vcpu(cs);
784 scc->parent_realize(dev, errp);
787 static void sparc_cpu_initfn(Object *obj)
789 CPUState *cs = CPU(obj);
790 SPARCCPU *cpu = SPARC_CPU(obj);
791 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
792 CPUSPARCState *env = &cpu->env;
794 cs->env_ptr = env;
796 if (tcg_enabled()) {
797 gen_intermediate_code_init(env);
800 if (scc->cpu_def) {
801 env->def = *scc->cpu_def;
805 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
806 void *opaque, Error **errp)
808 SPARCCPU *cpu = SPARC_CPU(obj);
809 int64_t value = cpu->env.def.nwindows;
811 visit_type_int(v, name, &value, errp);
814 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
815 void *opaque, Error **errp)
817 const int64_t min = MIN_NWINDOWS;
818 const int64_t max = MAX_NWINDOWS;
819 SPARCCPU *cpu = SPARC_CPU(obj);
820 Error *err = NULL;
821 int64_t value;
823 visit_type_int(v, name, &value, &err);
824 if (err) {
825 error_propagate(errp, err);
826 return;
829 if (value < min || value > max) {
830 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
831 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
832 object_get_typename(obj), name ? name : "null",
833 value, min, max);
834 return;
836 cpu->env.def.nwindows = value;
839 static PropertyInfo qdev_prop_nwindows = {
840 .name = "int",
841 .get = sparc_get_nwindows,
842 .set = sparc_set_nwindows,
845 static Property sparc_cpu_properties[] = {
846 DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false),
847 DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
848 DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false),
849 DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false),
850 DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false),
851 DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false),
852 DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false),
853 DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false),
854 DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false),
855 DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false),
856 DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false),
857 DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false),
858 DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false),
859 DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false),
860 DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
861 qdev_prop_uint64, target_ulong),
862 DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
863 DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
864 { .name = "nwindows", .info = &qdev_prop_nwindows },
865 DEFINE_PROP_END_OF_LIST()
868 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
870 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
871 CPUClass *cc = CPU_CLASS(oc);
872 DeviceClass *dc = DEVICE_CLASS(oc);
874 scc->parent_realize = dc->realize;
875 dc->realize = sparc_cpu_realizefn;
876 dc->props = sparc_cpu_properties;
878 scc->parent_reset = cc->reset;
879 cc->reset = sparc_cpu_reset;
881 cc->class_by_name = sparc_cpu_class_by_name;
882 cc->parse_features = sparc_cpu_parse_features;
883 cc->has_work = sparc_cpu_has_work;
884 cc->do_interrupt = sparc_cpu_do_interrupt;
885 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
886 cc->dump_state = sparc_cpu_dump_state;
887 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
888 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
889 #endif
890 cc->set_pc = sparc_cpu_set_pc;
891 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
892 cc->gdb_read_register = sparc_cpu_gdb_read_register;
893 cc->gdb_write_register = sparc_cpu_gdb_write_register;
894 #ifdef CONFIG_USER_ONLY
895 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
896 #else
897 cc->do_unassigned_access = sparc_cpu_unassigned_access;
898 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
899 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
900 cc->vmsd = &vmstate_sparc_cpu;
901 #endif
902 cc->disas_set_info = cpu_sparc_disas_set_info;
904 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
905 cc->gdb_num_core_regs = 86;
906 #else
907 cc->gdb_num_core_regs = 72;
908 #endif
911 static const TypeInfo sparc_cpu_type_info = {
912 .name = TYPE_SPARC_CPU,
913 .parent = TYPE_CPU,
914 .instance_size = sizeof(SPARCCPU),
915 .instance_init = sparc_cpu_initfn,
916 .abstract = true,
917 .class_size = sizeof(SPARCCPUClass),
918 .class_init = sparc_cpu_class_init,
921 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
923 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
924 scc->cpu_def = data;
927 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
929 char *typename = sparc_cpu_type_name(def->name);
930 TypeInfo ti = {
931 .name = typename,
932 .parent = TYPE_SPARC_CPU,
933 .class_init = sparc_cpu_cpudef_class_init,
934 .class_data = (void *)def,
937 type_register(&ti);
938 g_free(typename);
941 static void sparc_cpu_register_types(void)
943 int i;
945 type_register_static(&sparc_cpu_type_info);
946 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
947 sparc_register_cpudef_type(&sparc_defs[i]);
951 type_init(sparc_cpu_register_types)