hw/arm/virt: Disable pl011 clock migration if needed
[qemu/ar7.git] / target / sparc / cpu.c
blobaece2c7dc8392a720f3c2c18a7cee4c27b8b84ae
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.1 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/module.h"
24 #include "qemu/qemu-print.h"
25 #include "exec/exec-all.h"
26 #include "hw/qdev-properties.h"
27 #include "qapi/visitor.h"
29 //#define DEBUG_FEATURES
31 static void sparc_cpu_reset(DeviceState *dev)
33 CPUState *s = CPU(dev);
34 SPARCCPU *cpu = SPARC_CPU(s);
35 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
36 CPUSPARCState *env = &cpu->env;
38 scc->parent_reset(dev);
40 memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
41 env->cwp = 0;
42 #ifndef TARGET_SPARC64
43 env->wim = 1;
44 #endif
45 env->regwptr = env->regbase + (env->cwp * 16);
46 CC_OP = CC_OP_FLAGS;
47 #if defined(CONFIG_USER_ONLY)
48 #ifdef TARGET_SPARC64
49 env->cleanwin = env->nwindows - 2;
50 env->cansave = env->nwindows - 2;
51 env->pstate = PS_RMO | PS_PEF | PS_IE;
52 env->asi = 0x82; /* Primary no-fault */
53 #endif
54 #else
55 #if !defined(TARGET_SPARC64)
56 env->psret = 0;
57 env->psrs = 1;
58 env->psrps = 1;
59 #endif
60 #ifdef TARGET_SPARC64
61 env->pstate = PS_PRIV | PS_RED | PS_PEF;
62 if (!cpu_has_hypervisor(env)) {
63 env->pstate |= PS_AG;
65 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
66 env->tl = env->maxtl;
67 env->gl = 2;
68 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
69 env->lsu = 0;
70 #else
71 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
72 env->mmuregs[0] |= env->def.mmu_bm;
73 #endif
74 env->pc = 0;
75 env->npc = env->pc + 4;
76 #endif
77 env->cache_control = 0;
80 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
82 if (interrupt_request & CPU_INTERRUPT_HARD) {
83 SPARCCPU *cpu = SPARC_CPU(cs);
84 CPUSPARCState *env = &cpu->env;
86 if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
87 int pil = env->interrupt_index & 0xf;
88 int type = env->interrupt_index & 0xf0;
90 if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
91 cs->exception_index = env->interrupt_index;
92 sparc_cpu_do_interrupt(cs);
93 return true;
97 return false;
100 static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
102 info->print_insn = print_insn_sparc;
103 #ifdef TARGET_SPARC64
104 info->mach = bfd_mach_sparc_v9b;
105 #endif
108 static void
109 cpu_add_feat_as_prop(const char *typename, const char *name, const char *val)
111 GlobalProperty *prop = g_new0(typeof(*prop), 1);
112 prop->driver = typename;
113 prop->property = g_strdup(name);
114 prop->value = g_strdup(val);
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 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
199 #if !defined(TARGET_SPARC64)
200 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
201 #endif
204 static const sparc_def_t sparc_defs[] = {
205 #ifdef TARGET_SPARC64
207 .name = "Fujitsu Sparc64",
208 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
209 .fpu_version = 0x00000000,
210 .mmu_version = mmu_us_12,
211 .nwindows = 4,
212 .maxtl = 4,
213 .features = CPU_DEFAULT_FEATURES,
216 .name = "Fujitsu Sparc64 III",
217 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
218 .fpu_version = 0x00000000,
219 .mmu_version = mmu_us_12,
220 .nwindows = 5,
221 .maxtl = 4,
222 .features = CPU_DEFAULT_FEATURES,
225 .name = "Fujitsu Sparc64 IV",
226 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
227 .fpu_version = 0x00000000,
228 .mmu_version = mmu_us_12,
229 .nwindows = 8,
230 .maxtl = 5,
231 .features = CPU_DEFAULT_FEATURES,
234 .name = "Fujitsu Sparc64 V",
235 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
236 .fpu_version = 0x00000000,
237 .mmu_version = mmu_us_12,
238 .nwindows = 8,
239 .maxtl = 5,
240 .features = CPU_DEFAULT_FEATURES,
243 .name = "TI UltraSparc I",
244 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
245 .fpu_version = 0x00000000,
246 .mmu_version = mmu_us_12,
247 .nwindows = 8,
248 .maxtl = 5,
249 .features = CPU_DEFAULT_FEATURES,
252 .name = "TI UltraSparc II",
253 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
254 .fpu_version = 0x00000000,
255 .mmu_version = mmu_us_12,
256 .nwindows = 8,
257 .maxtl = 5,
258 .features = CPU_DEFAULT_FEATURES,
261 .name = "TI UltraSparc IIi",
262 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
263 .fpu_version = 0x00000000,
264 .mmu_version = mmu_us_12,
265 .nwindows = 8,
266 .maxtl = 5,
267 .features = CPU_DEFAULT_FEATURES,
270 .name = "TI UltraSparc IIe",
271 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
272 .fpu_version = 0x00000000,
273 .mmu_version = mmu_us_12,
274 .nwindows = 8,
275 .maxtl = 5,
276 .features = CPU_DEFAULT_FEATURES,
279 .name = "Sun UltraSparc III",
280 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
281 .fpu_version = 0x00000000,
282 .mmu_version = mmu_us_12,
283 .nwindows = 8,
284 .maxtl = 5,
285 .features = CPU_DEFAULT_FEATURES,
288 .name = "Sun UltraSparc III Cu",
289 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
290 .fpu_version = 0x00000000,
291 .mmu_version = mmu_us_3,
292 .nwindows = 8,
293 .maxtl = 5,
294 .features = CPU_DEFAULT_FEATURES,
297 .name = "Sun UltraSparc IIIi",
298 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
299 .fpu_version = 0x00000000,
300 .mmu_version = mmu_us_12,
301 .nwindows = 8,
302 .maxtl = 5,
303 .features = CPU_DEFAULT_FEATURES,
306 .name = "Sun UltraSparc IV",
307 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
308 .fpu_version = 0x00000000,
309 .mmu_version = mmu_us_4,
310 .nwindows = 8,
311 .maxtl = 5,
312 .features = CPU_DEFAULT_FEATURES,
315 .name = "Sun UltraSparc IV+",
316 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
317 .fpu_version = 0x00000000,
318 .mmu_version = mmu_us_12,
319 .nwindows = 8,
320 .maxtl = 5,
321 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
324 .name = "Sun UltraSparc IIIi+",
325 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
326 .fpu_version = 0x00000000,
327 .mmu_version = mmu_us_3,
328 .nwindows = 8,
329 .maxtl = 5,
330 .features = CPU_DEFAULT_FEATURES,
333 .name = "Sun UltraSparc T1",
334 /* defined in sparc_ifu_fdp.v and ctu.h */
335 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
336 .fpu_version = 0x00000000,
337 .mmu_version = mmu_sun4v,
338 .nwindows = 8,
339 .maxtl = 6,
340 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
341 | CPU_FEATURE_GL,
344 .name = "Sun UltraSparc T2",
345 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
346 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
347 .fpu_version = 0x00000000,
348 .mmu_version = mmu_sun4v,
349 .nwindows = 8,
350 .maxtl = 6,
351 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
352 | CPU_FEATURE_GL,
355 .name = "NEC UltraSparc I",
356 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
357 .fpu_version = 0x00000000,
358 .mmu_version = mmu_us_12,
359 .nwindows = 8,
360 .maxtl = 5,
361 .features = CPU_DEFAULT_FEATURES,
363 #else
365 .name = "Fujitsu MB86904",
366 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
367 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
368 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
369 .mmu_bm = 0x00004000,
370 .mmu_ctpr_mask = 0x00ffffc0,
371 .mmu_cxr_mask = 0x000000ff,
372 .mmu_sfsr_mask = 0x00016fff,
373 .mmu_trcr_mask = 0x00ffffff,
374 .nwindows = 8,
375 .features = CPU_DEFAULT_FEATURES,
378 .name = "Fujitsu MB86907",
379 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
380 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
381 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
382 .mmu_bm = 0x00004000,
383 .mmu_ctpr_mask = 0xffffffc0,
384 .mmu_cxr_mask = 0x000000ff,
385 .mmu_sfsr_mask = 0x00016fff,
386 .mmu_trcr_mask = 0xffffffff,
387 .nwindows = 8,
388 .features = CPU_DEFAULT_FEATURES,
391 .name = "TI MicroSparc I",
392 .iu_version = 0x41000000,
393 .fpu_version = 4 << 17,
394 .mmu_version = 0x41000000,
395 .mmu_bm = 0x00004000,
396 .mmu_ctpr_mask = 0x007ffff0,
397 .mmu_cxr_mask = 0x0000003f,
398 .mmu_sfsr_mask = 0x00016fff,
399 .mmu_trcr_mask = 0x0000003f,
400 .nwindows = 7,
401 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
402 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
403 CPU_FEATURE_FMUL,
406 .name = "TI MicroSparc II",
407 .iu_version = 0x42000000,
408 .fpu_version = 4 << 17,
409 .mmu_version = 0x02000000,
410 .mmu_bm = 0x00004000,
411 .mmu_ctpr_mask = 0x00ffffc0,
412 .mmu_cxr_mask = 0x000000ff,
413 .mmu_sfsr_mask = 0x00016fff,
414 .mmu_trcr_mask = 0x00ffffff,
415 .nwindows = 8,
416 .features = CPU_DEFAULT_FEATURES,
419 .name = "TI MicroSparc IIep",
420 .iu_version = 0x42000000,
421 .fpu_version = 4 << 17,
422 .mmu_version = 0x04000000,
423 .mmu_bm = 0x00004000,
424 .mmu_ctpr_mask = 0x00ffffc0,
425 .mmu_cxr_mask = 0x000000ff,
426 .mmu_sfsr_mask = 0x00016bff,
427 .mmu_trcr_mask = 0x00ffffff,
428 .nwindows = 8,
429 .features = CPU_DEFAULT_FEATURES,
432 .name = "TI SuperSparc 40", /* STP1020NPGA */
433 .iu_version = 0x41000000, /* SuperSPARC 2.x */
434 .fpu_version = 0 << 17,
435 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
436 .mmu_bm = 0x00002000,
437 .mmu_ctpr_mask = 0xffffffc0,
438 .mmu_cxr_mask = 0x0000ffff,
439 .mmu_sfsr_mask = 0xffffffff,
440 .mmu_trcr_mask = 0xffffffff,
441 .nwindows = 8,
442 .features = CPU_DEFAULT_FEATURES,
445 .name = "TI SuperSparc 50", /* STP1020PGA */
446 .iu_version = 0x40000000, /* SuperSPARC 3.x */
447 .fpu_version = 0 << 17,
448 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
449 .mmu_bm = 0x00002000,
450 .mmu_ctpr_mask = 0xffffffc0,
451 .mmu_cxr_mask = 0x0000ffff,
452 .mmu_sfsr_mask = 0xffffffff,
453 .mmu_trcr_mask = 0xffffffff,
454 .nwindows = 8,
455 .features = CPU_DEFAULT_FEATURES,
458 .name = "TI SuperSparc 51",
459 .iu_version = 0x40000000, /* SuperSPARC 3.x */
460 .fpu_version = 0 << 17,
461 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
462 .mmu_bm = 0x00002000,
463 .mmu_ctpr_mask = 0xffffffc0,
464 .mmu_cxr_mask = 0x0000ffff,
465 .mmu_sfsr_mask = 0xffffffff,
466 .mmu_trcr_mask = 0xffffffff,
467 .mxcc_version = 0x00000104,
468 .nwindows = 8,
469 .features = CPU_DEFAULT_FEATURES,
472 .name = "TI SuperSparc 60", /* STP1020APGA */
473 .iu_version = 0x40000000, /* SuperSPARC 3.x */
474 .fpu_version = 0 << 17,
475 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
476 .mmu_bm = 0x00002000,
477 .mmu_ctpr_mask = 0xffffffc0,
478 .mmu_cxr_mask = 0x0000ffff,
479 .mmu_sfsr_mask = 0xffffffff,
480 .mmu_trcr_mask = 0xffffffff,
481 .nwindows = 8,
482 .features = CPU_DEFAULT_FEATURES,
485 .name = "TI SuperSparc 61",
486 .iu_version = 0x44000000, /* SuperSPARC 3.x */
487 .fpu_version = 0 << 17,
488 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
489 .mmu_bm = 0x00002000,
490 .mmu_ctpr_mask = 0xffffffc0,
491 .mmu_cxr_mask = 0x0000ffff,
492 .mmu_sfsr_mask = 0xffffffff,
493 .mmu_trcr_mask = 0xffffffff,
494 .mxcc_version = 0x00000104,
495 .nwindows = 8,
496 .features = CPU_DEFAULT_FEATURES,
499 .name = "TI SuperSparc II",
500 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
501 .fpu_version = 0 << 17,
502 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
503 .mmu_bm = 0x00002000,
504 .mmu_ctpr_mask = 0xffffffc0,
505 .mmu_cxr_mask = 0x0000ffff,
506 .mmu_sfsr_mask = 0xffffffff,
507 .mmu_trcr_mask = 0xffffffff,
508 .mxcc_version = 0x00000104,
509 .nwindows = 8,
510 .features = CPU_DEFAULT_FEATURES,
513 .name = "LEON2",
514 .iu_version = 0xf2000000,
515 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
516 .mmu_version = 0xf2000000,
517 .mmu_bm = 0x00004000,
518 .mmu_ctpr_mask = 0x007ffff0,
519 .mmu_cxr_mask = 0x0000003f,
520 .mmu_sfsr_mask = 0xffffffff,
521 .mmu_trcr_mask = 0xffffffff,
522 .nwindows = 8,
523 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
526 .name = "LEON3",
527 .iu_version = 0xf3000000,
528 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
529 .mmu_version = 0xf3000000,
530 .mmu_bm = 0x00000000,
531 .mmu_ctpr_mask = 0xfffffffc,
532 .mmu_cxr_mask = 0x000000ff,
533 .mmu_sfsr_mask = 0xffffffff,
534 .mmu_trcr_mask = 0xffffffff,
535 .nwindows = 8,
536 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
537 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
538 CPU_FEATURE_CASA,
540 #endif
543 static const char * const feature_name[] = {
544 "float",
545 "float128",
546 "swap",
547 "mul",
548 "div",
549 "flush",
550 "fsqrt",
551 "fmul",
552 "vis1",
553 "vis2",
554 "fsmuld",
555 "hypv",
556 "cmt",
557 "gl",
560 static void print_features(uint32_t features, const char *prefix)
562 unsigned int i;
564 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
565 if (feature_name[i] && (features & (1 << i))) {
566 if (prefix) {
567 qemu_printf("%s", prefix);
569 qemu_printf("%s ", feature_name[i]);
574 void sparc_cpu_list(void)
576 unsigned int i;
578 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
579 qemu_printf("Sparc %16s IU " TARGET_FMT_lx
580 " FPU %08x MMU %08x NWINS %d ",
581 sparc_defs[i].name,
582 sparc_defs[i].iu_version,
583 sparc_defs[i].fpu_version,
584 sparc_defs[i].mmu_version,
585 sparc_defs[i].nwindows);
586 print_features(CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-");
587 print_features(~CPU_DEFAULT_FEATURES & sparc_defs[i].features, "+");
588 qemu_printf("\n");
590 qemu_printf("Default CPU feature flags (use '-' to remove): ");
591 print_features(CPU_DEFAULT_FEATURES, NULL);
592 qemu_printf("\n");
593 qemu_printf("Available CPU feature flags (use '+' to add): ");
594 print_features(~CPU_DEFAULT_FEATURES, NULL);
595 qemu_printf("\n");
596 qemu_printf("Numerical features (use '=' to set): iu_version "
597 "fpu_version mmu_version nwindows\n");
600 static void cpu_print_cc(FILE *f, uint32_t cc)
602 qemu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
603 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
604 cc & PSR_CARRY ? 'C' : '-');
607 #ifdef TARGET_SPARC64
608 #define REGS_PER_LINE 4
609 #else
610 #define REGS_PER_LINE 8
611 #endif
613 void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
615 SPARCCPU *cpu = SPARC_CPU(cs);
616 CPUSPARCState *env = &cpu->env;
617 int i, x;
619 qemu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
620 env->npc);
622 for (i = 0; i < 8; i++) {
623 if (i % REGS_PER_LINE == 0) {
624 qemu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
626 qemu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
627 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
628 qemu_fprintf(f, "\n");
631 for (x = 0; x < 3; x++) {
632 for (i = 0; i < 8; i++) {
633 if (i % REGS_PER_LINE == 0) {
634 qemu_fprintf(f, "%%%c%d-%d: ",
635 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
636 i, i + REGS_PER_LINE - 1);
638 qemu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
639 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
640 qemu_fprintf(f, "\n");
645 if (flags & CPU_DUMP_FPU) {
646 for (i = 0; i < TARGET_DPREGS; i++) {
647 if ((i & 3) == 0) {
648 qemu_fprintf(f, "%%f%02d: ", i * 2);
650 qemu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
651 if ((i & 3) == 3) {
652 qemu_fprintf(f, "\n");
657 #ifdef TARGET_SPARC64
658 qemu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
659 (unsigned)cpu_get_ccr(env));
660 cpu_print_cc(f, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
661 qemu_fprintf(f, " xcc: ");
662 cpu_print_cc(f, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
663 qemu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
664 env->psrpil, env->gl);
665 qemu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
666 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
667 qemu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
668 "cleanwin: %d cwp: %d\n",
669 env->cansave, env->canrestore, env->otherwin, env->wstate,
670 env->cleanwin, env->nwindows - 1 - env->cwp);
671 qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
672 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
674 #else
675 qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
676 cpu_print_cc(f, cpu_get_psr(env));
677 qemu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
678 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
679 env->wim);
680 qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
681 env->fsr, env->y);
682 #endif
683 qemu_fprintf(f, "\n");
686 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
688 SPARCCPU *cpu = SPARC_CPU(cs);
690 cpu->env.pc = value;
691 cpu->env.npc = value + 4;
694 static void sparc_cpu_synchronize_from_tb(CPUState *cs,
695 const TranslationBlock *tb)
697 SPARCCPU *cpu = SPARC_CPU(cs);
699 cpu->env.pc = tb->pc;
700 cpu->env.npc = tb->cs_base;
703 static bool sparc_cpu_has_work(CPUState *cs)
705 SPARCCPU *cpu = SPARC_CPU(cs);
706 CPUSPARCState *env = &cpu->env;
708 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
709 cpu_interrupts_enabled(env);
712 static char *sparc_cpu_type_name(const char *cpu_model)
714 char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
715 char *s = name;
717 /* SPARC cpu model names happen to have whitespaces,
718 * as type names shouldn't have spaces replace them with '-'
720 while ((s = strchr(s, ' '))) {
721 *s = '-';
724 return name;
727 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
729 ObjectClass *oc;
730 char *typename;
732 typename = sparc_cpu_type_name(cpu_model);
733 oc = object_class_by_name(typename);
734 g_free(typename);
735 return oc;
738 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
740 CPUState *cs = CPU(dev);
741 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
742 Error *local_err = NULL;
743 SPARCCPU *cpu = SPARC_CPU(dev);
744 CPUSPARCState *env = &cpu->env;
746 #if defined(CONFIG_USER_ONLY)
747 if ((env->def.features & CPU_FEATURE_FLOAT)) {
748 env->def.features |= CPU_FEATURE_FLOAT128;
750 #endif
752 env->version = env->def.iu_version;
753 env->fsr = env->def.fpu_version;
754 env->nwindows = env->def.nwindows;
755 #if !defined(TARGET_SPARC64)
756 env->mmuregs[0] |= env->def.mmu_version;
757 cpu_sparc_set_id(env, 0);
758 env->mxccregs[7] |= env->def.mxcc_version;
759 #else
760 env->mmu_version = env->def.mmu_version;
761 env->maxtl = env->def.maxtl;
762 env->version |= env->def.maxtl << 8;
763 env->version |= env->def.nwindows - 1;
764 #endif
766 cpu_exec_realizefn(cs, &local_err);
767 if (local_err != NULL) {
768 error_propagate(errp, local_err);
769 return;
772 qemu_init_vcpu(cs);
774 scc->parent_realize(dev, errp);
777 static void sparc_cpu_initfn(Object *obj)
779 SPARCCPU *cpu = SPARC_CPU(obj);
780 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
781 CPUSPARCState *env = &cpu->env;
783 cpu_set_cpustate_pointers(cpu);
785 if (scc->cpu_def) {
786 env->def = *scc->cpu_def;
790 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
791 void *opaque, Error **errp)
793 SPARCCPU *cpu = SPARC_CPU(obj);
794 int64_t value = cpu->env.def.nwindows;
796 visit_type_int(v, name, &value, errp);
799 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
800 void *opaque, Error **errp)
802 const int64_t min = MIN_NWINDOWS;
803 const int64_t max = MAX_NWINDOWS;
804 SPARCCPU *cpu = SPARC_CPU(obj);
805 int64_t value;
807 if (!visit_type_int(v, name, &value, errp)) {
808 return;
811 if (value < min || value > max) {
812 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
813 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
814 object_get_typename(obj), name ? name : "null",
815 value, min, max);
816 return;
818 cpu->env.def.nwindows = value;
821 static PropertyInfo qdev_prop_nwindows = {
822 .name = "int",
823 .get = sparc_get_nwindows,
824 .set = sparc_set_nwindows,
827 static Property sparc_cpu_properties[] = {
828 DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false),
829 DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
830 DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false),
831 DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false),
832 DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false),
833 DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false),
834 DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false),
835 DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false),
836 DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false),
837 DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false),
838 DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false),
839 DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false),
840 DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false),
841 DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false),
842 DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
843 qdev_prop_uint64, target_ulong),
844 DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
845 DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
846 DEFINE_PROP("nwindows", SPARCCPU, env.def.nwindows,
847 qdev_prop_nwindows, uint32_t),
848 DEFINE_PROP_END_OF_LIST()
851 #ifdef CONFIG_TCG
852 #include "hw/core/tcg-cpu-ops.h"
854 static struct TCGCPUOps sparc_tcg_ops = {
855 .initialize = sparc_tcg_init,
856 .synchronize_from_tb = sparc_cpu_synchronize_from_tb,
857 .cpu_exec_interrupt = sparc_cpu_exec_interrupt,
858 .tlb_fill = sparc_cpu_tlb_fill,
860 #ifndef CONFIG_USER_ONLY
861 .do_interrupt = sparc_cpu_do_interrupt,
862 .do_transaction_failed = sparc_cpu_do_transaction_failed,
863 .do_unaligned_access = sparc_cpu_do_unaligned_access,
864 #endif /* !CONFIG_USER_ONLY */
866 #endif /* CONFIG_TCG */
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 device_class_set_parent_realize(dc, sparc_cpu_realizefn,
875 &scc->parent_realize);
876 device_class_set_props(dc, sparc_cpu_properties);
878 device_class_set_parent_reset(dc, sparc_cpu_reset, &scc->parent_reset);
880 cc->class_by_name = sparc_cpu_class_by_name;
881 cc->parse_features = sparc_cpu_parse_features;
882 cc->has_work = sparc_cpu_has_work;
883 cc->dump_state = sparc_cpu_dump_state;
884 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
885 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
886 #endif
887 cc->set_pc = sparc_cpu_set_pc;
888 cc->gdb_read_register = sparc_cpu_gdb_read_register;
889 cc->gdb_write_register = sparc_cpu_gdb_write_register;
890 #ifndef CONFIG_USER_ONLY
891 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
892 cc->vmsd = &vmstate_sparc_cpu;
893 #endif
894 cc->disas_set_info = cpu_sparc_disas_set_info;
896 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
897 cc->gdb_num_core_regs = 86;
898 #else
899 cc->gdb_num_core_regs = 72;
900 #endif
901 cc->tcg_ops = &sparc_tcg_ops;
904 static const TypeInfo sparc_cpu_type_info = {
905 .name = TYPE_SPARC_CPU,
906 .parent = TYPE_CPU,
907 .instance_size = sizeof(SPARCCPU),
908 .instance_init = sparc_cpu_initfn,
909 .abstract = true,
910 .class_size = sizeof(SPARCCPUClass),
911 .class_init = sparc_cpu_class_init,
914 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
916 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
917 scc->cpu_def = data;
920 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
922 char *typename = sparc_cpu_type_name(def->name);
923 TypeInfo ti = {
924 .name = typename,
925 .parent = TYPE_SPARC_CPU,
926 .class_init = sparc_cpu_cpudef_class_init,
927 .class_data = (void *)def,
930 type_register(&ti);
931 g_free(typename);
934 static void sparc_cpu_register_types(void)
936 int i;
938 type_register_static(&sparc_cpu_type_info);
939 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
940 sparc_register_cpudef_type(&sparc_defs[i]);
944 type_init(sparc_cpu_register_types)