qapi: drop the sentinel in enum array
[qemu/armbru.git] / target / sparc / cpu.c
blobd606eb53f4cc330acee2dd3e234a9aeecaee28f1
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, 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 sparc_cpu_parse_features(CPUState *cs, char *features,
108 Error **errp);
110 static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
112 CPUSPARCState *env = &cpu->env;
113 char *s = g_strdup(cpu_model);
114 char *featurestr, *name = strtok(s, ",");
115 sparc_def_t def1, *def = &def1;
116 Error *err = NULL;
118 if (cpu_sparc_find_by_name(def, name) < 0) {
119 g_free(s);
120 return -1;
123 env->def = g_memdup(def, sizeof(*def));
125 featurestr = strtok(NULL, ",");
126 sparc_cpu_parse_features(CPU(cpu), featurestr, &err);
127 g_free(s);
128 if (err) {
129 error_report_err(err);
130 return -1;
133 env->version = def->iu_version;
134 env->fsr = def->fpu_version;
135 env->nwindows = def->nwindows;
136 #if !defined(TARGET_SPARC64)
137 env->mmuregs[0] |= def->mmu_version;
138 cpu_sparc_set_id(env, 0);
139 env->mxccregs[7] |= def->mxcc_version;
140 #else
141 env->mmu_version = def->mmu_version;
142 env->maxtl = def->maxtl;
143 env->version |= def->maxtl << 8;
144 env->version |= def->nwindows - 1;
145 #endif
146 return 0;
149 SPARCCPU *cpu_sparc_init(const char *cpu_model)
151 SPARCCPU *cpu;
153 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
155 if (cpu_sparc_register(cpu, cpu_model) < 0) {
156 object_unref(OBJECT(cpu));
157 return NULL;
160 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
162 return cpu;
165 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
167 #if !defined(TARGET_SPARC64)
168 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
169 #endif
172 static const sparc_def_t sparc_defs[] = {
173 #ifdef TARGET_SPARC64
175 .name = "Fujitsu Sparc64",
176 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
177 .fpu_version = 0x00000000,
178 .mmu_version = mmu_us_12,
179 .nwindows = 4,
180 .maxtl = 4,
181 .features = CPU_DEFAULT_FEATURES,
184 .name = "Fujitsu Sparc64 III",
185 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
186 .fpu_version = 0x00000000,
187 .mmu_version = mmu_us_12,
188 .nwindows = 5,
189 .maxtl = 4,
190 .features = CPU_DEFAULT_FEATURES,
193 .name = "Fujitsu Sparc64 IV",
194 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
195 .fpu_version = 0x00000000,
196 .mmu_version = mmu_us_12,
197 .nwindows = 8,
198 .maxtl = 5,
199 .features = CPU_DEFAULT_FEATURES,
202 .name = "Fujitsu Sparc64 V",
203 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
204 .fpu_version = 0x00000000,
205 .mmu_version = mmu_us_12,
206 .nwindows = 8,
207 .maxtl = 5,
208 .features = CPU_DEFAULT_FEATURES,
211 .name = "TI UltraSparc I",
212 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
213 .fpu_version = 0x00000000,
214 .mmu_version = mmu_us_12,
215 .nwindows = 8,
216 .maxtl = 5,
217 .features = CPU_DEFAULT_FEATURES,
220 .name = "TI UltraSparc II",
221 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
222 .fpu_version = 0x00000000,
223 .mmu_version = mmu_us_12,
224 .nwindows = 8,
225 .maxtl = 5,
226 .features = CPU_DEFAULT_FEATURES,
229 .name = "TI UltraSparc IIi",
230 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
231 .fpu_version = 0x00000000,
232 .mmu_version = mmu_us_12,
233 .nwindows = 8,
234 .maxtl = 5,
235 .features = CPU_DEFAULT_FEATURES,
238 .name = "TI UltraSparc IIe",
239 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
240 .fpu_version = 0x00000000,
241 .mmu_version = mmu_us_12,
242 .nwindows = 8,
243 .maxtl = 5,
244 .features = CPU_DEFAULT_FEATURES,
247 .name = "Sun UltraSparc III",
248 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
249 .fpu_version = 0x00000000,
250 .mmu_version = mmu_us_12,
251 .nwindows = 8,
252 .maxtl = 5,
253 .features = CPU_DEFAULT_FEATURES,
256 .name = "Sun UltraSparc III Cu",
257 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
258 .fpu_version = 0x00000000,
259 .mmu_version = mmu_us_3,
260 .nwindows = 8,
261 .maxtl = 5,
262 .features = CPU_DEFAULT_FEATURES,
265 .name = "Sun UltraSparc IIIi",
266 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
267 .fpu_version = 0x00000000,
268 .mmu_version = mmu_us_12,
269 .nwindows = 8,
270 .maxtl = 5,
271 .features = CPU_DEFAULT_FEATURES,
274 .name = "Sun UltraSparc IV",
275 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
276 .fpu_version = 0x00000000,
277 .mmu_version = mmu_us_4,
278 .nwindows = 8,
279 .maxtl = 5,
280 .features = CPU_DEFAULT_FEATURES,
283 .name = "Sun UltraSparc IV+",
284 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
285 .fpu_version = 0x00000000,
286 .mmu_version = mmu_us_12,
287 .nwindows = 8,
288 .maxtl = 5,
289 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
292 .name = "Sun UltraSparc IIIi+",
293 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
294 .fpu_version = 0x00000000,
295 .mmu_version = mmu_us_3,
296 .nwindows = 8,
297 .maxtl = 5,
298 .features = CPU_DEFAULT_FEATURES,
301 .name = "Sun UltraSparc T1",
302 /* defined in sparc_ifu_fdp.v and ctu.h */
303 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
304 .fpu_version = 0x00000000,
305 .mmu_version = mmu_sun4v,
306 .nwindows = 8,
307 .maxtl = 6,
308 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
309 | CPU_FEATURE_GL,
312 .name = "Sun UltraSparc T2",
313 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
314 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
315 .fpu_version = 0x00000000,
316 .mmu_version = mmu_sun4v,
317 .nwindows = 8,
318 .maxtl = 6,
319 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
320 | CPU_FEATURE_GL,
323 .name = "NEC UltraSparc I",
324 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
325 .fpu_version = 0x00000000,
326 .mmu_version = mmu_us_12,
327 .nwindows = 8,
328 .maxtl = 5,
329 .features = CPU_DEFAULT_FEATURES,
331 #else
333 .name = "Fujitsu MB86904",
334 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
335 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
336 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
337 .mmu_bm = 0x00004000,
338 .mmu_ctpr_mask = 0x00ffffc0,
339 .mmu_cxr_mask = 0x000000ff,
340 .mmu_sfsr_mask = 0x00016fff,
341 .mmu_trcr_mask = 0x00ffffff,
342 .nwindows = 8,
343 .features = CPU_DEFAULT_FEATURES,
346 .name = "Fujitsu MB86907",
347 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
348 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
349 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
350 .mmu_bm = 0x00004000,
351 .mmu_ctpr_mask = 0xffffffc0,
352 .mmu_cxr_mask = 0x000000ff,
353 .mmu_sfsr_mask = 0x00016fff,
354 .mmu_trcr_mask = 0xffffffff,
355 .nwindows = 8,
356 .features = CPU_DEFAULT_FEATURES,
359 .name = "TI MicroSparc I",
360 .iu_version = 0x41000000,
361 .fpu_version = 4 << 17,
362 .mmu_version = 0x41000000,
363 .mmu_bm = 0x00004000,
364 .mmu_ctpr_mask = 0x007ffff0,
365 .mmu_cxr_mask = 0x0000003f,
366 .mmu_sfsr_mask = 0x00016fff,
367 .mmu_trcr_mask = 0x0000003f,
368 .nwindows = 7,
369 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
370 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
371 CPU_FEATURE_FMUL,
374 .name = "TI MicroSparc II",
375 .iu_version = 0x42000000,
376 .fpu_version = 4 << 17,
377 .mmu_version = 0x02000000,
378 .mmu_bm = 0x00004000,
379 .mmu_ctpr_mask = 0x00ffffc0,
380 .mmu_cxr_mask = 0x000000ff,
381 .mmu_sfsr_mask = 0x00016fff,
382 .mmu_trcr_mask = 0x00ffffff,
383 .nwindows = 8,
384 .features = CPU_DEFAULT_FEATURES,
387 .name = "TI MicroSparc IIep",
388 .iu_version = 0x42000000,
389 .fpu_version = 4 << 17,
390 .mmu_version = 0x04000000,
391 .mmu_bm = 0x00004000,
392 .mmu_ctpr_mask = 0x00ffffc0,
393 .mmu_cxr_mask = 0x000000ff,
394 .mmu_sfsr_mask = 0x00016bff,
395 .mmu_trcr_mask = 0x00ffffff,
396 .nwindows = 8,
397 .features = CPU_DEFAULT_FEATURES,
400 .name = "TI SuperSparc 40", /* STP1020NPGA */
401 .iu_version = 0x41000000, /* SuperSPARC 2.x */
402 .fpu_version = 0 << 17,
403 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
404 .mmu_bm = 0x00002000,
405 .mmu_ctpr_mask = 0xffffffc0,
406 .mmu_cxr_mask = 0x0000ffff,
407 .mmu_sfsr_mask = 0xffffffff,
408 .mmu_trcr_mask = 0xffffffff,
409 .nwindows = 8,
410 .features = CPU_DEFAULT_FEATURES,
413 .name = "TI SuperSparc 50", /* STP1020PGA */
414 .iu_version = 0x40000000, /* SuperSPARC 3.x */
415 .fpu_version = 0 << 17,
416 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
417 .mmu_bm = 0x00002000,
418 .mmu_ctpr_mask = 0xffffffc0,
419 .mmu_cxr_mask = 0x0000ffff,
420 .mmu_sfsr_mask = 0xffffffff,
421 .mmu_trcr_mask = 0xffffffff,
422 .nwindows = 8,
423 .features = CPU_DEFAULT_FEATURES,
426 .name = "TI SuperSparc 51",
427 .iu_version = 0x40000000, /* SuperSPARC 3.x */
428 .fpu_version = 0 << 17,
429 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
430 .mmu_bm = 0x00002000,
431 .mmu_ctpr_mask = 0xffffffc0,
432 .mmu_cxr_mask = 0x0000ffff,
433 .mmu_sfsr_mask = 0xffffffff,
434 .mmu_trcr_mask = 0xffffffff,
435 .mxcc_version = 0x00000104,
436 .nwindows = 8,
437 .features = CPU_DEFAULT_FEATURES,
440 .name = "TI SuperSparc 60", /* STP1020APGA */
441 .iu_version = 0x40000000, /* SuperSPARC 3.x */
442 .fpu_version = 0 << 17,
443 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
444 .mmu_bm = 0x00002000,
445 .mmu_ctpr_mask = 0xffffffc0,
446 .mmu_cxr_mask = 0x0000ffff,
447 .mmu_sfsr_mask = 0xffffffff,
448 .mmu_trcr_mask = 0xffffffff,
449 .nwindows = 8,
450 .features = CPU_DEFAULT_FEATURES,
453 .name = "TI SuperSparc 61",
454 .iu_version = 0x44000000, /* SuperSPARC 3.x */
455 .fpu_version = 0 << 17,
456 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
457 .mmu_bm = 0x00002000,
458 .mmu_ctpr_mask = 0xffffffc0,
459 .mmu_cxr_mask = 0x0000ffff,
460 .mmu_sfsr_mask = 0xffffffff,
461 .mmu_trcr_mask = 0xffffffff,
462 .mxcc_version = 0x00000104,
463 .nwindows = 8,
464 .features = CPU_DEFAULT_FEATURES,
467 .name = "TI SuperSparc II",
468 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
469 .fpu_version = 0 << 17,
470 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
471 .mmu_bm = 0x00002000,
472 .mmu_ctpr_mask = 0xffffffc0,
473 .mmu_cxr_mask = 0x0000ffff,
474 .mmu_sfsr_mask = 0xffffffff,
475 .mmu_trcr_mask = 0xffffffff,
476 .mxcc_version = 0x00000104,
477 .nwindows = 8,
478 .features = CPU_DEFAULT_FEATURES,
481 .name = "LEON2",
482 .iu_version = 0xf2000000,
483 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
484 .mmu_version = 0xf2000000,
485 .mmu_bm = 0x00004000,
486 .mmu_ctpr_mask = 0x007ffff0,
487 .mmu_cxr_mask = 0x0000003f,
488 .mmu_sfsr_mask = 0xffffffff,
489 .mmu_trcr_mask = 0xffffffff,
490 .nwindows = 8,
491 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
494 .name = "LEON3",
495 .iu_version = 0xf3000000,
496 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
497 .mmu_version = 0xf3000000,
498 .mmu_bm = 0x00000000,
499 .mmu_ctpr_mask = 0xfffffffc,
500 .mmu_cxr_mask = 0x000000ff,
501 .mmu_sfsr_mask = 0xffffffff,
502 .mmu_trcr_mask = 0xffffffff,
503 .nwindows = 8,
504 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
505 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
506 CPU_FEATURE_CASA,
508 #endif
511 static const char * const feature_name[] = {
512 "float",
513 "float128",
514 "swap",
515 "mul",
516 "div",
517 "flush",
518 "fsqrt",
519 "fmul",
520 "vis1",
521 "vis2",
522 "fsmuld",
523 "hypv",
524 "cmt",
525 "gl",
528 static void print_features(FILE *f, fprintf_function cpu_fprintf,
529 uint32_t features, const char *prefix)
531 unsigned int i;
533 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
534 if (feature_name[i] && (features & (1 << i))) {
535 if (prefix) {
536 (*cpu_fprintf)(f, "%s", prefix);
538 (*cpu_fprintf)(f, "%s ", feature_name[i]);
543 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
545 unsigned int i;
547 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
548 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
549 *features |= 1 << i;
550 return;
553 error_report("CPU feature %s not found", flagname);
556 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
558 unsigned int i;
559 const sparc_def_t *def = NULL;
561 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
562 if (strcasecmp(name, sparc_defs[i].name) == 0) {
563 def = &sparc_defs[i];
566 if (!def) {
567 return -1;
569 memcpy(cpu_def, def, sizeof(*def));
570 return 0;
573 static void sparc_cpu_parse_features(CPUState *cs, char *features,
574 Error **errp)
576 SPARCCPU *cpu = SPARC_CPU(cs);
577 sparc_def_t *cpu_def = cpu->env.def;
578 char *featurestr;
579 uint32_t plus_features = 0;
580 uint32_t minus_features = 0;
581 uint64_t iu_version;
582 uint32_t fpu_version, mmu_version, nwindows;
584 featurestr = features ? strtok(features, ",") : NULL;
585 while (featurestr) {
586 char *val;
588 if (featurestr[0] == '+') {
589 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
590 } else if (featurestr[0] == '-') {
591 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
592 } else if ((val = strchr(featurestr, '='))) {
593 *val = 0; val++;
594 if (!strcmp(featurestr, "iu_version")) {
595 char *err;
597 iu_version = strtoll(val, &err, 0);
598 if (!*val || *err) {
599 error_setg(errp, "bad numerical value %s", val);
600 return;
602 cpu_def->iu_version = iu_version;
603 #ifdef DEBUG_FEATURES
604 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
605 #endif
606 } else if (!strcmp(featurestr, "fpu_version")) {
607 char *err;
609 fpu_version = strtol(val, &err, 0);
610 if (!*val || *err) {
611 error_setg(errp, "bad numerical value %s", val);
612 return;
614 cpu_def->fpu_version = fpu_version;
615 #ifdef DEBUG_FEATURES
616 fprintf(stderr, "fpu_version %x\n", fpu_version);
617 #endif
618 } else if (!strcmp(featurestr, "mmu_version")) {
619 char *err;
621 mmu_version = strtol(val, &err, 0);
622 if (!*val || *err) {
623 error_setg(errp, "bad numerical value %s", val);
624 return;
626 cpu_def->mmu_version = mmu_version;
627 #ifdef DEBUG_FEATURES
628 fprintf(stderr, "mmu_version %x\n", mmu_version);
629 #endif
630 } else if (!strcmp(featurestr, "nwindows")) {
631 char *err;
633 nwindows = strtol(val, &err, 0);
634 if (!*val || *err || nwindows > MAX_NWINDOWS ||
635 nwindows < MIN_NWINDOWS) {
636 error_setg(errp, "bad numerical value %s", val);
637 return;
639 cpu_def->nwindows = nwindows;
640 #ifdef DEBUG_FEATURES
641 fprintf(stderr, "nwindows %d\n", nwindows);
642 #endif
643 } else {
644 error_setg(errp, "unrecognized feature %s", featurestr);
645 return;
647 } else {
648 error_setg(errp, "feature string `%s' not in format "
649 "(+feature|-feature|feature=xyz)", featurestr);
650 return;
652 featurestr = strtok(NULL, ",");
654 cpu_def->features |= plus_features;
655 cpu_def->features &= ~minus_features;
656 #ifdef DEBUG_FEATURES
657 print_features(stderr, fprintf, cpu_def->features, NULL);
658 #endif
661 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
663 unsigned int i;
665 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
666 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
667 " FPU %08x MMU %08x NWINS %d ",
668 sparc_defs[i].name,
669 sparc_defs[i].iu_version,
670 sparc_defs[i].fpu_version,
671 sparc_defs[i].mmu_version,
672 sparc_defs[i].nwindows);
673 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
674 ~sparc_defs[i].features, "-");
675 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
676 sparc_defs[i].features, "+");
677 (*cpu_fprintf)(f, "\n");
679 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
680 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
681 (*cpu_fprintf)(f, "\n");
682 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
683 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
684 (*cpu_fprintf)(f, "\n");
685 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
686 "fpu_version mmu_version nwindows\n");
689 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
690 uint32_t cc)
692 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
693 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
694 cc & PSR_CARRY ? 'C' : '-');
697 #ifdef TARGET_SPARC64
698 #define REGS_PER_LINE 4
699 #else
700 #define REGS_PER_LINE 8
701 #endif
703 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
704 int flags)
706 SPARCCPU *cpu = SPARC_CPU(cs);
707 CPUSPARCState *env = &cpu->env;
708 int i, x;
710 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
711 env->npc);
713 for (i = 0; i < 8; i++) {
714 if (i % REGS_PER_LINE == 0) {
715 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
717 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
718 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
719 cpu_fprintf(f, "\n");
722 for (x = 0; x < 3; x++) {
723 for (i = 0; i < 8; i++) {
724 if (i % REGS_PER_LINE == 0) {
725 cpu_fprintf(f, "%%%c%d-%d: ",
726 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
727 i, i + REGS_PER_LINE - 1);
729 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
730 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
731 cpu_fprintf(f, "\n");
736 for (i = 0; i < TARGET_DPREGS; i++) {
737 if ((i & 3) == 0) {
738 cpu_fprintf(f, "%%f%02d: ", i * 2);
740 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
741 if ((i & 3) == 3) {
742 cpu_fprintf(f, "\n");
745 #ifdef TARGET_SPARC64
746 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
747 (unsigned)cpu_get_ccr(env));
748 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
749 cpu_fprintf(f, " xcc: ");
750 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
751 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x gl: %d\n", env->asi, env->tl,
752 env->psrpil, env->gl);
753 cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
754 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
755 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
756 "cleanwin: %d cwp: %d\n",
757 env->cansave, env->canrestore, env->otherwin, env->wstate,
758 env->cleanwin, env->nwindows - 1 - env->cwp);
759 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
760 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
762 #else
763 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
764 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
765 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
766 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
767 env->wim);
768 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
769 env->fsr, env->y);
770 #endif
771 cpu_fprintf(f, "\n");
774 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
776 SPARCCPU *cpu = SPARC_CPU(cs);
778 cpu->env.pc = value;
779 cpu->env.npc = value + 4;
782 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
784 SPARCCPU *cpu = SPARC_CPU(cs);
786 cpu->env.pc = tb->pc;
787 cpu->env.npc = tb->cs_base;
790 static bool sparc_cpu_has_work(CPUState *cs)
792 SPARCCPU *cpu = SPARC_CPU(cs);
793 CPUSPARCState *env = &cpu->env;
795 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
796 cpu_interrupts_enabled(env);
799 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
801 CPUState *cs = CPU(dev);
802 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
803 Error *local_err = NULL;
804 #if defined(CONFIG_USER_ONLY)
805 SPARCCPU *cpu = SPARC_CPU(dev);
806 CPUSPARCState *env = &cpu->env;
808 if ((env->def->features & CPU_FEATURE_FLOAT)) {
809 env->def->features |= CPU_FEATURE_FLOAT128;
811 #endif
813 cpu_exec_realizefn(cs, &local_err);
814 if (local_err != NULL) {
815 error_propagate(errp, local_err);
816 return;
819 qemu_init_vcpu(cs);
821 scc->parent_realize(dev, errp);
824 static void sparc_cpu_initfn(Object *obj)
826 CPUState *cs = CPU(obj);
827 SPARCCPU *cpu = SPARC_CPU(obj);
828 CPUSPARCState *env = &cpu->env;
830 cs->env_ptr = env;
832 if (tcg_enabled()) {
833 gen_intermediate_code_init(env);
837 static void sparc_cpu_uninitfn(Object *obj)
839 SPARCCPU *cpu = SPARC_CPU(obj);
840 CPUSPARCState *env = &cpu->env;
842 g_free(env->def);
845 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
847 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
848 CPUClass *cc = CPU_CLASS(oc);
849 DeviceClass *dc = DEVICE_CLASS(oc);
851 scc->parent_realize = dc->realize;
852 dc->realize = sparc_cpu_realizefn;
854 scc->parent_reset = cc->reset;
855 cc->reset = sparc_cpu_reset;
857 cc->has_work = sparc_cpu_has_work;
858 cc->do_interrupt = sparc_cpu_do_interrupt;
859 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
860 cc->dump_state = sparc_cpu_dump_state;
861 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
862 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
863 #endif
864 cc->set_pc = sparc_cpu_set_pc;
865 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
866 cc->gdb_read_register = sparc_cpu_gdb_read_register;
867 cc->gdb_write_register = sparc_cpu_gdb_write_register;
868 #ifdef CONFIG_USER_ONLY
869 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
870 #else
871 cc->do_unassigned_access = sparc_cpu_unassigned_access;
872 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
873 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
874 cc->vmsd = &vmstate_sparc_cpu;
875 #endif
876 cc->disas_set_info = cpu_sparc_disas_set_info;
878 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
879 cc->gdb_num_core_regs = 86;
880 #else
881 cc->gdb_num_core_regs = 72;
882 #endif
885 static const TypeInfo sparc_cpu_type_info = {
886 .name = TYPE_SPARC_CPU,
887 .parent = TYPE_CPU,
888 .instance_size = sizeof(SPARCCPU),
889 .instance_init = sparc_cpu_initfn,
890 .instance_finalize = sparc_cpu_uninitfn,
891 .abstract = false,
892 .class_size = sizeof(SPARCCPUClass),
893 .class_init = sparc_cpu_class_init,
896 static void sparc_cpu_register_types(void)
898 type_register_static(&sparc_cpu_type_info);
901 type_init(sparc_cpu_register_types)