cpu-exec: don't overwrite exception_index
[qemu/armbru.git] / target / sparc / cpu.c
blobc7adc281dee03e6cddc78ccc5544539bf3248c26
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 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");
659 #ifdef TARGET_SPARC64
660 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
661 (unsigned)cpu_get_ccr(env));
662 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
663 cpu_fprintf(f, " xcc: ");
664 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
665 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
666 env->psrpil, env->gl);
667 cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
668 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
669 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
670 "cleanwin: %d cwp: %d\n",
671 env->cansave, env->canrestore, env->otherwin, env->wstate,
672 env->cleanwin, env->nwindows - 1 - env->cwp);
673 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
674 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
676 #else
677 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
678 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
679 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
680 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
681 env->wim);
682 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
683 env->fsr, env->y);
684 #endif
685 cpu_fprintf(f, "\n");
688 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
690 SPARCCPU *cpu = SPARC_CPU(cs);
692 cpu->env.pc = value;
693 cpu->env.npc = value + 4;
696 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
698 SPARCCPU *cpu = SPARC_CPU(cs);
700 cpu->env.pc = tb->pc;
701 cpu->env.npc = tb->cs_base;
704 static bool sparc_cpu_has_work(CPUState *cs)
706 SPARCCPU *cpu = SPARC_CPU(cs);
707 CPUSPARCState *env = &cpu->env;
709 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
710 cpu_interrupts_enabled(env);
713 static char *sparc_cpu_type_name(const char *cpu_model)
715 char *name = g_strdup_printf(SPARC_CPU_TYPE_NAME("%s"), cpu_model);
716 char *s = name;
718 /* SPARC cpu model names happen to have whitespaces,
719 * as type names shouldn't have spaces replace them with '-'
721 while ((s = strchr(s, ' '))) {
722 *s = '-';
725 return name;
728 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
730 ObjectClass *oc;
731 char *typename;
733 typename = sparc_cpu_type_name(cpu_model);
734 oc = object_class_by_name(typename);
735 g_free(typename);
736 return oc;
739 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
741 CPUState *cs = CPU(dev);
742 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
743 Error *local_err = NULL;
744 SPARCCPU *cpu = SPARC_CPU(dev);
745 CPUSPARCState *env = &cpu->env;
747 #if defined(CONFIG_USER_ONLY)
748 if ((env->def.features & CPU_FEATURE_FLOAT)) {
749 env->def.features |= CPU_FEATURE_FLOAT128;
751 #endif
753 env->version = env->def.iu_version;
754 env->fsr = env->def.fpu_version;
755 env->nwindows = env->def.nwindows;
756 #if !defined(TARGET_SPARC64)
757 env->mmuregs[0] |= env->def.mmu_version;
758 cpu_sparc_set_id(env, 0);
759 env->mxccregs[7] |= env->def.mxcc_version;
760 #else
761 env->mmu_version = env->def.mmu_version;
762 env->maxtl = env->def.maxtl;
763 env->version |= env->def.maxtl << 8;
764 env->version |= env->def.nwindows - 1;
765 #endif
767 cpu_exec_realizefn(cs, &local_err);
768 if (local_err != NULL) {
769 error_propagate(errp, local_err);
770 return;
773 qemu_init_vcpu(cs);
775 scc->parent_realize(dev, errp);
778 static void sparc_cpu_initfn(Object *obj)
780 CPUState *cs = CPU(obj);
781 SPARCCPU *cpu = SPARC_CPU(obj);
782 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
783 CPUSPARCState *env = &cpu->env;
785 cs->env_ptr = env;
787 if (scc->cpu_def) {
788 env->def = *scc->cpu_def;
792 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
793 void *opaque, Error **errp)
795 SPARCCPU *cpu = SPARC_CPU(obj);
796 int64_t value = cpu->env.def.nwindows;
798 visit_type_int(v, name, &value, errp);
801 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
802 void *opaque, Error **errp)
804 const int64_t min = MIN_NWINDOWS;
805 const int64_t max = MAX_NWINDOWS;
806 SPARCCPU *cpu = SPARC_CPU(obj);
807 Error *err = NULL;
808 int64_t value;
810 visit_type_int(v, name, &value, &err);
811 if (err) {
812 error_propagate(errp, err);
813 return;
816 if (value < min || value > max) {
817 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
818 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
819 object_get_typename(obj), name ? name : "null",
820 value, min, max);
821 return;
823 cpu->env.def.nwindows = value;
826 static PropertyInfo qdev_prop_nwindows = {
827 .name = "int",
828 .get = sparc_get_nwindows,
829 .set = sparc_set_nwindows,
832 static Property sparc_cpu_properties[] = {
833 DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false),
834 DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
835 DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false),
836 DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false),
837 DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false),
838 DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false),
839 DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false),
840 DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false),
841 DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false),
842 DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false),
843 DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false),
844 DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false),
845 DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false),
846 DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false),
847 DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
848 qdev_prop_uint64, target_ulong),
849 DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
850 DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
851 { .name = "nwindows", .info = &qdev_prop_nwindows },
852 DEFINE_PROP_END_OF_LIST()
855 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
857 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
858 CPUClass *cc = CPU_CLASS(oc);
859 DeviceClass *dc = DEVICE_CLASS(oc);
861 scc->parent_realize = dc->realize;
862 dc->realize = sparc_cpu_realizefn;
863 dc->props = sparc_cpu_properties;
865 scc->parent_reset = cc->reset;
866 cc->reset = sparc_cpu_reset;
868 cc->class_by_name = sparc_cpu_class_by_name;
869 cc->parse_features = sparc_cpu_parse_features;
870 cc->has_work = sparc_cpu_has_work;
871 cc->do_interrupt = sparc_cpu_do_interrupt;
872 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
873 cc->dump_state = sparc_cpu_dump_state;
874 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
875 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
876 #endif
877 cc->set_pc = sparc_cpu_set_pc;
878 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
879 cc->gdb_read_register = sparc_cpu_gdb_read_register;
880 cc->gdb_write_register = sparc_cpu_gdb_write_register;
881 #ifdef CONFIG_USER_ONLY
882 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
883 #else
884 cc->do_unassigned_access = sparc_cpu_unassigned_access;
885 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
886 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
887 cc->vmsd = &vmstate_sparc_cpu;
888 #endif
889 cc->disas_set_info = cpu_sparc_disas_set_info;
890 cc->tcg_initialize = sparc_tcg_init;
892 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
893 cc->gdb_num_core_regs = 86;
894 #else
895 cc->gdb_num_core_regs = 72;
896 #endif
899 static const TypeInfo sparc_cpu_type_info = {
900 .name = TYPE_SPARC_CPU,
901 .parent = TYPE_CPU,
902 .instance_size = sizeof(SPARCCPU),
903 .instance_init = sparc_cpu_initfn,
904 .abstract = true,
905 .class_size = sizeof(SPARCCPUClass),
906 .class_init = sparc_cpu_class_init,
909 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
911 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
912 scc->cpu_def = data;
915 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
917 char *typename = sparc_cpu_type_name(def->name);
918 TypeInfo ti = {
919 .name = typename,
920 .parent = TYPE_SPARC_CPU,
921 .class_init = sparc_cpu_cpudef_class_init,
922 .class_data = (void *)def,
925 type_register(&ti);
926 g_free(typename);
929 static void sparc_cpu_register_types(void)
931 int i;
933 type_register_static(&sparc_cpu_type_info);
934 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
935 sparc_register_cpudef_type(&sparc_defs[i]);
939 type_init(sparc_cpu_register_types)