ppc: Fix catching some segfaults in user mode
[qemu/kevin.git] / target-sparc / cpu.c
blobe4089f2074cc493e6954f5507cdd4dd0cfa22efe
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"
26 //#define DEBUG_FEATURES
28 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
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, version));
40 tlb_flush(s, 1);
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|PS_AG;
62 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
63 env->tl = env->maxtl;
64 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
65 env->lsu = 0;
66 #else
67 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
68 env->mmuregs[0] |= env->def->mmu_bm;
69 #endif
70 env->pc = 0;
71 env->npc = env->pc + 4;
72 #endif
73 env->cache_control = 0;
76 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
78 if (interrupt_request & CPU_INTERRUPT_HARD) {
79 SPARCCPU *cpu = SPARC_CPU(cs);
80 CPUSPARCState *env = &cpu->env;
82 if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
83 int pil = env->interrupt_index & 0xf;
84 int type = env->interrupt_index & 0xf0;
86 if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
87 cs->exception_index = env->interrupt_index;
88 sparc_cpu_do_interrupt(cs);
89 return true;
93 return false;
96 static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
98 info->print_insn = print_insn_sparc;
99 #ifdef TARGET_SPARC64
100 info->mach = bfd_mach_sparc_v9b;
101 #endif
104 static void sparc_cpu_parse_features(CPUState *cs, char *features,
105 Error **errp);
107 static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
109 CPUSPARCState *env = &cpu->env;
110 char *s = g_strdup(cpu_model);
111 char *featurestr, *name = strtok(s, ",");
112 sparc_def_t def1, *def = &def1;
113 Error *err = NULL;
115 if (cpu_sparc_find_by_name(def, name) < 0) {
116 g_free(s);
117 return -1;
120 env->def = g_new0(sparc_def_t, 1);
121 memcpy(env->def, def, sizeof(*def));
123 featurestr = strtok(NULL, ",");
124 sparc_cpu_parse_features(CPU(cpu), featurestr, &err);
125 g_free(s);
126 if (err) {
127 error_report_err(err);
128 return -1;
131 env->version = def->iu_version;
132 env->fsr = def->fpu_version;
133 env->nwindows = def->nwindows;
134 #if !defined(TARGET_SPARC64)
135 env->mmuregs[0] |= def->mmu_version;
136 cpu_sparc_set_id(env, 0);
137 env->mxccregs[7] |= def->mxcc_version;
138 #else
139 env->mmu_version = def->mmu_version;
140 env->maxtl = def->maxtl;
141 env->version |= def->maxtl << 8;
142 env->version |= def->nwindows - 1;
143 #endif
144 return 0;
147 SPARCCPU *cpu_sparc_init(const char *cpu_model)
149 SPARCCPU *cpu;
151 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
153 if (cpu_sparc_register(cpu, cpu_model) < 0) {
154 object_unref(OBJECT(cpu));
155 return NULL;
158 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
160 return cpu;
163 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
165 #if !defined(TARGET_SPARC64)
166 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
167 #endif
170 static const sparc_def_t sparc_defs[] = {
171 #ifdef TARGET_SPARC64
173 .name = "Fujitsu Sparc64",
174 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
175 .fpu_version = 0x00000000,
176 .mmu_version = mmu_us_12,
177 .nwindows = 4,
178 .maxtl = 4,
179 .features = CPU_DEFAULT_FEATURES,
182 .name = "Fujitsu Sparc64 III",
183 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
184 .fpu_version = 0x00000000,
185 .mmu_version = mmu_us_12,
186 .nwindows = 5,
187 .maxtl = 4,
188 .features = CPU_DEFAULT_FEATURES,
191 .name = "Fujitsu Sparc64 IV",
192 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
193 .fpu_version = 0x00000000,
194 .mmu_version = mmu_us_12,
195 .nwindows = 8,
196 .maxtl = 5,
197 .features = CPU_DEFAULT_FEATURES,
200 .name = "Fujitsu Sparc64 V",
201 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
202 .fpu_version = 0x00000000,
203 .mmu_version = mmu_us_12,
204 .nwindows = 8,
205 .maxtl = 5,
206 .features = CPU_DEFAULT_FEATURES,
209 .name = "TI UltraSparc I",
210 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
211 .fpu_version = 0x00000000,
212 .mmu_version = mmu_us_12,
213 .nwindows = 8,
214 .maxtl = 5,
215 .features = CPU_DEFAULT_FEATURES,
218 .name = "TI UltraSparc II",
219 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
220 .fpu_version = 0x00000000,
221 .mmu_version = mmu_us_12,
222 .nwindows = 8,
223 .maxtl = 5,
224 .features = CPU_DEFAULT_FEATURES,
227 .name = "TI UltraSparc IIi",
228 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
229 .fpu_version = 0x00000000,
230 .mmu_version = mmu_us_12,
231 .nwindows = 8,
232 .maxtl = 5,
233 .features = CPU_DEFAULT_FEATURES,
236 .name = "TI UltraSparc IIe",
237 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
238 .fpu_version = 0x00000000,
239 .mmu_version = mmu_us_12,
240 .nwindows = 8,
241 .maxtl = 5,
242 .features = CPU_DEFAULT_FEATURES,
245 .name = "Sun UltraSparc III",
246 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
247 .fpu_version = 0x00000000,
248 .mmu_version = mmu_us_12,
249 .nwindows = 8,
250 .maxtl = 5,
251 .features = CPU_DEFAULT_FEATURES,
254 .name = "Sun UltraSparc III Cu",
255 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
256 .fpu_version = 0x00000000,
257 .mmu_version = mmu_us_3,
258 .nwindows = 8,
259 .maxtl = 5,
260 .features = CPU_DEFAULT_FEATURES,
263 .name = "Sun UltraSparc IIIi",
264 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
265 .fpu_version = 0x00000000,
266 .mmu_version = mmu_us_12,
267 .nwindows = 8,
268 .maxtl = 5,
269 .features = CPU_DEFAULT_FEATURES,
272 .name = "Sun UltraSparc IV",
273 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
274 .fpu_version = 0x00000000,
275 .mmu_version = mmu_us_4,
276 .nwindows = 8,
277 .maxtl = 5,
278 .features = CPU_DEFAULT_FEATURES,
281 .name = "Sun UltraSparc IV+",
282 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
283 .fpu_version = 0x00000000,
284 .mmu_version = mmu_us_12,
285 .nwindows = 8,
286 .maxtl = 5,
287 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
290 .name = "Sun UltraSparc IIIi+",
291 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
292 .fpu_version = 0x00000000,
293 .mmu_version = mmu_us_3,
294 .nwindows = 8,
295 .maxtl = 5,
296 .features = CPU_DEFAULT_FEATURES,
299 .name = "Sun UltraSparc T1",
300 /* defined in sparc_ifu_fdp.v and ctu.h */
301 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
302 .fpu_version = 0x00000000,
303 .mmu_version = mmu_sun4v,
304 .nwindows = 8,
305 .maxtl = 6,
306 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
307 | CPU_FEATURE_GL,
310 .name = "Sun UltraSparc T2",
311 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
312 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
313 .fpu_version = 0x00000000,
314 .mmu_version = mmu_sun4v,
315 .nwindows = 8,
316 .maxtl = 6,
317 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
318 | CPU_FEATURE_GL,
321 .name = "NEC UltraSparc I",
322 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
323 .fpu_version = 0x00000000,
324 .mmu_version = mmu_us_12,
325 .nwindows = 8,
326 .maxtl = 5,
327 .features = CPU_DEFAULT_FEATURES,
329 #else
331 .name = "Fujitsu MB86904",
332 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
333 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
334 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
335 .mmu_bm = 0x00004000,
336 .mmu_ctpr_mask = 0x00ffffc0,
337 .mmu_cxr_mask = 0x000000ff,
338 .mmu_sfsr_mask = 0x00016fff,
339 .mmu_trcr_mask = 0x00ffffff,
340 .nwindows = 8,
341 .features = CPU_DEFAULT_FEATURES,
344 .name = "Fujitsu MB86907",
345 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
346 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
347 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
348 .mmu_bm = 0x00004000,
349 .mmu_ctpr_mask = 0xffffffc0,
350 .mmu_cxr_mask = 0x000000ff,
351 .mmu_sfsr_mask = 0x00016fff,
352 .mmu_trcr_mask = 0xffffffff,
353 .nwindows = 8,
354 .features = CPU_DEFAULT_FEATURES,
357 .name = "TI MicroSparc I",
358 .iu_version = 0x41000000,
359 .fpu_version = 4 << 17,
360 .mmu_version = 0x41000000,
361 .mmu_bm = 0x00004000,
362 .mmu_ctpr_mask = 0x007ffff0,
363 .mmu_cxr_mask = 0x0000003f,
364 .mmu_sfsr_mask = 0x00016fff,
365 .mmu_trcr_mask = 0x0000003f,
366 .nwindows = 7,
367 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
368 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
369 CPU_FEATURE_FMUL,
372 .name = "TI MicroSparc II",
373 .iu_version = 0x42000000,
374 .fpu_version = 4 << 17,
375 .mmu_version = 0x02000000,
376 .mmu_bm = 0x00004000,
377 .mmu_ctpr_mask = 0x00ffffc0,
378 .mmu_cxr_mask = 0x000000ff,
379 .mmu_sfsr_mask = 0x00016fff,
380 .mmu_trcr_mask = 0x00ffffff,
381 .nwindows = 8,
382 .features = CPU_DEFAULT_FEATURES,
385 .name = "TI MicroSparc IIep",
386 .iu_version = 0x42000000,
387 .fpu_version = 4 << 17,
388 .mmu_version = 0x04000000,
389 .mmu_bm = 0x00004000,
390 .mmu_ctpr_mask = 0x00ffffc0,
391 .mmu_cxr_mask = 0x000000ff,
392 .mmu_sfsr_mask = 0x00016bff,
393 .mmu_trcr_mask = 0x00ffffff,
394 .nwindows = 8,
395 .features = CPU_DEFAULT_FEATURES,
398 .name = "TI SuperSparc 40", /* STP1020NPGA */
399 .iu_version = 0x41000000, /* SuperSPARC 2.x */
400 .fpu_version = 0 << 17,
401 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
402 .mmu_bm = 0x00002000,
403 .mmu_ctpr_mask = 0xffffffc0,
404 .mmu_cxr_mask = 0x0000ffff,
405 .mmu_sfsr_mask = 0xffffffff,
406 .mmu_trcr_mask = 0xffffffff,
407 .nwindows = 8,
408 .features = CPU_DEFAULT_FEATURES,
411 .name = "TI SuperSparc 50", /* STP1020PGA */
412 .iu_version = 0x40000000, /* SuperSPARC 3.x */
413 .fpu_version = 0 << 17,
414 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
415 .mmu_bm = 0x00002000,
416 .mmu_ctpr_mask = 0xffffffc0,
417 .mmu_cxr_mask = 0x0000ffff,
418 .mmu_sfsr_mask = 0xffffffff,
419 .mmu_trcr_mask = 0xffffffff,
420 .nwindows = 8,
421 .features = CPU_DEFAULT_FEATURES,
424 .name = "TI SuperSparc 51",
425 .iu_version = 0x40000000, /* SuperSPARC 3.x */
426 .fpu_version = 0 << 17,
427 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
428 .mmu_bm = 0x00002000,
429 .mmu_ctpr_mask = 0xffffffc0,
430 .mmu_cxr_mask = 0x0000ffff,
431 .mmu_sfsr_mask = 0xffffffff,
432 .mmu_trcr_mask = 0xffffffff,
433 .mxcc_version = 0x00000104,
434 .nwindows = 8,
435 .features = CPU_DEFAULT_FEATURES,
438 .name = "TI SuperSparc 60", /* STP1020APGA */
439 .iu_version = 0x40000000, /* SuperSPARC 3.x */
440 .fpu_version = 0 << 17,
441 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
442 .mmu_bm = 0x00002000,
443 .mmu_ctpr_mask = 0xffffffc0,
444 .mmu_cxr_mask = 0x0000ffff,
445 .mmu_sfsr_mask = 0xffffffff,
446 .mmu_trcr_mask = 0xffffffff,
447 .nwindows = 8,
448 .features = CPU_DEFAULT_FEATURES,
451 .name = "TI SuperSparc 61",
452 .iu_version = 0x44000000, /* SuperSPARC 3.x */
453 .fpu_version = 0 << 17,
454 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
455 .mmu_bm = 0x00002000,
456 .mmu_ctpr_mask = 0xffffffc0,
457 .mmu_cxr_mask = 0x0000ffff,
458 .mmu_sfsr_mask = 0xffffffff,
459 .mmu_trcr_mask = 0xffffffff,
460 .mxcc_version = 0x00000104,
461 .nwindows = 8,
462 .features = CPU_DEFAULT_FEATURES,
465 .name = "TI SuperSparc II",
466 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
467 .fpu_version = 0 << 17,
468 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
469 .mmu_bm = 0x00002000,
470 .mmu_ctpr_mask = 0xffffffc0,
471 .mmu_cxr_mask = 0x0000ffff,
472 .mmu_sfsr_mask = 0xffffffff,
473 .mmu_trcr_mask = 0xffffffff,
474 .mxcc_version = 0x00000104,
475 .nwindows = 8,
476 .features = CPU_DEFAULT_FEATURES,
479 .name = "LEON2",
480 .iu_version = 0xf2000000,
481 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
482 .mmu_version = 0xf2000000,
483 .mmu_bm = 0x00004000,
484 .mmu_ctpr_mask = 0x007ffff0,
485 .mmu_cxr_mask = 0x0000003f,
486 .mmu_sfsr_mask = 0xffffffff,
487 .mmu_trcr_mask = 0xffffffff,
488 .nwindows = 8,
489 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
492 .name = "LEON3",
493 .iu_version = 0xf3000000,
494 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
495 .mmu_version = 0xf3000000,
496 .mmu_bm = 0x00000000,
497 .mmu_ctpr_mask = 0xfffffffc,
498 .mmu_cxr_mask = 0x000000ff,
499 .mmu_sfsr_mask = 0xffffffff,
500 .mmu_trcr_mask = 0xffffffff,
501 .nwindows = 8,
502 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
503 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
504 CPU_FEATURE_CASA,
506 #endif
509 static const char * const feature_name[] = {
510 "float",
511 "float128",
512 "swap",
513 "mul",
514 "div",
515 "flush",
516 "fsqrt",
517 "fmul",
518 "vis1",
519 "vis2",
520 "fsmuld",
521 "hypv",
522 "cmt",
523 "gl",
526 static void print_features(FILE *f, fprintf_function cpu_fprintf,
527 uint32_t features, const char *prefix)
529 unsigned int i;
531 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
532 if (feature_name[i] && (features & (1 << i))) {
533 if (prefix) {
534 (*cpu_fprintf)(f, "%s", prefix);
536 (*cpu_fprintf)(f, "%s ", feature_name[i]);
541 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
543 unsigned int i;
545 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
546 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
547 *features |= 1 << i;
548 return;
551 error_report("CPU feature %s not found", flagname);
554 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
556 unsigned int i;
557 const sparc_def_t *def = NULL;
559 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
560 if (strcasecmp(name, sparc_defs[i].name) == 0) {
561 def = &sparc_defs[i];
564 if (!def) {
565 return -1;
567 memcpy(cpu_def, def, sizeof(*def));
568 return 0;
571 static void sparc_cpu_parse_features(CPUState *cs, char *features,
572 Error **errp)
574 SPARCCPU *cpu = SPARC_CPU(cs);
575 sparc_def_t *cpu_def = cpu->env.def;
576 char *featurestr;
577 uint32_t plus_features = 0;
578 uint32_t minus_features = 0;
579 uint64_t iu_version;
580 uint32_t fpu_version, mmu_version, nwindows;
582 featurestr = features ? strtok(features, ",") : NULL;
583 while (featurestr) {
584 char *val;
586 if (featurestr[0] == '+') {
587 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
588 } else if (featurestr[0] == '-') {
589 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
590 } else if ((val = strchr(featurestr, '='))) {
591 *val = 0; val++;
592 if (!strcmp(featurestr, "iu_version")) {
593 char *err;
595 iu_version = strtoll(val, &err, 0);
596 if (!*val || *err) {
597 error_setg(errp, "bad numerical value %s", val);
598 return;
600 cpu_def->iu_version = iu_version;
601 #ifdef DEBUG_FEATURES
602 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
603 #endif
604 } else if (!strcmp(featurestr, "fpu_version")) {
605 char *err;
607 fpu_version = strtol(val, &err, 0);
608 if (!*val || *err) {
609 error_setg(errp, "bad numerical value %s", val);
610 return;
612 cpu_def->fpu_version = fpu_version;
613 #ifdef DEBUG_FEATURES
614 fprintf(stderr, "fpu_version %x\n", fpu_version);
615 #endif
616 } else if (!strcmp(featurestr, "mmu_version")) {
617 char *err;
619 mmu_version = strtol(val, &err, 0);
620 if (!*val || *err) {
621 error_setg(errp, "bad numerical value %s", val);
622 return;
624 cpu_def->mmu_version = mmu_version;
625 #ifdef DEBUG_FEATURES
626 fprintf(stderr, "mmu_version %x\n", mmu_version);
627 #endif
628 } else if (!strcmp(featurestr, "nwindows")) {
629 char *err;
631 nwindows = strtol(val, &err, 0);
632 if (!*val || *err || nwindows > MAX_NWINDOWS ||
633 nwindows < MIN_NWINDOWS) {
634 error_setg(errp, "bad numerical value %s", val);
635 return;
637 cpu_def->nwindows = nwindows;
638 #ifdef DEBUG_FEATURES
639 fprintf(stderr, "nwindows %d\n", nwindows);
640 #endif
641 } else {
642 error_setg(errp, "unrecognized feature %s", featurestr);
643 return;
645 } else {
646 error_setg(errp, "feature string `%s' not in format "
647 "(+feature|-feature|feature=xyz)", featurestr);
648 return;
650 featurestr = strtok(NULL, ",");
652 cpu_def->features |= plus_features;
653 cpu_def->features &= ~minus_features;
654 #ifdef DEBUG_FEATURES
655 print_features(stderr, fprintf, cpu_def->features, NULL);
656 #endif
659 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
661 unsigned int i;
663 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
664 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
665 " FPU %08x MMU %08x NWINS %d ",
666 sparc_defs[i].name,
667 sparc_defs[i].iu_version,
668 sparc_defs[i].fpu_version,
669 sparc_defs[i].mmu_version,
670 sparc_defs[i].nwindows);
671 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
672 ~sparc_defs[i].features, "-");
673 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
674 sparc_defs[i].features, "+");
675 (*cpu_fprintf)(f, "\n");
677 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
678 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
679 (*cpu_fprintf)(f, "\n");
680 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
681 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
682 (*cpu_fprintf)(f, "\n");
683 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
684 "fpu_version mmu_version nwindows\n");
687 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
688 uint32_t cc)
690 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
691 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
692 cc & PSR_CARRY ? 'C' : '-');
695 #ifdef TARGET_SPARC64
696 #define REGS_PER_LINE 4
697 #else
698 #define REGS_PER_LINE 8
699 #endif
701 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
702 int flags)
704 SPARCCPU *cpu = SPARC_CPU(cs);
705 CPUSPARCState *env = &cpu->env;
706 int i, x;
708 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
709 env->npc);
711 for (i = 0; i < 8; i++) {
712 if (i % REGS_PER_LINE == 0) {
713 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
715 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
716 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
717 cpu_fprintf(f, "\n");
720 for (x = 0; x < 3; x++) {
721 for (i = 0; i < 8; i++) {
722 if (i % REGS_PER_LINE == 0) {
723 cpu_fprintf(f, "%%%c%d-%d: ",
724 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
725 i, i + REGS_PER_LINE - 1);
727 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
728 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
729 cpu_fprintf(f, "\n");
734 for (i = 0; i < TARGET_DPREGS; i++) {
735 if ((i & 3) == 0) {
736 cpu_fprintf(f, "%%f%02d: ", i * 2);
738 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
739 if ((i & 3) == 3) {
740 cpu_fprintf(f, "\n");
743 #ifdef TARGET_SPARC64
744 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
745 (unsigned)cpu_get_ccr(env));
746 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
747 cpu_fprintf(f, " xcc: ");
748 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
749 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
750 env->psrpil);
751 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
752 "cleanwin: %d cwp: %d\n",
753 env->cansave, env->canrestore, env->otherwin, env->wstate,
754 env->cleanwin, env->nwindows - 1 - env->cwp);
755 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
756 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
757 #else
758 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
759 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
760 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
761 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
762 env->wim);
763 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
764 env->fsr, env->y);
765 #endif
766 cpu_fprintf(f, "\n");
769 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
771 SPARCCPU *cpu = SPARC_CPU(cs);
773 cpu->env.pc = value;
774 cpu->env.npc = value + 4;
777 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
779 SPARCCPU *cpu = SPARC_CPU(cs);
781 cpu->env.pc = tb->pc;
782 cpu->env.npc = tb->cs_base;
785 static bool sparc_cpu_has_work(CPUState *cs)
787 SPARCCPU *cpu = SPARC_CPU(cs);
788 CPUSPARCState *env = &cpu->env;
790 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
791 cpu_interrupts_enabled(env);
794 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
796 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
797 #if defined(CONFIG_USER_ONLY)
798 SPARCCPU *cpu = SPARC_CPU(dev);
799 CPUSPARCState *env = &cpu->env;
801 if ((env->def->features & CPU_FEATURE_FLOAT)) {
802 env->def->features |= CPU_FEATURE_FLOAT128;
804 #endif
806 qemu_init_vcpu(CPU(dev));
808 scc->parent_realize(dev, errp);
811 static void sparc_cpu_initfn(Object *obj)
813 CPUState *cs = CPU(obj);
814 SPARCCPU *cpu = SPARC_CPU(obj);
815 CPUSPARCState *env = &cpu->env;
817 cs->env_ptr = env;
818 cpu_exec_init(cs, &error_abort);
820 if (tcg_enabled()) {
821 gen_intermediate_code_init(env);
825 static void sparc_cpu_uninitfn(Object *obj)
827 SPARCCPU *cpu = SPARC_CPU(obj);
828 CPUSPARCState *env = &cpu->env;
830 g_free(env->def);
833 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
835 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
836 CPUClass *cc = CPU_CLASS(oc);
837 DeviceClass *dc = DEVICE_CLASS(oc);
839 scc->parent_realize = dc->realize;
840 dc->realize = sparc_cpu_realizefn;
842 scc->parent_reset = cc->reset;
843 cc->reset = sparc_cpu_reset;
845 cc->has_work = sparc_cpu_has_work;
846 cc->do_interrupt = sparc_cpu_do_interrupt;
847 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
848 cc->dump_state = sparc_cpu_dump_state;
849 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
850 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
851 #endif
852 cc->set_pc = sparc_cpu_set_pc;
853 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
854 cc->gdb_read_register = sparc_cpu_gdb_read_register;
855 cc->gdb_write_register = sparc_cpu_gdb_write_register;
856 #ifdef CONFIG_USER_ONLY
857 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
858 #else
859 cc->do_unassigned_access = sparc_cpu_unassigned_access;
860 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
861 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
862 cc->vmsd = &vmstate_sparc_cpu;
863 #endif
864 cc->disas_set_info = cpu_sparc_disas_set_info;
866 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
867 cc->gdb_num_core_regs = 86;
868 #else
869 cc->gdb_num_core_regs = 72;
870 #endif
873 * Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
874 * the object in cpus -> dangling pointer after final
875 * object_unref().
877 dc->cannot_destroy_with_object_finalize_yet = true;
880 static const TypeInfo sparc_cpu_type_info = {
881 .name = TYPE_SPARC_CPU,
882 .parent = TYPE_CPU,
883 .instance_size = sizeof(SPARCCPU),
884 .instance_init = sparc_cpu_initfn,
885 .instance_finalize = sparc_cpu_uninitfn,
886 .abstract = false,
887 .class_size = sizeof(SPARCCPUClass),
888 .class_init = sparc_cpu_class_init,
891 static void sparc_cpu_register_types(void)
893 type_register_static(&sparc_cpu_type_info);
896 type_init(sparc_cpu_register_types)