icount: Take iothread lock when running QEMU timers
[qemu/ar7.git] / target / sparc / cpu.c
blob55268ed2a19e133d2084442106d03c7a5bce41f3
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 #ifndef CONFIG_USER_ONLY
81 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
83 if (interrupt_request & CPU_INTERRUPT_HARD) {
84 SPARCCPU *cpu = SPARC_CPU(cs);
85 CPUSPARCState *env = &cpu->env;
87 if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
88 int pil = env->interrupt_index & 0xf;
89 int type = env->interrupt_index & 0xf0;
91 if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
92 cs->exception_index = env->interrupt_index;
93 sparc_cpu_do_interrupt(cs);
94 return true;
98 return false;
100 #endif /* !CONFIG_USER_ONLY */
102 static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
104 info->print_insn = print_insn_sparc;
105 #ifdef TARGET_SPARC64
106 info->mach = bfd_mach_sparc_v9b;
107 #endif
110 static void
111 cpu_add_feat_as_prop(const char *typename, const char *name, const char *val)
113 GlobalProperty *prop = g_new0(typeof(*prop), 1);
114 prop->driver = typename;
115 prop->property = g_strdup(name);
116 prop->value = g_strdup(val);
117 qdev_prop_register_global(prop);
120 /* Parse "+feature,-feature,feature=foo" CPU feature string */
121 static void sparc_cpu_parse_features(const char *typename, char *features,
122 Error **errp)
124 GList *l, *plus_features = NULL, *minus_features = NULL;
125 char *featurestr; /* Single 'key=value" string being parsed */
126 static bool cpu_globals_initialized;
128 if (cpu_globals_initialized) {
129 return;
131 cpu_globals_initialized = true;
133 if (!features) {
134 return;
137 for (featurestr = strtok(features, ",");
138 featurestr;
139 featurestr = strtok(NULL, ",")) {
140 const char *name;
141 const char *val = NULL;
142 char *eq = NULL;
144 /* Compatibility syntax: */
145 if (featurestr[0] == '+') {
146 plus_features = g_list_append(plus_features,
147 g_strdup(featurestr + 1));
148 continue;
149 } else if (featurestr[0] == '-') {
150 minus_features = g_list_append(minus_features,
151 g_strdup(featurestr + 1));
152 continue;
155 eq = strchr(featurestr, '=');
156 name = featurestr;
157 if (eq) {
158 *eq++ = 0;
159 val = eq;
162 * Temporarily, only +feat/-feat will be supported
163 * for boolean properties until we remove the
164 * minus-overrides-plus semantics and just follow
165 * the order options appear on the command-line.
167 * TODO: warn if user is relying on minus-override-plus semantics
168 * TODO: remove minus-override-plus semantics after
169 * warning for a few releases
171 if (!strcasecmp(val, "on") ||
172 !strcasecmp(val, "off") ||
173 !strcasecmp(val, "true") ||
174 !strcasecmp(val, "false")) {
175 error_setg(errp, "Boolean properties in format %s=%s"
176 " are not supported", name, val);
177 return;
179 } else {
180 error_setg(errp, "Unsupported property format: %s", name);
181 return;
183 cpu_add_feat_as_prop(typename, name, val);
186 for (l = plus_features; l; l = l->next) {
187 const char *name = l->data;
188 cpu_add_feat_as_prop(typename, name, "on");
190 g_list_free_full(plus_features, g_free);
192 for (l = minus_features; l; l = l->next) {
193 const char *name = l->data;
194 cpu_add_feat_as_prop(typename, name, "off");
196 g_list_free_full(minus_features, g_free);
199 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
201 #if !defined(TARGET_SPARC64)
202 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
203 #endif
206 static const sparc_def_t sparc_defs[] = {
207 #ifdef TARGET_SPARC64
209 .name = "Fujitsu Sparc64",
210 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
211 .fpu_version = 0x00000000,
212 .mmu_version = mmu_us_12,
213 .nwindows = 4,
214 .maxtl = 4,
215 .features = CPU_DEFAULT_FEATURES,
218 .name = "Fujitsu Sparc64 III",
219 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
220 .fpu_version = 0x00000000,
221 .mmu_version = mmu_us_12,
222 .nwindows = 5,
223 .maxtl = 4,
224 .features = CPU_DEFAULT_FEATURES,
227 .name = "Fujitsu Sparc64 IV",
228 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
229 .fpu_version = 0x00000000,
230 .mmu_version = mmu_us_12,
231 .nwindows = 8,
232 .maxtl = 5,
233 .features = CPU_DEFAULT_FEATURES,
236 .name = "Fujitsu Sparc64 V",
237 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
238 .fpu_version = 0x00000000,
239 .mmu_version = mmu_us_12,
240 .nwindows = 8,
241 .maxtl = 5,
242 .features = CPU_DEFAULT_FEATURES,
245 .name = "TI UltraSparc I",
246 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
247 .fpu_version = 0x00000000,
248 .mmu_version = mmu_us_12,
249 .nwindows = 8,
250 .maxtl = 5,
251 .features = CPU_DEFAULT_FEATURES,
254 .name = "TI UltraSparc II",
255 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
256 .fpu_version = 0x00000000,
257 .mmu_version = mmu_us_12,
258 .nwindows = 8,
259 .maxtl = 5,
260 .features = CPU_DEFAULT_FEATURES,
263 .name = "TI UltraSparc IIi",
264 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
265 .fpu_version = 0x00000000,
266 .mmu_version = mmu_us_12,
267 .nwindows = 8,
268 .maxtl = 5,
269 .features = CPU_DEFAULT_FEATURES,
272 .name = "TI UltraSparc IIe",
273 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
274 .fpu_version = 0x00000000,
275 .mmu_version = mmu_us_12,
276 .nwindows = 8,
277 .maxtl = 5,
278 .features = CPU_DEFAULT_FEATURES,
281 .name = "Sun UltraSparc III",
282 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
283 .fpu_version = 0x00000000,
284 .mmu_version = mmu_us_12,
285 .nwindows = 8,
286 .maxtl = 5,
287 .features = CPU_DEFAULT_FEATURES,
290 .name = "Sun UltraSparc III Cu",
291 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
292 .fpu_version = 0x00000000,
293 .mmu_version = mmu_us_3,
294 .nwindows = 8,
295 .maxtl = 5,
296 .features = CPU_DEFAULT_FEATURES,
299 .name = "Sun UltraSparc IIIi",
300 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
301 .fpu_version = 0x00000000,
302 .mmu_version = mmu_us_12,
303 .nwindows = 8,
304 .maxtl = 5,
305 .features = CPU_DEFAULT_FEATURES,
308 .name = "Sun UltraSparc IV",
309 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
310 .fpu_version = 0x00000000,
311 .mmu_version = mmu_us_4,
312 .nwindows = 8,
313 .maxtl = 5,
314 .features = CPU_DEFAULT_FEATURES,
317 .name = "Sun UltraSparc IV+",
318 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
319 .fpu_version = 0x00000000,
320 .mmu_version = mmu_us_12,
321 .nwindows = 8,
322 .maxtl = 5,
323 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
326 .name = "Sun UltraSparc IIIi+",
327 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
328 .fpu_version = 0x00000000,
329 .mmu_version = mmu_us_3,
330 .nwindows = 8,
331 .maxtl = 5,
332 .features = CPU_DEFAULT_FEATURES,
335 .name = "Sun UltraSparc T1",
336 /* defined in sparc_ifu_fdp.v and ctu.h */
337 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
338 .fpu_version = 0x00000000,
339 .mmu_version = mmu_sun4v,
340 .nwindows = 8,
341 .maxtl = 6,
342 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
343 | CPU_FEATURE_GL,
346 .name = "Sun UltraSparc T2",
347 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
348 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
349 .fpu_version = 0x00000000,
350 .mmu_version = mmu_sun4v,
351 .nwindows = 8,
352 .maxtl = 6,
353 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
354 | CPU_FEATURE_GL,
357 .name = "NEC UltraSparc I",
358 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
359 .fpu_version = 0x00000000,
360 .mmu_version = mmu_us_12,
361 .nwindows = 8,
362 .maxtl = 5,
363 .features = CPU_DEFAULT_FEATURES,
365 #else
367 .name = "Fujitsu MB86904",
368 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
369 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
370 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
371 .mmu_bm = 0x00004000,
372 .mmu_ctpr_mask = 0x00ffffc0,
373 .mmu_cxr_mask = 0x000000ff,
374 .mmu_sfsr_mask = 0x00016fff,
375 .mmu_trcr_mask = 0x00ffffff,
376 .nwindows = 8,
377 .features = CPU_DEFAULT_FEATURES,
380 .name = "Fujitsu MB86907",
381 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
382 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
383 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
384 .mmu_bm = 0x00004000,
385 .mmu_ctpr_mask = 0xffffffc0,
386 .mmu_cxr_mask = 0x000000ff,
387 .mmu_sfsr_mask = 0x00016fff,
388 .mmu_trcr_mask = 0xffffffff,
389 .nwindows = 8,
390 .features = CPU_DEFAULT_FEATURES,
393 .name = "TI MicroSparc I",
394 .iu_version = 0x41000000,
395 .fpu_version = 4 << 17,
396 .mmu_version = 0x41000000,
397 .mmu_bm = 0x00004000,
398 .mmu_ctpr_mask = 0x007ffff0,
399 .mmu_cxr_mask = 0x0000003f,
400 .mmu_sfsr_mask = 0x00016fff,
401 .mmu_trcr_mask = 0x0000003f,
402 .nwindows = 7,
403 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
404 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
405 CPU_FEATURE_FMUL,
408 .name = "TI MicroSparc II",
409 .iu_version = 0x42000000,
410 .fpu_version = 4 << 17,
411 .mmu_version = 0x02000000,
412 .mmu_bm = 0x00004000,
413 .mmu_ctpr_mask = 0x00ffffc0,
414 .mmu_cxr_mask = 0x000000ff,
415 .mmu_sfsr_mask = 0x00016fff,
416 .mmu_trcr_mask = 0x00ffffff,
417 .nwindows = 8,
418 .features = CPU_DEFAULT_FEATURES,
421 .name = "TI MicroSparc IIep",
422 .iu_version = 0x42000000,
423 .fpu_version = 4 << 17,
424 .mmu_version = 0x04000000,
425 .mmu_bm = 0x00004000,
426 .mmu_ctpr_mask = 0x00ffffc0,
427 .mmu_cxr_mask = 0x000000ff,
428 .mmu_sfsr_mask = 0x00016bff,
429 .mmu_trcr_mask = 0x00ffffff,
430 .nwindows = 8,
431 .features = CPU_DEFAULT_FEATURES,
434 .name = "TI SuperSparc 40", /* STP1020NPGA */
435 .iu_version = 0x41000000, /* SuperSPARC 2.x */
436 .fpu_version = 0 << 17,
437 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
438 .mmu_bm = 0x00002000,
439 .mmu_ctpr_mask = 0xffffffc0,
440 .mmu_cxr_mask = 0x0000ffff,
441 .mmu_sfsr_mask = 0xffffffff,
442 .mmu_trcr_mask = 0xffffffff,
443 .nwindows = 8,
444 .features = CPU_DEFAULT_FEATURES,
447 .name = "TI SuperSparc 50", /* STP1020PGA */
448 .iu_version = 0x40000000, /* SuperSPARC 3.x */
449 .fpu_version = 0 << 17,
450 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
451 .mmu_bm = 0x00002000,
452 .mmu_ctpr_mask = 0xffffffc0,
453 .mmu_cxr_mask = 0x0000ffff,
454 .mmu_sfsr_mask = 0xffffffff,
455 .mmu_trcr_mask = 0xffffffff,
456 .nwindows = 8,
457 .features = CPU_DEFAULT_FEATURES,
460 .name = "TI SuperSparc 51",
461 .iu_version = 0x40000000, /* SuperSPARC 3.x */
462 .fpu_version = 0 << 17,
463 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
464 .mmu_bm = 0x00002000,
465 .mmu_ctpr_mask = 0xffffffc0,
466 .mmu_cxr_mask = 0x0000ffff,
467 .mmu_sfsr_mask = 0xffffffff,
468 .mmu_trcr_mask = 0xffffffff,
469 .mxcc_version = 0x00000104,
470 .nwindows = 8,
471 .features = CPU_DEFAULT_FEATURES,
474 .name = "TI SuperSparc 60", /* STP1020APGA */
475 .iu_version = 0x40000000, /* SuperSPARC 3.x */
476 .fpu_version = 0 << 17,
477 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
478 .mmu_bm = 0x00002000,
479 .mmu_ctpr_mask = 0xffffffc0,
480 .mmu_cxr_mask = 0x0000ffff,
481 .mmu_sfsr_mask = 0xffffffff,
482 .mmu_trcr_mask = 0xffffffff,
483 .nwindows = 8,
484 .features = CPU_DEFAULT_FEATURES,
487 .name = "TI SuperSparc 61",
488 .iu_version = 0x44000000, /* SuperSPARC 3.x */
489 .fpu_version = 0 << 17,
490 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
491 .mmu_bm = 0x00002000,
492 .mmu_ctpr_mask = 0xffffffc0,
493 .mmu_cxr_mask = 0x0000ffff,
494 .mmu_sfsr_mask = 0xffffffff,
495 .mmu_trcr_mask = 0xffffffff,
496 .mxcc_version = 0x00000104,
497 .nwindows = 8,
498 .features = CPU_DEFAULT_FEATURES,
501 .name = "TI SuperSparc II",
502 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
503 .fpu_version = 0 << 17,
504 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
505 .mmu_bm = 0x00002000,
506 .mmu_ctpr_mask = 0xffffffc0,
507 .mmu_cxr_mask = 0x0000ffff,
508 .mmu_sfsr_mask = 0xffffffff,
509 .mmu_trcr_mask = 0xffffffff,
510 .mxcc_version = 0x00000104,
511 .nwindows = 8,
512 .features = CPU_DEFAULT_FEATURES,
515 .name = "LEON2",
516 .iu_version = 0xf2000000,
517 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
518 .mmu_version = 0xf2000000,
519 .mmu_bm = 0x00004000,
520 .mmu_ctpr_mask = 0x007ffff0,
521 .mmu_cxr_mask = 0x0000003f,
522 .mmu_sfsr_mask = 0xffffffff,
523 .mmu_trcr_mask = 0xffffffff,
524 .nwindows = 8,
525 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
528 .name = "LEON3",
529 .iu_version = 0xf3000000,
530 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
531 .mmu_version = 0xf3000000,
532 .mmu_bm = 0x00000000,
533 .mmu_ctpr_mask = 0xfffffffc,
534 .mmu_cxr_mask = 0x000000ff,
535 .mmu_sfsr_mask = 0xffffffff,
536 .mmu_trcr_mask = 0xffffffff,
537 .nwindows = 8,
538 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
539 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
540 CPU_FEATURE_CASA,
542 #endif
545 static const char * const feature_name[] = {
546 "float",
547 "float128",
548 "swap",
549 "mul",
550 "div",
551 "flush",
552 "fsqrt",
553 "fmul",
554 "vis1",
555 "vis2",
556 "fsmuld",
557 "hypv",
558 "cmt",
559 "gl",
562 static void print_features(uint32_t features, const char *prefix)
564 unsigned int i;
566 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
567 if (feature_name[i] && (features & (1 << i))) {
568 if (prefix) {
569 qemu_printf("%s", prefix);
571 qemu_printf("%s ", feature_name[i]);
576 void sparc_cpu_list(void)
578 unsigned int i;
580 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
581 qemu_printf("Sparc %16s IU " TARGET_FMT_lx
582 " FPU %08x MMU %08x NWINS %d ",
583 sparc_defs[i].name,
584 sparc_defs[i].iu_version,
585 sparc_defs[i].fpu_version,
586 sparc_defs[i].mmu_version,
587 sparc_defs[i].nwindows);
588 print_features(CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-");
589 print_features(~CPU_DEFAULT_FEATURES & sparc_defs[i].features, "+");
590 qemu_printf("\n");
592 qemu_printf("Default CPU feature flags (use '-' to remove): ");
593 print_features(CPU_DEFAULT_FEATURES, NULL);
594 qemu_printf("\n");
595 qemu_printf("Available CPU feature flags (use '+' to add): ");
596 print_features(~CPU_DEFAULT_FEATURES, NULL);
597 qemu_printf("\n");
598 qemu_printf("Numerical features (use '=' to set): iu_version "
599 "fpu_version mmu_version nwindows\n");
602 static void cpu_print_cc(FILE *f, uint32_t cc)
604 qemu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
605 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
606 cc & PSR_CARRY ? 'C' : '-');
609 #ifdef TARGET_SPARC64
610 #define REGS_PER_LINE 4
611 #else
612 #define REGS_PER_LINE 8
613 #endif
615 static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
617 SPARCCPU *cpu = SPARC_CPU(cs);
618 CPUSPARCState *env = &cpu->env;
619 int i, x;
621 qemu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
622 env->npc);
624 for (i = 0; i < 8; i++) {
625 if (i % REGS_PER_LINE == 0) {
626 qemu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
628 qemu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
629 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
630 qemu_fprintf(f, "\n");
633 for (x = 0; x < 3; x++) {
634 for (i = 0; i < 8; i++) {
635 if (i % REGS_PER_LINE == 0) {
636 qemu_fprintf(f, "%%%c%d-%d: ",
637 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
638 i, i + REGS_PER_LINE - 1);
640 qemu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
641 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
642 qemu_fprintf(f, "\n");
647 if (flags & CPU_DUMP_FPU) {
648 for (i = 0; i < TARGET_DPREGS; i++) {
649 if ((i & 3) == 0) {
650 qemu_fprintf(f, "%%f%02d: ", i * 2);
652 qemu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
653 if ((i & 3) == 3) {
654 qemu_fprintf(f, "\n");
659 #ifdef TARGET_SPARC64
660 qemu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
661 (unsigned)cpu_get_ccr(env));
662 cpu_print_cc(f, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
663 qemu_fprintf(f, " xcc: ");
664 cpu_print_cc(f, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
665 qemu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
666 env->psrpil, env->gl);
667 qemu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
668 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
669 qemu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
670 "cleanwin: %d cwp: %d\n",
671 env->cansave, env->canrestore, env->otherwin, env->wstate,
672 env->cleanwin, env->nwindows - 1 - env->cwp);
673 qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
674 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
676 #else
677 qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
678 cpu_print_cc(f, cpu_get_psr(env));
679 qemu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
680 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
681 env->wim);
682 qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
683 env->fsr, env->y);
684 #endif
685 qemu_fprintf(f, "\n");
688 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
690 SPARCCPU *cpu = SPARC_CPU(cs);
692 cpu->env.pc = value;
693 cpu->env.npc = value + 4;
696 static void sparc_cpu_synchronize_from_tb(CPUState *cs,
697 const TranslationBlock *tb)
699 SPARCCPU *cpu = SPARC_CPU(cs);
701 cpu->env.pc = tb->pc;
702 cpu->env.npc = tb->cs_base;
705 static bool sparc_cpu_has_work(CPUState *cs)
707 SPARCCPU *cpu = SPARC_CPU(cs);
708 CPUSPARCState *env = &cpu->env;
710 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
711 cpu_interrupts_enabled(env);
714 static char *sparc_cpu_type_name(const char *cpu_model)
716 char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
717 char *s = name;
719 /* SPARC cpu model names happen to have whitespaces,
720 * as type names shouldn't have spaces replace them with '-'
722 while ((s = strchr(s, ' '))) {
723 *s = '-';
726 return name;
729 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
731 ObjectClass *oc;
732 char *typename;
734 typename = sparc_cpu_type_name(cpu_model);
735 oc = object_class_by_name(typename);
736 g_free(typename);
737 return oc;
740 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
742 CPUState *cs = CPU(dev);
743 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
744 Error *local_err = NULL;
745 SPARCCPU *cpu = SPARC_CPU(dev);
746 CPUSPARCState *env = &cpu->env;
748 #if defined(CONFIG_USER_ONLY)
749 if ((env->def.features & CPU_FEATURE_FLOAT)) {
750 env->def.features |= CPU_FEATURE_FLOAT128;
752 #endif
754 env->version = env->def.iu_version;
755 env->fsr = env->def.fpu_version;
756 env->nwindows = env->def.nwindows;
757 #if !defined(TARGET_SPARC64)
758 env->mmuregs[0] |= env->def.mmu_version;
759 cpu_sparc_set_id(env, 0);
760 env->mxccregs[7] |= env->def.mxcc_version;
761 #else
762 env->mmu_version = env->def.mmu_version;
763 env->maxtl = env->def.maxtl;
764 env->version |= env->def.maxtl << 8;
765 env->version |= env->def.nwindows - 1;
766 #endif
768 cpu_exec_realizefn(cs, &local_err);
769 if (local_err != NULL) {
770 error_propagate(errp, local_err);
771 return;
774 qemu_init_vcpu(cs);
776 scc->parent_realize(dev, errp);
779 static void sparc_cpu_initfn(Object *obj)
781 SPARCCPU *cpu = SPARC_CPU(obj);
782 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
783 CPUSPARCState *env = &cpu->env;
785 cpu_set_cpustate_pointers(cpu);
787 if (scc->cpu_def) {
788 env->def = *scc->cpu_def;
792 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
793 void *opaque, Error **errp)
795 SPARCCPU *cpu = SPARC_CPU(obj);
796 int64_t value = cpu->env.def.nwindows;
798 visit_type_int(v, name, &value, errp);
801 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
802 void *opaque, Error **errp)
804 const int64_t min = MIN_NWINDOWS;
805 const int64_t max = MAX_NWINDOWS;
806 SPARCCPU *cpu = SPARC_CPU(obj);
807 int64_t value;
809 if (!visit_type_int(v, name, &value, errp)) {
810 return;
813 if (value < min || value > max) {
814 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
815 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
816 object_get_typename(obj), name ? name : "null",
817 value, min, max);
818 return;
820 cpu->env.def.nwindows = value;
823 static PropertyInfo qdev_prop_nwindows = {
824 .name = "int",
825 .get = sparc_get_nwindows,
826 .set = sparc_set_nwindows,
829 static Property sparc_cpu_properties[] = {
830 DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false),
831 DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
832 DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false),
833 DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false),
834 DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false),
835 DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false),
836 DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false),
837 DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false),
838 DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false),
839 DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false),
840 DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false),
841 DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false),
842 DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false),
843 DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false),
844 DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
845 qdev_prop_uint64, target_ulong),
846 DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
847 DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
848 DEFINE_PROP("nwindows", SPARCCPU, env.def.nwindows,
849 qdev_prop_nwindows, uint32_t),
850 DEFINE_PROP_END_OF_LIST()
853 #ifndef CONFIG_USER_ONLY
854 #include "hw/core/sysemu-cpu-ops.h"
856 static const struct SysemuCPUOps sparc_sysemu_ops = {
857 .get_phys_page_debug = sparc_cpu_get_phys_page_debug,
858 .legacy_vmsd = &vmstate_sparc_cpu,
860 #endif
862 #ifdef CONFIG_TCG
863 #include "hw/core/tcg-cpu-ops.h"
865 static const struct TCGCPUOps sparc_tcg_ops = {
866 .initialize = sparc_tcg_init,
867 .synchronize_from_tb = sparc_cpu_synchronize_from_tb,
869 #ifndef CONFIG_USER_ONLY
870 .tlb_fill = sparc_cpu_tlb_fill,
871 .cpu_exec_interrupt = sparc_cpu_exec_interrupt,
872 .do_interrupt = sparc_cpu_do_interrupt,
873 .do_transaction_failed = sparc_cpu_do_transaction_failed,
874 .do_unaligned_access = sparc_cpu_do_unaligned_access,
875 #endif /* !CONFIG_USER_ONLY */
877 #endif /* CONFIG_TCG */
879 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
881 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
882 CPUClass *cc = CPU_CLASS(oc);
883 DeviceClass *dc = DEVICE_CLASS(oc);
885 device_class_set_parent_realize(dc, sparc_cpu_realizefn,
886 &scc->parent_realize);
887 device_class_set_props(dc, sparc_cpu_properties);
889 device_class_set_parent_reset(dc, sparc_cpu_reset, &scc->parent_reset);
891 cc->class_by_name = sparc_cpu_class_by_name;
892 cc->parse_features = sparc_cpu_parse_features;
893 cc->has_work = sparc_cpu_has_work;
894 cc->dump_state = sparc_cpu_dump_state;
895 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
896 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
897 #endif
898 cc->set_pc = sparc_cpu_set_pc;
899 cc->gdb_read_register = sparc_cpu_gdb_read_register;
900 cc->gdb_write_register = sparc_cpu_gdb_write_register;
901 #ifndef CONFIG_USER_ONLY
902 cc->sysemu_ops = &sparc_sysemu_ops;
903 #endif
904 cc->disas_set_info = cpu_sparc_disas_set_info;
906 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
907 cc->gdb_num_core_regs = 86;
908 #else
909 cc->gdb_num_core_regs = 72;
910 #endif
911 cc->tcg_ops = &sparc_tcg_ops;
914 static const TypeInfo sparc_cpu_type_info = {
915 .name = TYPE_SPARC_CPU,
916 .parent = TYPE_CPU,
917 .instance_size = sizeof(SPARCCPU),
918 .instance_init = sparc_cpu_initfn,
919 .abstract = true,
920 .class_size = sizeof(SPARCCPUClass),
921 .class_init = sparc_cpu_class_init,
924 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
926 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
927 scc->cpu_def = data;
930 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
932 char *typename = sparc_cpu_type_name(def->name);
933 TypeInfo ti = {
934 .name = typename,
935 .parent = TYPE_SPARC_CPU,
936 .class_init = sparc_cpu_cpudef_class_init,
937 .class_data = (void *)def,
940 type_register(&ti);
941 g_free(typename);
944 static void sparc_cpu_register_types(void)
946 int i;
948 type_register_static(&sparc_cpu_type_info);
949 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
950 sparc_register_cpudef_type(&sparc_defs[i]);
954 type_init(sparc_cpu_register_types)