MAINTAINERS: Add an entry for the Parallel NOR Flash devices
[qemu/ar7.git] / target / sparc / cpu.c
blob4654c2a6a07707e340f6f1233d43c69720051687
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/qemu-print.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 qdev_prop_register_global(prop);
117 /* Parse "+feature,-feature,feature=foo" CPU feature string */
118 static void sparc_cpu_parse_features(const char *typename, char *features,
119 Error **errp)
121 GList *l, *plus_features = NULL, *minus_features = NULL;
122 char *featurestr; /* Single 'key=value" string being parsed */
123 static bool cpu_globals_initialized;
125 if (cpu_globals_initialized) {
126 return;
128 cpu_globals_initialized = true;
130 if (!features) {
131 return;
134 for (featurestr = strtok(features, ",");
135 featurestr;
136 featurestr = strtok(NULL, ",")) {
137 const char *name;
138 const char *val = NULL;
139 char *eq = NULL;
141 /* Compatibility syntax: */
142 if (featurestr[0] == '+') {
143 plus_features = g_list_append(plus_features,
144 g_strdup(featurestr + 1));
145 continue;
146 } else if (featurestr[0] == '-') {
147 minus_features = g_list_append(minus_features,
148 g_strdup(featurestr + 1));
149 continue;
152 eq = strchr(featurestr, '=');
153 name = featurestr;
154 if (eq) {
155 *eq++ = 0;
156 val = eq;
159 * Temporarily, only +feat/-feat will be supported
160 * for boolean properties until we remove the
161 * minus-overrides-plus semantics and just follow
162 * the order options appear on the command-line.
164 * TODO: warn if user is relying on minus-override-plus semantics
165 * TODO: remove minus-override-plus semantics after
166 * warning for a few releases
168 if (!strcasecmp(val, "on") ||
169 !strcasecmp(val, "off") ||
170 !strcasecmp(val, "true") ||
171 !strcasecmp(val, "false")) {
172 error_setg(errp, "Boolean properties in format %s=%s"
173 " are not supported", name, val);
174 return;
176 } else {
177 error_setg(errp, "Unsupported property format: %s", name);
178 return;
180 cpu_add_feat_as_prop(typename, name, val);
183 for (l = plus_features; l; l = l->next) {
184 const char *name = l->data;
185 cpu_add_feat_as_prop(typename, name, "on");
187 g_list_free_full(plus_features, g_free);
189 for (l = minus_features; l; l = l->next) {
190 const char *name = l->data;
191 cpu_add_feat_as_prop(typename, name, "off");
193 g_list_free_full(minus_features, g_free);
196 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
198 #if !defined(TARGET_SPARC64)
199 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
200 #endif
203 static const sparc_def_t sparc_defs[] = {
204 #ifdef TARGET_SPARC64
206 .name = "Fujitsu Sparc64",
207 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
208 .fpu_version = 0x00000000,
209 .mmu_version = mmu_us_12,
210 .nwindows = 4,
211 .maxtl = 4,
212 .features = CPU_DEFAULT_FEATURES,
215 .name = "Fujitsu Sparc64 III",
216 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
217 .fpu_version = 0x00000000,
218 .mmu_version = mmu_us_12,
219 .nwindows = 5,
220 .maxtl = 4,
221 .features = CPU_DEFAULT_FEATURES,
224 .name = "Fujitsu Sparc64 IV",
225 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
226 .fpu_version = 0x00000000,
227 .mmu_version = mmu_us_12,
228 .nwindows = 8,
229 .maxtl = 5,
230 .features = CPU_DEFAULT_FEATURES,
233 .name = "Fujitsu Sparc64 V",
234 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
235 .fpu_version = 0x00000000,
236 .mmu_version = mmu_us_12,
237 .nwindows = 8,
238 .maxtl = 5,
239 .features = CPU_DEFAULT_FEATURES,
242 .name = "TI UltraSparc I",
243 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
244 .fpu_version = 0x00000000,
245 .mmu_version = mmu_us_12,
246 .nwindows = 8,
247 .maxtl = 5,
248 .features = CPU_DEFAULT_FEATURES,
251 .name = "TI UltraSparc II",
252 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
253 .fpu_version = 0x00000000,
254 .mmu_version = mmu_us_12,
255 .nwindows = 8,
256 .maxtl = 5,
257 .features = CPU_DEFAULT_FEATURES,
260 .name = "TI UltraSparc IIi",
261 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
262 .fpu_version = 0x00000000,
263 .mmu_version = mmu_us_12,
264 .nwindows = 8,
265 .maxtl = 5,
266 .features = CPU_DEFAULT_FEATURES,
269 .name = "TI UltraSparc IIe",
270 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
271 .fpu_version = 0x00000000,
272 .mmu_version = mmu_us_12,
273 .nwindows = 8,
274 .maxtl = 5,
275 .features = CPU_DEFAULT_FEATURES,
278 .name = "Sun UltraSparc III",
279 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
280 .fpu_version = 0x00000000,
281 .mmu_version = mmu_us_12,
282 .nwindows = 8,
283 .maxtl = 5,
284 .features = CPU_DEFAULT_FEATURES,
287 .name = "Sun UltraSparc III Cu",
288 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
289 .fpu_version = 0x00000000,
290 .mmu_version = mmu_us_3,
291 .nwindows = 8,
292 .maxtl = 5,
293 .features = CPU_DEFAULT_FEATURES,
296 .name = "Sun UltraSparc IIIi",
297 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
298 .fpu_version = 0x00000000,
299 .mmu_version = mmu_us_12,
300 .nwindows = 8,
301 .maxtl = 5,
302 .features = CPU_DEFAULT_FEATURES,
305 .name = "Sun UltraSparc IV",
306 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
307 .fpu_version = 0x00000000,
308 .mmu_version = mmu_us_4,
309 .nwindows = 8,
310 .maxtl = 5,
311 .features = CPU_DEFAULT_FEATURES,
314 .name = "Sun UltraSparc IV+",
315 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
316 .fpu_version = 0x00000000,
317 .mmu_version = mmu_us_12,
318 .nwindows = 8,
319 .maxtl = 5,
320 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
323 .name = "Sun UltraSparc IIIi+",
324 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
325 .fpu_version = 0x00000000,
326 .mmu_version = mmu_us_3,
327 .nwindows = 8,
328 .maxtl = 5,
329 .features = CPU_DEFAULT_FEATURES,
332 .name = "Sun UltraSparc T1",
333 /* defined in sparc_ifu_fdp.v and ctu.h */
334 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
335 .fpu_version = 0x00000000,
336 .mmu_version = mmu_sun4v,
337 .nwindows = 8,
338 .maxtl = 6,
339 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
340 | CPU_FEATURE_GL,
343 .name = "Sun UltraSparc T2",
344 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
345 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
346 .fpu_version = 0x00000000,
347 .mmu_version = mmu_sun4v,
348 .nwindows = 8,
349 .maxtl = 6,
350 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
351 | CPU_FEATURE_GL,
354 .name = "NEC UltraSparc I",
355 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
356 .fpu_version = 0x00000000,
357 .mmu_version = mmu_us_12,
358 .nwindows = 8,
359 .maxtl = 5,
360 .features = CPU_DEFAULT_FEATURES,
362 #else
364 .name = "Fujitsu MB86904",
365 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
366 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
367 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
368 .mmu_bm = 0x00004000,
369 .mmu_ctpr_mask = 0x00ffffc0,
370 .mmu_cxr_mask = 0x000000ff,
371 .mmu_sfsr_mask = 0x00016fff,
372 .mmu_trcr_mask = 0x00ffffff,
373 .nwindows = 8,
374 .features = CPU_DEFAULT_FEATURES,
377 .name = "Fujitsu MB86907",
378 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
379 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
380 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
381 .mmu_bm = 0x00004000,
382 .mmu_ctpr_mask = 0xffffffc0,
383 .mmu_cxr_mask = 0x000000ff,
384 .mmu_sfsr_mask = 0x00016fff,
385 .mmu_trcr_mask = 0xffffffff,
386 .nwindows = 8,
387 .features = CPU_DEFAULT_FEATURES,
390 .name = "TI MicroSparc I",
391 .iu_version = 0x41000000,
392 .fpu_version = 4 << 17,
393 .mmu_version = 0x41000000,
394 .mmu_bm = 0x00004000,
395 .mmu_ctpr_mask = 0x007ffff0,
396 .mmu_cxr_mask = 0x0000003f,
397 .mmu_sfsr_mask = 0x00016fff,
398 .mmu_trcr_mask = 0x0000003f,
399 .nwindows = 7,
400 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
401 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
402 CPU_FEATURE_FMUL,
405 .name = "TI MicroSparc II",
406 .iu_version = 0x42000000,
407 .fpu_version = 4 << 17,
408 .mmu_version = 0x02000000,
409 .mmu_bm = 0x00004000,
410 .mmu_ctpr_mask = 0x00ffffc0,
411 .mmu_cxr_mask = 0x000000ff,
412 .mmu_sfsr_mask = 0x00016fff,
413 .mmu_trcr_mask = 0x00ffffff,
414 .nwindows = 8,
415 .features = CPU_DEFAULT_FEATURES,
418 .name = "TI MicroSparc IIep",
419 .iu_version = 0x42000000,
420 .fpu_version = 4 << 17,
421 .mmu_version = 0x04000000,
422 .mmu_bm = 0x00004000,
423 .mmu_ctpr_mask = 0x00ffffc0,
424 .mmu_cxr_mask = 0x000000ff,
425 .mmu_sfsr_mask = 0x00016bff,
426 .mmu_trcr_mask = 0x00ffffff,
427 .nwindows = 8,
428 .features = CPU_DEFAULT_FEATURES,
431 .name = "TI SuperSparc 40", /* STP1020NPGA */
432 .iu_version = 0x41000000, /* SuperSPARC 2.x */
433 .fpu_version = 0 << 17,
434 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
435 .mmu_bm = 0x00002000,
436 .mmu_ctpr_mask = 0xffffffc0,
437 .mmu_cxr_mask = 0x0000ffff,
438 .mmu_sfsr_mask = 0xffffffff,
439 .mmu_trcr_mask = 0xffffffff,
440 .nwindows = 8,
441 .features = CPU_DEFAULT_FEATURES,
444 .name = "TI SuperSparc 50", /* STP1020PGA */
445 .iu_version = 0x40000000, /* SuperSPARC 3.x */
446 .fpu_version = 0 << 17,
447 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
448 .mmu_bm = 0x00002000,
449 .mmu_ctpr_mask = 0xffffffc0,
450 .mmu_cxr_mask = 0x0000ffff,
451 .mmu_sfsr_mask = 0xffffffff,
452 .mmu_trcr_mask = 0xffffffff,
453 .nwindows = 8,
454 .features = CPU_DEFAULT_FEATURES,
457 .name = "TI SuperSparc 51",
458 .iu_version = 0x40000000, /* SuperSPARC 3.x */
459 .fpu_version = 0 << 17,
460 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
461 .mmu_bm = 0x00002000,
462 .mmu_ctpr_mask = 0xffffffc0,
463 .mmu_cxr_mask = 0x0000ffff,
464 .mmu_sfsr_mask = 0xffffffff,
465 .mmu_trcr_mask = 0xffffffff,
466 .mxcc_version = 0x00000104,
467 .nwindows = 8,
468 .features = CPU_DEFAULT_FEATURES,
471 .name = "TI SuperSparc 60", /* STP1020APGA */
472 .iu_version = 0x40000000, /* SuperSPARC 3.x */
473 .fpu_version = 0 << 17,
474 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
475 .mmu_bm = 0x00002000,
476 .mmu_ctpr_mask = 0xffffffc0,
477 .mmu_cxr_mask = 0x0000ffff,
478 .mmu_sfsr_mask = 0xffffffff,
479 .mmu_trcr_mask = 0xffffffff,
480 .nwindows = 8,
481 .features = CPU_DEFAULT_FEATURES,
484 .name = "TI SuperSparc 61",
485 .iu_version = 0x44000000, /* SuperSPARC 3.x */
486 .fpu_version = 0 << 17,
487 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
488 .mmu_bm = 0x00002000,
489 .mmu_ctpr_mask = 0xffffffc0,
490 .mmu_cxr_mask = 0x0000ffff,
491 .mmu_sfsr_mask = 0xffffffff,
492 .mmu_trcr_mask = 0xffffffff,
493 .mxcc_version = 0x00000104,
494 .nwindows = 8,
495 .features = CPU_DEFAULT_FEATURES,
498 .name = "TI SuperSparc II",
499 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
500 .fpu_version = 0 << 17,
501 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
502 .mmu_bm = 0x00002000,
503 .mmu_ctpr_mask = 0xffffffc0,
504 .mmu_cxr_mask = 0x0000ffff,
505 .mmu_sfsr_mask = 0xffffffff,
506 .mmu_trcr_mask = 0xffffffff,
507 .mxcc_version = 0x00000104,
508 .nwindows = 8,
509 .features = CPU_DEFAULT_FEATURES,
512 .name = "LEON2",
513 .iu_version = 0xf2000000,
514 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
515 .mmu_version = 0xf2000000,
516 .mmu_bm = 0x00004000,
517 .mmu_ctpr_mask = 0x007ffff0,
518 .mmu_cxr_mask = 0x0000003f,
519 .mmu_sfsr_mask = 0xffffffff,
520 .mmu_trcr_mask = 0xffffffff,
521 .nwindows = 8,
522 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
525 .name = "LEON3",
526 .iu_version = 0xf3000000,
527 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
528 .mmu_version = 0xf3000000,
529 .mmu_bm = 0x00000000,
530 .mmu_ctpr_mask = 0xfffffffc,
531 .mmu_cxr_mask = 0x000000ff,
532 .mmu_sfsr_mask = 0xffffffff,
533 .mmu_trcr_mask = 0xffffffff,
534 .nwindows = 8,
535 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
536 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
537 CPU_FEATURE_CASA,
539 #endif
542 static const char * const feature_name[] = {
543 "float",
544 "float128",
545 "swap",
546 "mul",
547 "div",
548 "flush",
549 "fsqrt",
550 "fmul",
551 "vis1",
552 "vis2",
553 "fsmuld",
554 "hypv",
555 "cmt",
556 "gl",
559 static void print_features(uint32_t features, const char *prefix)
561 unsigned int i;
563 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
564 if (feature_name[i] && (features & (1 << i))) {
565 if (prefix) {
566 qemu_printf("%s", prefix);
568 qemu_printf("%s ", feature_name[i]);
573 void sparc_cpu_list(void)
575 unsigned int i;
577 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
578 qemu_printf("Sparc %16s IU " TARGET_FMT_lx
579 " FPU %08x MMU %08x NWINS %d ",
580 sparc_defs[i].name,
581 sparc_defs[i].iu_version,
582 sparc_defs[i].fpu_version,
583 sparc_defs[i].mmu_version,
584 sparc_defs[i].nwindows);
585 print_features(CPU_DEFAULT_FEATURES & ~sparc_defs[i].features, "-");
586 print_features(~CPU_DEFAULT_FEATURES & sparc_defs[i].features, "+");
587 qemu_printf("\n");
589 qemu_printf("Default CPU feature flags (use '-' to remove): ");
590 print_features(CPU_DEFAULT_FEATURES, NULL);
591 qemu_printf("\n");
592 qemu_printf("Available CPU feature flags (use '+' to add): ");
593 print_features(~CPU_DEFAULT_FEATURES, NULL);
594 qemu_printf("\n");
595 qemu_printf("Numerical features (use '=' to set): iu_version "
596 "fpu_version mmu_version nwindows\n");
599 static void cpu_print_cc(FILE *f, uint32_t cc)
601 qemu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
602 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
603 cc & PSR_CARRY ? 'C' : '-');
606 #ifdef TARGET_SPARC64
607 #define REGS_PER_LINE 4
608 #else
609 #define REGS_PER_LINE 8
610 #endif
612 void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
614 SPARCCPU *cpu = SPARC_CPU(cs);
615 CPUSPARCState *env = &cpu->env;
616 int i, x;
618 qemu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
619 env->npc);
621 for (i = 0; i < 8; i++) {
622 if (i % REGS_PER_LINE == 0) {
623 qemu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
625 qemu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
626 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
627 qemu_fprintf(f, "\n");
630 for (x = 0; x < 3; x++) {
631 for (i = 0; i < 8; i++) {
632 if (i % REGS_PER_LINE == 0) {
633 qemu_fprintf(f, "%%%c%d-%d: ",
634 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
635 i, i + REGS_PER_LINE - 1);
637 qemu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
638 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
639 qemu_fprintf(f, "\n");
644 if (flags & CPU_DUMP_FPU) {
645 for (i = 0; i < TARGET_DPREGS; i++) {
646 if ((i & 3) == 0) {
647 qemu_fprintf(f, "%%f%02d: ", i * 2);
649 qemu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
650 if ((i & 3) == 3) {
651 qemu_fprintf(f, "\n");
656 #ifdef TARGET_SPARC64
657 qemu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
658 (unsigned)cpu_get_ccr(env));
659 cpu_print_cc(f, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
660 qemu_fprintf(f, " xcc: ");
661 cpu_print_cc(f, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
662 qemu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
663 env->psrpil, env->gl);
664 qemu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
665 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
666 qemu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
667 "cleanwin: %d cwp: %d\n",
668 env->cansave, env->canrestore, env->otherwin, env->wstate,
669 env->cleanwin, env->nwindows - 1 - env->cwp);
670 qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
671 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
673 #else
674 qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
675 cpu_print_cc(f, cpu_get_psr(env));
676 qemu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
677 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
678 env->wim);
679 qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
680 env->fsr, env->y);
681 #endif
682 qemu_fprintf(f, "\n");
685 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
687 SPARCCPU *cpu = SPARC_CPU(cs);
689 cpu->env.pc = value;
690 cpu->env.npc = value + 4;
693 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
695 SPARCCPU *cpu = SPARC_CPU(cs);
697 cpu->env.pc = tb->pc;
698 cpu->env.npc = tb->cs_base;
701 static bool sparc_cpu_has_work(CPUState *cs)
703 SPARCCPU *cpu = SPARC_CPU(cs);
704 CPUSPARCState *env = &cpu->env;
706 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
707 cpu_interrupts_enabled(env);
710 static char *sparc_cpu_type_name(const char *cpu_model)
712 char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
713 char *s = name;
715 /* SPARC cpu model names happen to have whitespaces,
716 * as type names shouldn't have spaces replace them with '-'
718 while ((s = strchr(s, ' '))) {
719 *s = '-';
722 return name;
725 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
727 ObjectClass *oc;
728 char *typename;
730 typename = sparc_cpu_type_name(cpu_model);
731 oc = object_class_by_name(typename);
732 g_free(typename);
733 return oc;
736 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
738 CPUState *cs = CPU(dev);
739 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
740 Error *local_err = NULL;
741 SPARCCPU *cpu = SPARC_CPU(dev);
742 CPUSPARCState *env = &cpu->env;
744 #if defined(CONFIG_USER_ONLY)
745 if ((env->def.features & CPU_FEATURE_FLOAT)) {
746 env->def.features |= CPU_FEATURE_FLOAT128;
748 #endif
750 env->version = env->def.iu_version;
751 env->fsr = env->def.fpu_version;
752 env->nwindows = env->def.nwindows;
753 #if !defined(TARGET_SPARC64)
754 env->mmuregs[0] |= env->def.mmu_version;
755 cpu_sparc_set_id(env, 0);
756 env->mxccregs[7] |= env->def.mxcc_version;
757 #else
758 env->mmu_version = env->def.mmu_version;
759 env->maxtl = env->def.maxtl;
760 env->version |= env->def.maxtl << 8;
761 env->version |= env->def.nwindows - 1;
762 #endif
764 cpu_exec_realizefn(cs, &local_err);
765 if (local_err != NULL) {
766 error_propagate(errp, local_err);
767 return;
770 qemu_init_vcpu(cs);
772 scc->parent_realize(dev, errp);
775 static void sparc_cpu_initfn(Object *obj)
777 CPUState *cs = CPU(obj);
778 SPARCCPU *cpu = SPARC_CPU(obj);
779 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
780 CPUSPARCState *env = &cpu->env;
782 cs->env_ptr = env;
784 if (scc->cpu_def) {
785 env->def = *scc->cpu_def;
789 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
790 void *opaque, Error **errp)
792 SPARCCPU *cpu = SPARC_CPU(obj);
793 int64_t value = cpu->env.def.nwindows;
795 visit_type_int(v, name, &value, errp);
798 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
799 void *opaque, Error **errp)
801 const int64_t min = MIN_NWINDOWS;
802 const int64_t max = MAX_NWINDOWS;
803 SPARCCPU *cpu = SPARC_CPU(obj);
804 Error *err = NULL;
805 int64_t value;
807 visit_type_int(v, name, &value, &err);
808 if (err) {
809 error_propagate(errp, err);
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 { .name = "nwindows", .info = &qdev_prop_nwindows },
849 DEFINE_PROP_END_OF_LIST()
852 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
854 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
855 CPUClass *cc = CPU_CLASS(oc);
856 DeviceClass *dc = DEVICE_CLASS(oc);
858 device_class_set_parent_realize(dc, sparc_cpu_realizefn,
859 &scc->parent_realize);
860 dc->props = sparc_cpu_properties;
862 scc->parent_reset = cc->reset;
863 cc->reset = sparc_cpu_reset;
865 cc->class_by_name = sparc_cpu_class_by_name;
866 cc->parse_features = sparc_cpu_parse_features;
867 cc->has_work = sparc_cpu_has_work;
868 cc->do_interrupt = sparc_cpu_do_interrupt;
869 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
870 cc->dump_state = sparc_cpu_dump_state;
871 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
872 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
873 #endif
874 cc->set_pc = sparc_cpu_set_pc;
875 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
876 cc->gdb_read_register = sparc_cpu_gdb_read_register;
877 cc->gdb_write_register = sparc_cpu_gdb_write_register;
878 #ifdef CONFIG_USER_ONLY
879 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
880 #else
881 cc->do_unassigned_access = sparc_cpu_unassigned_access;
882 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
883 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
884 cc->vmsd = &vmstate_sparc_cpu;
885 #endif
886 cc->disas_set_info = cpu_sparc_disas_set_info;
887 cc->tcg_initialize = sparc_tcg_init;
889 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
890 cc->gdb_num_core_regs = 86;
891 #else
892 cc->gdb_num_core_regs = 72;
893 #endif
896 static const TypeInfo sparc_cpu_type_info = {
897 .name = TYPE_SPARC_CPU,
898 .parent = TYPE_CPU,
899 .instance_size = sizeof(SPARCCPU),
900 .instance_init = sparc_cpu_initfn,
901 .abstract = true,
902 .class_size = sizeof(SPARCCPUClass),
903 .class_init = sparc_cpu_class_init,
906 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
908 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
909 scc->cpu_def = data;
912 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
914 char *typename = sparc_cpu_type_name(def->name);
915 TypeInfo ti = {
916 .name = typename,
917 .parent = TYPE_SPARC_CPU,
918 .class_init = sparc_cpu_cpudef_class_init,
919 .class_data = (void *)def,
922 type_register(&ti);
923 g_free(typename);
926 static void sparc_cpu_register_types(void)
928 int i;
930 type_register_static(&sparc_cpu_type_info);
931 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
932 sparc_register_cpudef_type(&sparc_defs[i]);
936 type_init(sparc_cpu_register_types)