nbd: Only require disabled bitmap for read-only exports
[qemu/ar7.git] / target / sparc / cpu.c
blob4a4445bdf58fa9d271613fdd8840ab63b6ec5b2a
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 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(FILE *f, fprintf_function cpu_fprintf,
560 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 (*cpu_fprintf)(f, "%s", prefix);
569 (*cpu_fprintf)(f, "%s ", feature_name[i]);
574 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
576 unsigned int i;
578 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
579 (*cpu_fprintf)(f, "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(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
587 ~sparc_defs[i].features, "-");
588 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
589 sparc_defs[i].features, "+");
590 (*cpu_fprintf)(f, "\n");
592 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
593 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
594 (*cpu_fprintf)(f, "\n");
595 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
596 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
597 (*cpu_fprintf)(f, "\n");
598 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
599 "fpu_version mmu_version nwindows\n");
602 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
603 uint32_t cc)
605 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
606 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
607 cc & PSR_CARRY ? 'C' : '-');
610 #ifdef TARGET_SPARC64
611 #define REGS_PER_LINE 4
612 #else
613 #define REGS_PER_LINE 8
614 #endif
616 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
617 int flags)
619 SPARCCPU *cpu = SPARC_CPU(cs);
620 CPUSPARCState *env = &cpu->env;
621 int i, x;
623 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
624 env->npc);
626 for (i = 0; i < 8; i++) {
627 if (i % REGS_PER_LINE == 0) {
628 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
630 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
631 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
632 cpu_fprintf(f, "\n");
635 for (x = 0; x < 3; x++) {
636 for (i = 0; i < 8; i++) {
637 if (i % REGS_PER_LINE == 0) {
638 cpu_fprintf(f, "%%%c%d-%d: ",
639 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
640 i, i + REGS_PER_LINE - 1);
642 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
643 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
644 cpu_fprintf(f, "\n");
649 if (flags & CPU_DUMP_FPU) {
650 for (i = 0; i < TARGET_DPREGS; i++) {
651 if ((i & 3) == 0) {
652 cpu_fprintf(f, "%%f%02d: ", i * 2);
654 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
655 if ((i & 3) == 3) {
656 cpu_fprintf(f, "\n");
661 #ifdef TARGET_SPARC64
662 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
663 (unsigned)cpu_get_ccr(env));
664 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
665 cpu_fprintf(f, " xcc: ");
666 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
667 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
668 env->psrpil, env->gl);
669 cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
670 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
671 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
672 "cleanwin: %d cwp: %d\n",
673 env->cansave, env->canrestore, env->otherwin, env->wstate,
674 env->cleanwin, env->nwindows - 1 - env->cwp);
675 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
676 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
678 #else
679 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
680 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
681 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
682 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
683 env->wim);
684 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
685 env->fsr, env->y);
686 #endif
687 cpu_fprintf(f, "\n");
690 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
692 SPARCCPU *cpu = SPARC_CPU(cs);
694 cpu->env.pc = value;
695 cpu->env.npc = value + 4;
698 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
700 SPARCCPU *cpu = SPARC_CPU(cs);
702 cpu->env.pc = tb->pc;
703 cpu->env.npc = tb->cs_base;
706 static bool sparc_cpu_has_work(CPUState *cs)
708 SPARCCPU *cpu = SPARC_CPU(cs);
709 CPUSPARCState *env = &cpu->env;
711 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
712 cpu_interrupts_enabled(env);
715 static char *sparc_cpu_type_name(const char *cpu_model)
717 char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
718 char *s = name;
720 /* SPARC cpu model names happen to have whitespaces,
721 * as type names shouldn't have spaces replace them with '-'
723 while ((s = strchr(s, ' '))) {
724 *s = '-';
727 return name;
730 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
732 ObjectClass *oc;
733 char *typename;
735 typename = sparc_cpu_type_name(cpu_model);
736 oc = object_class_by_name(typename);
737 g_free(typename);
738 return oc;
741 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
743 CPUState *cs = CPU(dev);
744 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
745 Error *local_err = NULL;
746 SPARCCPU *cpu = SPARC_CPU(dev);
747 CPUSPARCState *env = &cpu->env;
749 #if defined(CONFIG_USER_ONLY)
750 if ((env->def.features & CPU_FEATURE_FLOAT)) {
751 env->def.features |= CPU_FEATURE_FLOAT128;
753 #endif
755 env->version = env->def.iu_version;
756 env->fsr = env->def.fpu_version;
757 env->nwindows = env->def.nwindows;
758 #if !defined(TARGET_SPARC64)
759 env->mmuregs[0] |= env->def.mmu_version;
760 cpu_sparc_set_id(env, 0);
761 env->mxccregs[7] |= env->def.mxcc_version;
762 #else
763 env->mmu_version = env->def.mmu_version;
764 env->maxtl = env->def.maxtl;
765 env->version |= env->def.maxtl << 8;
766 env->version |= env->def.nwindows - 1;
767 #endif
769 cpu_exec_realizefn(cs, &local_err);
770 if (local_err != NULL) {
771 error_propagate(errp, local_err);
772 return;
775 qemu_init_vcpu(cs);
777 scc->parent_realize(dev, errp);
780 static void sparc_cpu_initfn(Object *obj)
782 CPUState *cs = CPU(obj);
783 SPARCCPU *cpu = SPARC_CPU(obj);
784 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
785 CPUSPARCState *env = &cpu->env;
787 cs->env_ptr = env;
789 if (scc->cpu_def) {
790 env->def = *scc->cpu_def;
794 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
795 void *opaque, Error **errp)
797 SPARCCPU *cpu = SPARC_CPU(obj);
798 int64_t value = cpu->env.def.nwindows;
800 visit_type_int(v, name, &value, errp);
803 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
804 void *opaque, Error **errp)
806 const int64_t min = MIN_NWINDOWS;
807 const int64_t max = MAX_NWINDOWS;
808 SPARCCPU *cpu = SPARC_CPU(obj);
809 Error *err = NULL;
810 int64_t value;
812 visit_type_int(v, name, &value, &err);
813 if (err) {
814 error_propagate(errp, err);
815 return;
818 if (value < min || value > max) {
819 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
820 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
821 object_get_typename(obj), name ? name : "null",
822 value, min, max);
823 return;
825 cpu->env.def.nwindows = value;
828 static PropertyInfo qdev_prop_nwindows = {
829 .name = "int",
830 .get = sparc_get_nwindows,
831 .set = sparc_set_nwindows,
834 static Property sparc_cpu_properties[] = {
835 DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false),
836 DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
837 DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false),
838 DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false),
839 DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false),
840 DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false),
841 DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false),
842 DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false),
843 DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false),
844 DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false),
845 DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false),
846 DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false),
847 DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false),
848 DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false),
849 DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
850 qdev_prop_uint64, target_ulong),
851 DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
852 DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
853 { .name = "nwindows", .info = &qdev_prop_nwindows },
854 DEFINE_PROP_END_OF_LIST()
857 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
859 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
860 CPUClass *cc = CPU_CLASS(oc);
861 DeviceClass *dc = DEVICE_CLASS(oc);
863 device_class_set_parent_realize(dc, sparc_cpu_realizefn,
864 &scc->parent_realize);
865 dc->props = sparc_cpu_properties;
867 scc->parent_reset = cc->reset;
868 cc->reset = sparc_cpu_reset;
870 cc->class_by_name = sparc_cpu_class_by_name;
871 cc->parse_features = sparc_cpu_parse_features;
872 cc->has_work = sparc_cpu_has_work;
873 cc->do_interrupt = sparc_cpu_do_interrupt;
874 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
875 cc->dump_state = sparc_cpu_dump_state;
876 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
877 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
878 #endif
879 cc->set_pc = sparc_cpu_set_pc;
880 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
881 cc->gdb_read_register = sparc_cpu_gdb_read_register;
882 cc->gdb_write_register = sparc_cpu_gdb_write_register;
883 #ifdef CONFIG_USER_ONLY
884 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
885 #else
886 cc->do_unassigned_access = sparc_cpu_unassigned_access;
887 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
888 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
889 cc->vmsd = &vmstate_sparc_cpu;
890 #endif
891 cc->disas_set_info = cpu_sparc_disas_set_info;
892 cc->tcg_initialize = sparc_tcg_init;
894 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
895 cc->gdb_num_core_regs = 86;
896 #else
897 cc->gdb_num_core_regs = 72;
898 #endif
901 static const TypeInfo sparc_cpu_type_info = {
902 .name = TYPE_SPARC_CPU,
903 .parent = TYPE_CPU,
904 .instance_size = sizeof(SPARCCPU),
905 .instance_init = sparc_cpu_initfn,
906 .abstract = true,
907 .class_size = sizeof(SPARCCPUClass),
908 .class_init = sparc_cpu_class_init,
911 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
913 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
914 scc->cpu_def = data;
917 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
919 char *typename = sparc_cpu_type_name(def->name);
920 TypeInfo ti = {
921 .name = typename,
922 .parent = TYPE_SPARC_CPU,
923 .class_init = sparc_cpu_cpudef_class_init,
924 .class_data = (void *)def,
927 type_register(&ti);
928 g_free(typename);
931 static void sparc_cpu_register_types(void)
933 int i;
935 type_register_static(&sparc_cpu_type_info);
936 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
937 sparc_register_cpudef_type(&sparc_defs[i]);
941 type_init(sparc_cpu_register_types)