linux-user/: fix some comment spelling errors
[qemu/ar7.git] / target / sparc / cpu.c
blobcf21efd85f5b5e54ed2ae3c0cb54ed2491f2351a
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/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, TranslationBlock *tb)
696 SPARCCPU *cpu = SPARC_CPU(cs);
698 cpu->env.pc = tb->pc;
699 cpu->env.npc = tb->cs_base;
702 static bool sparc_cpu_has_work(CPUState *cs)
704 SPARCCPU *cpu = SPARC_CPU(cs);
705 CPUSPARCState *env = &cpu->env;
707 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
708 cpu_interrupts_enabled(env);
711 static char *sparc_cpu_type_name(const char *cpu_model)
713 char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
714 char *s = name;
716 /* SPARC cpu model names happen to have whitespaces,
717 * as type names shouldn't have spaces replace them with '-'
719 while ((s = strchr(s, ' '))) {
720 *s = '-';
723 return name;
726 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
728 ObjectClass *oc;
729 char *typename;
731 typename = sparc_cpu_type_name(cpu_model);
732 oc = object_class_by_name(typename);
733 g_free(typename);
734 return oc;
737 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
739 CPUState *cs = CPU(dev);
740 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
741 Error *local_err = NULL;
742 SPARCCPU *cpu = SPARC_CPU(dev);
743 CPUSPARCState *env = &cpu->env;
745 #if defined(CONFIG_USER_ONLY)
746 if ((env->def.features & CPU_FEATURE_FLOAT)) {
747 env->def.features |= CPU_FEATURE_FLOAT128;
749 #endif
751 env->version = env->def.iu_version;
752 env->fsr = env->def.fpu_version;
753 env->nwindows = env->def.nwindows;
754 #if !defined(TARGET_SPARC64)
755 env->mmuregs[0] |= env->def.mmu_version;
756 cpu_sparc_set_id(env, 0);
757 env->mxccregs[7] |= env->def.mxcc_version;
758 #else
759 env->mmu_version = env->def.mmu_version;
760 env->maxtl = env->def.maxtl;
761 env->version |= env->def.maxtl << 8;
762 env->version |= env->def.nwindows - 1;
763 #endif
765 cpu_exec_realizefn(cs, &local_err);
766 if (local_err != NULL) {
767 error_propagate(errp, local_err);
768 return;
771 qemu_init_vcpu(cs);
773 scc->parent_realize(dev, errp);
776 static void sparc_cpu_initfn(Object *obj)
778 SPARCCPU *cpu = SPARC_CPU(obj);
779 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
780 CPUSPARCState *env = &cpu->env;
782 cpu_set_cpustate_pointers(cpu);
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 int64_t value;
806 if (!visit_type_int(v, name, &value, errp)) {
807 return;
810 if (value < min || value > max) {
811 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
812 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
813 object_get_typename(obj), name ? name : "null",
814 value, min, max);
815 return;
817 cpu->env.def.nwindows = value;
820 static PropertyInfo qdev_prop_nwindows = {
821 .name = "int",
822 .get = sparc_get_nwindows,
823 .set = sparc_set_nwindows,
826 static Property sparc_cpu_properties[] = {
827 DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false),
828 DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
829 DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false),
830 DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false),
831 DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false),
832 DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false),
833 DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false),
834 DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false),
835 DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false),
836 DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false),
837 DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false),
838 DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false),
839 DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false),
840 DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false),
841 DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
842 qdev_prop_uint64, target_ulong),
843 DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
844 DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
845 { .name = "nwindows", .info = &qdev_prop_nwindows },
846 DEFINE_PROP_END_OF_LIST()
849 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
851 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
852 CPUClass *cc = CPU_CLASS(oc);
853 DeviceClass *dc = DEVICE_CLASS(oc);
855 device_class_set_parent_realize(dc, sparc_cpu_realizefn,
856 &scc->parent_realize);
857 device_class_set_props(dc, sparc_cpu_properties);
859 device_class_set_parent_reset(dc, sparc_cpu_reset, &scc->parent_reset);
861 cc->class_by_name = sparc_cpu_class_by_name;
862 cc->parse_features = sparc_cpu_parse_features;
863 cc->has_work = sparc_cpu_has_work;
864 cc->do_interrupt = sparc_cpu_do_interrupt;
865 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
866 cc->dump_state = sparc_cpu_dump_state;
867 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
868 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
869 #endif
870 cc->set_pc = sparc_cpu_set_pc;
871 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
872 cc->gdb_read_register = sparc_cpu_gdb_read_register;
873 cc->gdb_write_register = sparc_cpu_gdb_write_register;
874 cc->tlb_fill = sparc_cpu_tlb_fill;
875 #ifndef CONFIG_USER_ONLY
876 cc->do_transaction_failed = sparc_cpu_do_transaction_failed;
877 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
878 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
879 cc->vmsd = &vmstate_sparc_cpu;
880 #endif
881 cc->disas_set_info = cpu_sparc_disas_set_info;
882 cc->tcg_initialize = sparc_tcg_init;
884 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
885 cc->gdb_num_core_regs = 86;
886 #else
887 cc->gdb_num_core_regs = 72;
888 #endif
891 static const TypeInfo sparc_cpu_type_info = {
892 .name = TYPE_SPARC_CPU,
893 .parent = TYPE_CPU,
894 .instance_size = sizeof(SPARCCPU),
895 .instance_init = sparc_cpu_initfn,
896 .abstract = true,
897 .class_size = sizeof(SPARCCPUClass),
898 .class_init = sparc_cpu_class_init,
901 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
903 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
904 scc->cpu_def = data;
907 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
909 char *typename = sparc_cpu_type_name(def->name);
910 TypeInfo ti = {
911 .name = typename,
912 .parent = TYPE_SPARC_CPU,
913 .class_init = sparc_cpu_cpudef_class_init,
914 .class_data = (void *)def,
917 type_register(&ti);
918 g_free(typename);
921 static void sparc_cpu_register_types(void)
923 int i;
925 type_register_static(&sparc_cpu_type_info);
926 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
927 sparc_register_cpudef_type(&sparc_defs[i]);
931 type_init(sparc_cpu_register_types)