pxb: cleanup
[qemu/ar7.git] / target-sparc / cpu.c
blobce903f8dfd643d480bcc0469dbe69e68cf5630bc
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 "cpu.h"
22 #include "qemu/error-report.h"
24 //#define DEBUG_FEATURES
26 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
28 /* CPUClass::reset() */
29 static void sparc_cpu_reset(CPUState *s)
31 SPARCCPU *cpu = SPARC_CPU(s);
32 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
33 CPUSPARCState *env = &cpu->env;
35 scc->parent_reset(s);
37 memset(env, 0, offsetof(CPUSPARCState, version));
38 tlb_flush(s, 1);
39 env->cwp = 0;
40 #ifndef TARGET_SPARC64
41 env->wim = 1;
42 #endif
43 env->regwptr = env->regbase + (env->cwp * 16);
44 CC_OP = CC_OP_FLAGS;
45 #if defined(CONFIG_USER_ONLY)
46 #ifdef TARGET_SPARC64
47 env->cleanwin = env->nwindows - 2;
48 env->cansave = env->nwindows - 2;
49 env->pstate = PS_RMO | PS_PEF | PS_IE;
50 env->asi = 0x82; /* Primary no-fault */
51 #endif
52 #else
53 #if !defined(TARGET_SPARC64)
54 env->psret = 0;
55 env->psrs = 1;
56 env->psrps = 1;
57 #endif
58 #ifdef TARGET_SPARC64
59 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
60 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
61 env->tl = env->maxtl;
62 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
63 env->lsu = 0;
64 #else
65 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
66 env->mmuregs[0] |= env->def->mmu_bm;
67 #endif
68 env->pc = 0;
69 env->npc = env->pc + 4;
70 #endif
71 env->cache_control = 0;
74 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
76 if (interrupt_request & CPU_INTERRUPT_HARD) {
77 SPARCCPU *cpu = SPARC_CPU(cs);
78 CPUSPARCState *env = &cpu->env;
80 if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
81 int pil = env->interrupt_index & 0xf;
82 int type = env->interrupt_index & 0xf0;
84 if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
85 cs->exception_index = env->interrupt_index;
86 sparc_cpu_do_interrupt(cs);
87 return true;
91 return false;
94 static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
96 info->print_insn = print_insn_sparc;
97 #ifdef TARGET_SPARC64
98 info->mach = bfd_mach_sparc_v9b;
99 #endif
102 static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
104 CPUClass *cc = CPU_GET_CLASS(cpu);
105 CPUSPARCState *env = &cpu->env;
106 char *s = g_strdup(cpu_model);
107 char *featurestr, *name = strtok(s, ",");
108 sparc_def_t def1, *def = &def1;
109 Error *err = NULL;
111 if (cpu_sparc_find_by_name(def, name) < 0) {
112 g_free(s);
113 return -1;
116 env->def = g_new0(sparc_def_t, 1);
117 memcpy(env->def, def, sizeof(*def));
119 featurestr = strtok(NULL, ",");
120 cc->parse_features(CPU(cpu), featurestr, &err);
121 g_free(s);
122 if (err) {
123 error_report_err(err);
124 return -1;
127 env->version = def->iu_version;
128 env->fsr = def->fpu_version;
129 env->nwindows = def->nwindows;
130 #if !defined(TARGET_SPARC64)
131 env->mmuregs[0] |= def->mmu_version;
132 cpu_sparc_set_id(env, 0);
133 env->mxccregs[7] |= def->mxcc_version;
134 #else
135 env->mmu_version = def->mmu_version;
136 env->maxtl = def->maxtl;
137 env->version |= def->maxtl << 8;
138 env->version |= def->nwindows - 1;
139 #endif
140 return 0;
143 SPARCCPU *cpu_sparc_init(const char *cpu_model)
145 SPARCCPU *cpu;
147 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
149 if (cpu_sparc_register(cpu, cpu_model) < 0) {
150 object_unref(OBJECT(cpu));
151 return NULL;
154 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
156 return cpu;
159 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
161 #if !defined(TARGET_SPARC64)
162 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
163 #endif
166 static const sparc_def_t sparc_defs[] = {
167 #ifdef TARGET_SPARC64
169 .name = "Fujitsu Sparc64",
170 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
171 .fpu_version = 0x00000000,
172 .mmu_version = mmu_us_12,
173 .nwindows = 4,
174 .maxtl = 4,
175 .features = CPU_DEFAULT_FEATURES,
178 .name = "Fujitsu Sparc64 III",
179 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
180 .fpu_version = 0x00000000,
181 .mmu_version = mmu_us_12,
182 .nwindows = 5,
183 .maxtl = 4,
184 .features = CPU_DEFAULT_FEATURES,
187 .name = "Fujitsu Sparc64 IV",
188 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
189 .fpu_version = 0x00000000,
190 .mmu_version = mmu_us_12,
191 .nwindows = 8,
192 .maxtl = 5,
193 .features = CPU_DEFAULT_FEATURES,
196 .name = "Fujitsu Sparc64 V",
197 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
198 .fpu_version = 0x00000000,
199 .mmu_version = mmu_us_12,
200 .nwindows = 8,
201 .maxtl = 5,
202 .features = CPU_DEFAULT_FEATURES,
205 .name = "TI UltraSparc I",
206 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
207 .fpu_version = 0x00000000,
208 .mmu_version = mmu_us_12,
209 .nwindows = 8,
210 .maxtl = 5,
211 .features = CPU_DEFAULT_FEATURES,
214 .name = "TI UltraSparc II",
215 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
216 .fpu_version = 0x00000000,
217 .mmu_version = mmu_us_12,
218 .nwindows = 8,
219 .maxtl = 5,
220 .features = CPU_DEFAULT_FEATURES,
223 .name = "TI UltraSparc IIi",
224 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
225 .fpu_version = 0x00000000,
226 .mmu_version = mmu_us_12,
227 .nwindows = 8,
228 .maxtl = 5,
229 .features = CPU_DEFAULT_FEATURES,
232 .name = "TI UltraSparc IIe",
233 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
234 .fpu_version = 0x00000000,
235 .mmu_version = mmu_us_12,
236 .nwindows = 8,
237 .maxtl = 5,
238 .features = CPU_DEFAULT_FEATURES,
241 .name = "Sun UltraSparc III",
242 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
243 .fpu_version = 0x00000000,
244 .mmu_version = mmu_us_12,
245 .nwindows = 8,
246 .maxtl = 5,
247 .features = CPU_DEFAULT_FEATURES,
250 .name = "Sun UltraSparc III Cu",
251 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
252 .fpu_version = 0x00000000,
253 .mmu_version = mmu_us_3,
254 .nwindows = 8,
255 .maxtl = 5,
256 .features = CPU_DEFAULT_FEATURES,
259 .name = "Sun UltraSparc IIIi",
260 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
261 .fpu_version = 0x00000000,
262 .mmu_version = mmu_us_12,
263 .nwindows = 8,
264 .maxtl = 5,
265 .features = CPU_DEFAULT_FEATURES,
268 .name = "Sun UltraSparc IV",
269 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
270 .fpu_version = 0x00000000,
271 .mmu_version = mmu_us_4,
272 .nwindows = 8,
273 .maxtl = 5,
274 .features = CPU_DEFAULT_FEATURES,
277 .name = "Sun UltraSparc IV+",
278 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
279 .fpu_version = 0x00000000,
280 .mmu_version = mmu_us_12,
281 .nwindows = 8,
282 .maxtl = 5,
283 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
286 .name = "Sun UltraSparc IIIi+",
287 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
288 .fpu_version = 0x00000000,
289 .mmu_version = mmu_us_3,
290 .nwindows = 8,
291 .maxtl = 5,
292 .features = CPU_DEFAULT_FEATURES,
295 .name = "Sun UltraSparc T1",
296 /* defined in sparc_ifu_fdp.v and ctu.h */
297 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
298 .fpu_version = 0x00000000,
299 .mmu_version = mmu_sun4v,
300 .nwindows = 8,
301 .maxtl = 6,
302 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
303 | CPU_FEATURE_GL,
306 .name = "Sun UltraSparc T2",
307 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
308 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
309 .fpu_version = 0x00000000,
310 .mmu_version = mmu_sun4v,
311 .nwindows = 8,
312 .maxtl = 6,
313 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
314 | CPU_FEATURE_GL,
317 .name = "NEC UltraSparc I",
318 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
319 .fpu_version = 0x00000000,
320 .mmu_version = mmu_us_12,
321 .nwindows = 8,
322 .maxtl = 5,
323 .features = CPU_DEFAULT_FEATURES,
325 #else
327 .name = "Fujitsu MB86904",
328 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
329 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
330 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
331 .mmu_bm = 0x00004000,
332 .mmu_ctpr_mask = 0x00ffffc0,
333 .mmu_cxr_mask = 0x000000ff,
334 .mmu_sfsr_mask = 0x00016fff,
335 .mmu_trcr_mask = 0x00ffffff,
336 .nwindows = 8,
337 .features = CPU_DEFAULT_FEATURES,
340 .name = "Fujitsu MB86907",
341 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
342 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
343 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
344 .mmu_bm = 0x00004000,
345 .mmu_ctpr_mask = 0xffffffc0,
346 .mmu_cxr_mask = 0x000000ff,
347 .mmu_sfsr_mask = 0x00016fff,
348 .mmu_trcr_mask = 0xffffffff,
349 .nwindows = 8,
350 .features = CPU_DEFAULT_FEATURES,
353 .name = "TI MicroSparc I",
354 .iu_version = 0x41000000,
355 .fpu_version = 4 << 17,
356 .mmu_version = 0x41000000,
357 .mmu_bm = 0x00004000,
358 .mmu_ctpr_mask = 0x007ffff0,
359 .mmu_cxr_mask = 0x0000003f,
360 .mmu_sfsr_mask = 0x00016fff,
361 .mmu_trcr_mask = 0x0000003f,
362 .nwindows = 7,
363 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
364 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
365 CPU_FEATURE_FMUL,
368 .name = "TI MicroSparc II",
369 .iu_version = 0x42000000,
370 .fpu_version = 4 << 17,
371 .mmu_version = 0x02000000,
372 .mmu_bm = 0x00004000,
373 .mmu_ctpr_mask = 0x00ffffc0,
374 .mmu_cxr_mask = 0x000000ff,
375 .mmu_sfsr_mask = 0x00016fff,
376 .mmu_trcr_mask = 0x00ffffff,
377 .nwindows = 8,
378 .features = CPU_DEFAULT_FEATURES,
381 .name = "TI MicroSparc IIep",
382 .iu_version = 0x42000000,
383 .fpu_version = 4 << 17,
384 .mmu_version = 0x04000000,
385 .mmu_bm = 0x00004000,
386 .mmu_ctpr_mask = 0x00ffffc0,
387 .mmu_cxr_mask = 0x000000ff,
388 .mmu_sfsr_mask = 0x00016bff,
389 .mmu_trcr_mask = 0x00ffffff,
390 .nwindows = 8,
391 .features = CPU_DEFAULT_FEATURES,
394 .name = "TI SuperSparc 40", /* STP1020NPGA */
395 .iu_version = 0x41000000, /* SuperSPARC 2.x */
396 .fpu_version = 0 << 17,
397 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
398 .mmu_bm = 0x00002000,
399 .mmu_ctpr_mask = 0xffffffc0,
400 .mmu_cxr_mask = 0x0000ffff,
401 .mmu_sfsr_mask = 0xffffffff,
402 .mmu_trcr_mask = 0xffffffff,
403 .nwindows = 8,
404 .features = CPU_DEFAULT_FEATURES,
407 .name = "TI SuperSparc 50", /* STP1020PGA */
408 .iu_version = 0x40000000, /* SuperSPARC 3.x */
409 .fpu_version = 0 << 17,
410 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
411 .mmu_bm = 0x00002000,
412 .mmu_ctpr_mask = 0xffffffc0,
413 .mmu_cxr_mask = 0x0000ffff,
414 .mmu_sfsr_mask = 0xffffffff,
415 .mmu_trcr_mask = 0xffffffff,
416 .nwindows = 8,
417 .features = CPU_DEFAULT_FEATURES,
420 .name = "TI SuperSparc 51",
421 .iu_version = 0x40000000, /* SuperSPARC 3.x */
422 .fpu_version = 0 << 17,
423 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
424 .mmu_bm = 0x00002000,
425 .mmu_ctpr_mask = 0xffffffc0,
426 .mmu_cxr_mask = 0x0000ffff,
427 .mmu_sfsr_mask = 0xffffffff,
428 .mmu_trcr_mask = 0xffffffff,
429 .mxcc_version = 0x00000104,
430 .nwindows = 8,
431 .features = CPU_DEFAULT_FEATURES,
434 .name = "TI SuperSparc 60", /* STP1020APGA */
435 .iu_version = 0x40000000, /* SuperSPARC 3.x */
436 .fpu_version = 0 << 17,
437 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
438 .mmu_bm = 0x00002000,
439 .mmu_ctpr_mask = 0xffffffc0,
440 .mmu_cxr_mask = 0x0000ffff,
441 .mmu_sfsr_mask = 0xffffffff,
442 .mmu_trcr_mask = 0xffffffff,
443 .nwindows = 8,
444 .features = CPU_DEFAULT_FEATURES,
447 .name = "TI SuperSparc 61",
448 .iu_version = 0x44000000, /* SuperSPARC 3.x */
449 .fpu_version = 0 << 17,
450 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
451 .mmu_bm = 0x00002000,
452 .mmu_ctpr_mask = 0xffffffc0,
453 .mmu_cxr_mask = 0x0000ffff,
454 .mmu_sfsr_mask = 0xffffffff,
455 .mmu_trcr_mask = 0xffffffff,
456 .mxcc_version = 0x00000104,
457 .nwindows = 8,
458 .features = CPU_DEFAULT_FEATURES,
461 .name = "TI SuperSparc II",
462 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
463 .fpu_version = 0 << 17,
464 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
465 .mmu_bm = 0x00002000,
466 .mmu_ctpr_mask = 0xffffffc0,
467 .mmu_cxr_mask = 0x0000ffff,
468 .mmu_sfsr_mask = 0xffffffff,
469 .mmu_trcr_mask = 0xffffffff,
470 .mxcc_version = 0x00000104,
471 .nwindows = 8,
472 .features = CPU_DEFAULT_FEATURES,
475 .name = "LEON2",
476 .iu_version = 0xf2000000,
477 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
478 .mmu_version = 0xf2000000,
479 .mmu_bm = 0x00004000,
480 .mmu_ctpr_mask = 0x007ffff0,
481 .mmu_cxr_mask = 0x0000003f,
482 .mmu_sfsr_mask = 0xffffffff,
483 .mmu_trcr_mask = 0xffffffff,
484 .nwindows = 8,
485 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
488 .name = "LEON3",
489 .iu_version = 0xf3000000,
490 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
491 .mmu_version = 0xf3000000,
492 .mmu_bm = 0x00000000,
493 .mmu_ctpr_mask = 0xfffffffc,
494 .mmu_cxr_mask = 0x000000ff,
495 .mmu_sfsr_mask = 0xffffffff,
496 .mmu_trcr_mask = 0xffffffff,
497 .nwindows = 8,
498 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
499 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
500 CPU_FEATURE_CASA,
502 #endif
505 static const char * const feature_name[] = {
506 "float",
507 "float128",
508 "swap",
509 "mul",
510 "div",
511 "flush",
512 "fsqrt",
513 "fmul",
514 "vis1",
515 "vis2",
516 "fsmuld",
517 "hypv",
518 "cmt",
519 "gl",
522 static void print_features(FILE *f, fprintf_function cpu_fprintf,
523 uint32_t features, const char *prefix)
525 unsigned int i;
527 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
528 if (feature_name[i] && (features & (1 << i))) {
529 if (prefix) {
530 (*cpu_fprintf)(f, "%s", prefix);
532 (*cpu_fprintf)(f, "%s ", feature_name[i]);
537 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
539 unsigned int i;
541 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
542 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
543 *features |= 1 << i;
544 return;
547 error_report("CPU feature %s not found", flagname);
550 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
552 unsigned int i;
553 const sparc_def_t *def = NULL;
555 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
556 if (strcasecmp(name, sparc_defs[i].name) == 0) {
557 def = &sparc_defs[i];
560 if (!def) {
561 return -1;
563 memcpy(cpu_def, def, sizeof(*def));
564 return 0;
567 static void sparc_cpu_parse_features(CPUState *cs, char *features,
568 Error **errp)
570 SPARCCPU *cpu = SPARC_CPU(cs);
571 sparc_def_t *cpu_def = cpu->env.def;
572 char *featurestr;
573 uint32_t plus_features = 0;
574 uint32_t minus_features = 0;
575 uint64_t iu_version;
576 uint32_t fpu_version, mmu_version, nwindows;
578 featurestr = features ? strtok(features, ",") : NULL;
579 while (featurestr) {
580 char *val;
582 if (featurestr[0] == '+') {
583 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
584 } else if (featurestr[0] == '-') {
585 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
586 } else if ((val = strchr(featurestr, '='))) {
587 *val = 0; val++;
588 if (!strcmp(featurestr, "iu_version")) {
589 char *err;
591 iu_version = strtoll(val, &err, 0);
592 if (!*val || *err) {
593 error_setg(errp, "bad numerical value %s", val);
594 return;
596 cpu_def->iu_version = iu_version;
597 #ifdef DEBUG_FEATURES
598 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
599 #endif
600 } else if (!strcmp(featurestr, "fpu_version")) {
601 char *err;
603 fpu_version = strtol(val, &err, 0);
604 if (!*val || *err) {
605 error_setg(errp, "bad numerical value %s", val);
606 return;
608 cpu_def->fpu_version = fpu_version;
609 #ifdef DEBUG_FEATURES
610 fprintf(stderr, "fpu_version %x\n", fpu_version);
611 #endif
612 } else if (!strcmp(featurestr, "mmu_version")) {
613 char *err;
615 mmu_version = strtol(val, &err, 0);
616 if (!*val || *err) {
617 error_setg(errp, "bad numerical value %s", val);
618 return;
620 cpu_def->mmu_version = mmu_version;
621 #ifdef DEBUG_FEATURES
622 fprintf(stderr, "mmu_version %x\n", mmu_version);
623 #endif
624 } else if (!strcmp(featurestr, "nwindows")) {
625 char *err;
627 nwindows = strtol(val, &err, 0);
628 if (!*val || *err || nwindows > MAX_NWINDOWS ||
629 nwindows < MIN_NWINDOWS) {
630 error_setg(errp, "bad numerical value %s", val);
631 return;
633 cpu_def->nwindows = nwindows;
634 #ifdef DEBUG_FEATURES
635 fprintf(stderr, "nwindows %d\n", nwindows);
636 #endif
637 } else {
638 error_setg(errp, "unrecognized feature %s", featurestr);
639 return;
641 } else {
642 error_setg(errp, "feature string `%s' not in format "
643 "(+feature|-feature|feature=xyz)", featurestr);
644 return;
646 featurestr = strtok(NULL, ",");
648 cpu_def->features |= plus_features;
649 cpu_def->features &= ~minus_features;
650 #ifdef DEBUG_FEATURES
651 print_features(stderr, fprintf, cpu_def->features, NULL);
652 #endif
655 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
657 unsigned int i;
659 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
660 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
661 " FPU %08x MMU %08x NWINS %d ",
662 sparc_defs[i].name,
663 sparc_defs[i].iu_version,
664 sparc_defs[i].fpu_version,
665 sparc_defs[i].mmu_version,
666 sparc_defs[i].nwindows);
667 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
668 ~sparc_defs[i].features, "-");
669 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
670 sparc_defs[i].features, "+");
671 (*cpu_fprintf)(f, "\n");
673 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
674 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
675 (*cpu_fprintf)(f, "\n");
676 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
677 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
678 (*cpu_fprintf)(f, "\n");
679 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
680 "fpu_version mmu_version nwindows\n");
683 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
684 uint32_t cc)
686 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
687 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
688 cc & PSR_CARRY ? 'C' : '-');
691 #ifdef TARGET_SPARC64
692 #define REGS_PER_LINE 4
693 #else
694 #define REGS_PER_LINE 8
695 #endif
697 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
698 int flags)
700 SPARCCPU *cpu = SPARC_CPU(cs);
701 CPUSPARCState *env = &cpu->env;
702 int i, x;
704 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
705 env->npc);
707 for (i = 0; i < 8; i++) {
708 if (i % REGS_PER_LINE == 0) {
709 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
711 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
712 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
713 cpu_fprintf(f, "\n");
716 for (x = 0; x < 3; x++) {
717 for (i = 0; i < 8; i++) {
718 if (i % REGS_PER_LINE == 0) {
719 cpu_fprintf(f, "%%%c%d-%d: ",
720 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
721 i, i + REGS_PER_LINE - 1);
723 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
724 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
725 cpu_fprintf(f, "\n");
730 for (i = 0; i < TARGET_DPREGS; i++) {
731 if ((i & 3) == 0) {
732 cpu_fprintf(f, "%%f%02d: ", i * 2);
734 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
735 if ((i & 3) == 3) {
736 cpu_fprintf(f, "\n");
739 #ifdef TARGET_SPARC64
740 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
741 (unsigned)cpu_get_ccr(env));
742 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
743 cpu_fprintf(f, " xcc: ");
744 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
745 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
746 env->psrpil);
747 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
748 "cleanwin: %d cwp: %d\n",
749 env->cansave, env->canrestore, env->otherwin, env->wstate,
750 env->cleanwin, env->nwindows - 1 - env->cwp);
751 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
752 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
753 #else
754 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
755 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
756 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
757 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
758 env->wim);
759 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
760 env->fsr, env->y);
761 #endif
762 cpu_fprintf(f, "\n");
765 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
767 SPARCCPU *cpu = SPARC_CPU(cs);
769 cpu->env.pc = value;
770 cpu->env.npc = value + 4;
773 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
775 SPARCCPU *cpu = SPARC_CPU(cs);
777 cpu->env.pc = tb->pc;
778 cpu->env.npc = tb->cs_base;
781 static bool sparc_cpu_has_work(CPUState *cs)
783 SPARCCPU *cpu = SPARC_CPU(cs);
784 CPUSPARCState *env = &cpu->env;
786 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
787 cpu_interrupts_enabled(env);
790 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
792 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
793 #if defined(CONFIG_USER_ONLY)
794 SPARCCPU *cpu = SPARC_CPU(dev);
795 CPUSPARCState *env = &cpu->env;
797 if ((env->def->features & CPU_FEATURE_FLOAT)) {
798 env->def->features |= CPU_FEATURE_FLOAT128;
800 #endif
802 qemu_init_vcpu(CPU(dev));
804 scc->parent_realize(dev, errp);
807 static void sparc_cpu_initfn(Object *obj)
809 CPUState *cs = CPU(obj);
810 SPARCCPU *cpu = SPARC_CPU(obj);
811 CPUSPARCState *env = &cpu->env;
813 cs->env_ptr = env;
814 cpu_exec_init(cs, &error_abort);
816 if (tcg_enabled()) {
817 gen_intermediate_code_init(env);
821 static void sparc_cpu_uninitfn(Object *obj)
823 SPARCCPU *cpu = SPARC_CPU(obj);
824 CPUSPARCState *env = &cpu->env;
826 g_free(env->def);
829 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
831 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
832 CPUClass *cc = CPU_CLASS(oc);
833 DeviceClass *dc = DEVICE_CLASS(oc);
835 scc->parent_realize = dc->realize;
836 dc->realize = sparc_cpu_realizefn;
838 scc->parent_reset = cc->reset;
839 cc->reset = sparc_cpu_reset;
841 cc->parse_features = sparc_cpu_parse_features;
842 cc->has_work = sparc_cpu_has_work;
843 cc->do_interrupt = sparc_cpu_do_interrupt;
844 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
845 cc->dump_state = sparc_cpu_dump_state;
846 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
847 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
848 #endif
849 cc->set_pc = sparc_cpu_set_pc;
850 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
851 cc->gdb_read_register = sparc_cpu_gdb_read_register;
852 cc->gdb_write_register = sparc_cpu_gdb_write_register;
853 #ifdef CONFIG_USER_ONLY
854 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
855 #else
856 cc->do_unassigned_access = sparc_cpu_unassigned_access;
857 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
858 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
859 cc->vmsd = &vmstate_sparc_cpu;
860 #endif
861 cc->disas_set_info = cpu_sparc_disas_set_info;
863 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
864 cc->gdb_num_core_regs = 86;
865 #else
866 cc->gdb_num_core_regs = 72;
867 #endif
870 * Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
871 * the object in cpus -> dangling pointer after final
872 * object_unref().
874 dc->cannot_destroy_with_object_finalize_yet = true;
877 static const TypeInfo sparc_cpu_type_info = {
878 .name = TYPE_SPARC_CPU,
879 .parent = TYPE_CPU,
880 .instance_size = sizeof(SPARCCPU),
881 .instance_init = sparc_cpu_initfn,
882 .instance_finalize = sparc_cpu_uninitfn,
883 .abstract = false,
884 .class_size = sizeof(SPARCCPUClass),
885 .class_init = sparc_cpu_class_init,
888 static void sparc_cpu_register_types(void)
890 type_register_static(&sparc_cpu_type_info);
893 type_init(sparc_cpu_register_types)