Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging
[qemu/ar7.git] / target / sparc / cpu.c
blob0f090ece540161e0b121f8e83b0d43925931f942
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 prop->errp = &error_fatal;
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(FILE *f, fprintf_function cpu_fprintf,
561 uint32_t features, const char *prefix)
563 unsigned int i;
565 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
566 if (feature_name[i] && (features & (1 << i))) {
567 if (prefix) {
568 (*cpu_fprintf)(f, "%s", prefix);
570 (*cpu_fprintf)(f, "%s ", feature_name[i]);
575 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
577 unsigned int i;
579 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
580 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
581 " FPU %08x MMU %08x NWINS %d ",
582 sparc_defs[i].name,
583 sparc_defs[i].iu_version,
584 sparc_defs[i].fpu_version,
585 sparc_defs[i].mmu_version,
586 sparc_defs[i].nwindows);
587 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
588 ~sparc_defs[i].features, "-");
589 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
590 sparc_defs[i].features, "+");
591 (*cpu_fprintf)(f, "\n");
593 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
594 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
595 (*cpu_fprintf)(f, "\n");
596 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
597 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
598 (*cpu_fprintf)(f, "\n");
599 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
600 "fpu_version mmu_version nwindows\n");
603 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
604 uint32_t cc)
606 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
607 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
608 cc & PSR_CARRY ? 'C' : '-');
611 #ifdef TARGET_SPARC64
612 #define REGS_PER_LINE 4
613 #else
614 #define REGS_PER_LINE 8
615 #endif
617 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
618 int flags)
620 SPARCCPU *cpu = SPARC_CPU(cs);
621 CPUSPARCState *env = &cpu->env;
622 int i, x;
624 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
625 env->npc);
627 for (i = 0; i < 8; i++) {
628 if (i % REGS_PER_LINE == 0) {
629 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
631 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
632 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
633 cpu_fprintf(f, "\n");
636 for (x = 0; x < 3; x++) {
637 for (i = 0; i < 8; i++) {
638 if (i % REGS_PER_LINE == 0) {
639 cpu_fprintf(f, "%%%c%d-%d: ",
640 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
641 i, i + REGS_PER_LINE - 1);
643 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
644 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
645 cpu_fprintf(f, "\n");
650 if (flags & CPU_DUMP_FPU) {
651 for (i = 0; i < TARGET_DPREGS; i++) {
652 if ((i & 3) == 0) {
653 cpu_fprintf(f, "%%f%02d: ", i * 2);
655 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
656 if ((i & 3) == 3) {
657 cpu_fprintf(f, "\n");
662 #ifdef TARGET_SPARC64
663 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
664 (unsigned)cpu_get_ccr(env));
665 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
666 cpu_fprintf(f, " xcc: ");
667 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
668 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
669 env->psrpil, env->gl);
670 cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
671 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
672 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
673 "cleanwin: %d cwp: %d\n",
674 env->cansave, env->canrestore, env->otherwin, env->wstate,
675 env->cleanwin, env->nwindows - 1 - env->cwp);
676 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
677 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
679 #else
680 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
681 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
682 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
683 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
684 env->wim);
685 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
686 env->fsr, env->y);
687 #endif
688 cpu_fprintf(f, "\n");
691 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
693 SPARCCPU *cpu = SPARC_CPU(cs);
695 cpu->env.pc = value;
696 cpu->env.npc = value + 4;
699 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
701 SPARCCPU *cpu = SPARC_CPU(cs);
703 cpu->env.pc = tb->pc;
704 cpu->env.npc = tb->cs_base;
707 static bool sparc_cpu_has_work(CPUState *cs)
709 SPARCCPU *cpu = SPARC_CPU(cs);
710 CPUSPARCState *env = &cpu->env;
712 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
713 cpu_interrupts_enabled(env);
716 static char *sparc_cpu_type_name(const char *cpu_model)
718 char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
719 char *s = name;
721 /* SPARC cpu model names happen to have whitespaces,
722 * as type names shouldn't have spaces replace them with '-'
724 while ((s = strchr(s, ' '))) {
725 *s = '-';
728 return name;
731 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
733 ObjectClass *oc;
734 char *typename;
736 typename = sparc_cpu_type_name(cpu_model);
737 oc = object_class_by_name(typename);
738 g_free(typename);
739 return oc;
742 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
744 CPUState *cs = CPU(dev);
745 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
746 Error *local_err = NULL;
747 SPARCCPU *cpu = SPARC_CPU(dev);
748 CPUSPARCState *env = &cpu->env;
750 #if defined(CONFIG_USER_ONLY)
751 if ((env->def.features & CPU_FEATURE_FLOAT)) {
752 env->def.features |= CPU_FEATURE_FLOAT128;
754 #endif
756 env->version = env->def.iu_version;
757 env->fsr = env->def.fpu_version;
758 env->nwindows = env->def.nwindows;
759 #if !defined(TARGET_SPARC64)
760 env->mmuregs[0] |= env->def.mmu_version;
761 cpu_sparc_set_id(env, 0);
762 env->mxccregs[7] |= env->def.mxcc_version;
763 #else
764 env->mmu_version = env->def.mmu_version;
765 env->maxtl = env->def.maxtl;
766 env->version |= env->def.maxtl << 8;
767 env->version |= env->def.nwindows - 1;
768 #endif
770 cpu_exec_realizefn(cs, &local_err);
771 if (local_err != NULL) {
772 error_propagate(errp, local_err);
773 return;
776 qemu_init_vcpu(cs);
778 scc->parent_realize(dev, errp);
781 static void sparc_cpu_initfn(Object *obj)
783 CPUState *cs = CPU(obj);
784 SPARCCPU *cpu = SPARC_CPU(obj);
785 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
786 CPUSPARCState *env = &cpu->env;
788 cs->env_ptr = env;
790 if (scc->cpu_def) {
791 env->def = *scc->cpu_def;
795 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
796 void *opaque, Error **errp)
798 SPARCCPU *cpu = SPARC_CPU(obj);
799 int64_t value = cpu->env.def.nwindows;
801 visit_type_int(v, name, &value, errp);
804 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
805 void *opaque, Error **errp)
807 const int64_t min = MIN_NWINDOWS;
808 const int64_t max = MAX_NWINDOWS;
809 SPARCCPU *cpu = SPARC_CPU(obj);
810 Error *err = NULL;
811 int64_t value;
813 visit_type_int(v, name, &value, &err);
814 if (err) {
815 error_propagate(errp, err);
816 return;
819 if (value < min || value > max) {
820 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
821 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
822 object_get_typename(obj), name ? name : "null",
823 value, min, max);
824 return;
826 cpu->env.def.nwindows = value;
829 static PropertyInfo qdev_prop_nwindows = {
830 .name = "int",
831 .get = sparc_get_nwindows,
832 .set = sparc_set_nwindows,
835 static Property sparc_cpu_properties[] = {
836 DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false),
837 DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
838 DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false),
839 DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false),
840 DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false),
841 DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false),
842 DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false),
843 DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false),
844 DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false),
845 DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false),
846 DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false),
847 DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false),
848 DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false),
849 DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false),
850 DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
851 qdev_prop_uint64, target_ulong),
852 DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
853 DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
854 { .name = "nwindows", .info = &qdev_prop_nwindows },
855 DEFINE_PROP_END_OF_LIST()
858 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
860 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
861 CPUClass *cc = CPU_CLASS(oc);
862 DeviceClass *dc = DEVICE_CLASS(oc);
864 device_class_set_parent_realize(dc, sparc_cpu_realizefn,
865 &scc->parent_realize);
866 dc->props = sparc_cpu_properties;
868 scc->parent_reset = cc->reset;
869 cc->reset = sparc_cpu_reset;
871 cc->class_by_name = sparc_cpu_class_by_name;
872 cc->parse_features = sparc_cpu_parse_features;
873 cc->has_work = sparc_cpu_has_work;
874 cc->do_interrupt = sparc_cpu_do_interrupt;
875 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
876 cc->dump_state = sparc_cpu_dump_state;
877 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
878 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
879 #endif
880 cc->set_pc = sparc_cpu_set_pc;
881 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
882 cc->gdb_read_register = sparc_cpu_gdb_read_register;
883 cc->gdb_write_register = sparc_cpu_gdb_write_register;
884 #ifdef CONFIG_USER_ONLY
885 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
886 #else
887 cc->do_unassigned_access = sparc_cpu_unassigned_access;
888 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
889 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
890 cc->vmsd = &vmstate_sparc_cpu;
891 #endif
892 cc->disas_set_info = cpu_sparc_disas_set_info;
893 cc->tcg_initialize = sparc_tcg_init;
895 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
896 cc->gdb_num_core_regs = 86;
897 #else
898 cc->gdb_num_core_regs = 72;
899 #endif
902 static const TypeInfo sparc_cpu_type_info = {
903 .name = TYPE_SPARC_CPU,
904 .parent = TYPE_CPU,
905 .instance_size = sizeof(SPARCCPU),
906 .instance_init = sparc_cpu_initfn,
907 .abstract = true,
908 .class_size = sizeof(SPARCCPUClass),
909 .class_init = sparc_cpu_class_init,
912 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
914 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
915 scc->cpu_def = data;
918 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
920 char *typename = sparc_cpu_type_name(def->name);
921 TypeInfo ti = {
922 .name = typename,
923 .parent = TYPE_SPARC_CPU,
924 .class_init = sparc_cpu_cpudef_class_init,
925 .class_data = (void *)def,
928 type_register(&ti);
929 g_free(typename);
932 static void sparc_cpu_register_types(void)
934 int i;
936 type_register_static(&sparc_cpu_type_info);
937 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
938 sparc_register_cpudef_type(&sparc_defs[i]);
942 type_init(sparc_cpu_register_types)