Merge remote-tracking branch 'remotes/xtensa/tags/20141110-xtensa' into staging
[qemu-kvm.git] / target-sparc / cpu.c
blobaa7626c1bfea56a60fd598cd26688558c290c80d
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 "cpu.h"
21 #include "qemu/error-report.h"
23 //#define DEBUG_FEATURES
25 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
27 /* CPUClass::reset() */
28 static void sparc_cpu_reset(CPUState *s)
30 SPARCCPU *cpu = SPARC_CPU(s);
31 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
32 CPUSPARCState *env = &cpu->env;
34 scc->parent_reset(s);
36 memset(env, 0, offsetof(CPUSPARCState, version));
37 tlb_flush(s, 1);
38 env->cwp = 0;
39 #ifndef TARGET_SPARC64
40 env->wim = 1;
41 #endif
42 env->regwptr = env->regbase + (env->cwp * 16);
43 CC_OP = CC_OP_FLAGS;
44 #if defined(CONFIG_USER_ONLY)
45 #ifdef TARGET_SPARC64
46 env->cleanwin = env->nwindows - 2;
47 env->cansave = env->nwindows - 2;
48 env->pstate = PS_RMO | PS_PEF | PS_IE;
49 env->asi = 0x82; /* Primary no-fault */
50 #endif
51 #else
52 #if !defined(TARGET_SPARC64)
53 env->psret = 0;
54 env->psrs = 1;
55 env->psrps = 1;
56 #endif
57 #ifdef TARGET_SPARC64
58 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
59 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
60 env->tl = env->maxtl;
61 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
62 env->lsu = 0;
63 #else
64 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
65 env->mmuregs[0] |= env->def->mmu_bm;
66 #endif
67 env->pc = 0;
68 env->npc = env->pc + 4;
69 #endif
70 env->cache_control = 0;
73 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
75 if (interrupt_request & CPU_INTERRUPT_HARD) {
76 SPARCCPU *cpu = SPARC_CPU(cs);
77 CPUSPARCState *env = &cpu->env;
79 if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
80 int pil = env->interrupt_index & 0xf;
81 int type = env->interrupt_index & 0xf0;
83 if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
84 cs->exception_index = env->interrupt_index;
85 sparc_cpu_do_interrupt(cs);
86 return true;
90 return false;
93 static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
95 CPUClass *cc = CPU_GET_CLASS(cpu);
96 CPUSPARCState *env = &cpu->env;
97 char *s = g_strdup(cpu_model);
98 char *featurestr, *name = strtok(s, ",");
99 sparc_def_t def1, *def = &def1;
100 Error *err = NULL;
102 if (cpu_sparc_find_by_name(def, name) < 0) {
103 g_free(s);
104 return -1;
107 env->def = g_new0(sparc_def_t, 1);
108 memcpy(env->def, def, sizeof(*def));
110 featurestr = strtok(NULL, ",");
111 cc->parse_features(CPU(cpu), featurestr, &err);
112 g_free(s);
113 if (err) {
114 error_report("%s", error_get_pretty(err));
115 error_free(err);
116 return -1;
119 env->version = def->iu_version;
120 env->fsr = def->fpu_version;
121 env->nwindows = def->nwindows;
122 #if !defined(TARGET_SPARC64)
123 env->mmuregs[0] |= def->mmu_version;
124 cpu_sparc_set_id(env, 0);
125 env->mxccregs[7] |= def->mxcc_version;
126 #else
127 env->mmu_version = def->mmu_version;
128 env->maxtl = def->maxtl;
129 env->version |= def->maxtl << 8;
130 env->version |= def->nwindows - 1;
131 #endif
132 return 0;
135 SPARCCPU *cpu_sparc_init(const char *cpu_model)
137 SPARCCPU *cpu;
139 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
141 if (cpu_sparc_register(cpu, cpu_model) < 0) {
142 object_unref(OBJECT(cpu));
143 return NULL;
146 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
148 return cpu;
151 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
153 #if !defined(TARGET_SPARC64)
154 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
155 #endif
158 static const sparc_def_t sparc_defs[] = {
159 #ifdef TARGET_SPARC64
161 .name = "Fujitsu Sparc64",
162 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
163 .fpu_version = 0x00000000,
164 .mmu_version = mmu_us_12,
165 .nwindows = 4,
166 .maxtl = 4,
167 .features = CPU_DEFAULT_FEATURES,
170 .name = "Fujitsu Sparc64 III",
171 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
172 .fpu_version = 0x00000000,
173 .mmu_version = mmu_us_12,
174 .nwindows = 5,
175 .maxtl = 4,
176 .features = CPU_DEFAULT_FEATURES,
179 .name = "Fujitsu Sparc64 IV",
180 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
181 .fpu_version = 0x00000000,
182 .mmu_version = mmu_us_12,
183 .nwindows = 8,
184 .maxtl = 5,
185 .features = CPU_DEFAULT_FEATURES,
188 .name = "Fujitsu Sparc64 V",
189 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
190 .fpu_version = 0x00000000,
191 .mmu_version = mmu_us_12,
192 .nwindows = 8,
193 .maxtl = 5,
194 .features = CPU_DEFAULT_FEATURES,
197 .name = "TI UltraSparc I",
198 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
199 .fpu_version = 0x00000000,
200 .mmu_version = mmu_us_12,
201 .nwindows = 8,
202 .maxtl = 5,
203 .features = CPU_DEFAULT_FEATURES,
206 .name = "TI UltraSparc II",
207 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
208 .fpu_version = 0x00000000,
209 .mmu_version = mmu_us_12,
210 .nwindows = 8,
211 .maxtl = 5,
212 .features = CPU_DEFAULT_FEATURES,
215 .name = "TI UltraSparc IIi",
216 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
217 .fpu_version = 0x00000000,
218 .mmu_version = mmu_us_12,
219 .nwindows = 8,
220 .maxtl = 5,
221 .features = CPU_DEFAULT_FEATURES,
224 .name = "TI UltraSparc IIe",
225 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
226 .fpu_version = 0x00000000,
227 .mmu_version = mmu_us_12,
228 .nwindows = 8,
229 .maxtl = 5,
230 .features = CPU_DEFAULT_FEATURES,
233 .name = "Sun UltraSparc III",
234 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
235 .fpu_version = 0x00000000,
236 .mmu_version = mmu_us_12,
237 .nwindows = 8,
238 .maxtl = 5,
239 .features = CPU_DEFAULT_FEATURES,
242 .name = "Sun UltraSparc III Cu",
243 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
244 .fpu_version = 0x00000000,
245 .mmu_version = mmu_us_3,
246 .nwindows = 8,
247 .maxtl = 5,
248 .features = CPU_DEFAULT_FEATURES,
251 .name = "Sun UltraSparc IIIi",
252 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
253 .fpu_version = 0x00000000,
254 .mmu_version = mmu_us_12,
255 .nwindows = 8,
256 .maxtl = 5,
257 .features = CPU_DEFAULT_FEATURES,
260 .name = "Sun UltraSparc IV",
261 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
262 .fpu_version = 0x00000000,
263 .mmu_version = mmu_us_4,
264 .nwindows = 8,
265 .maxtl = 5,
266 .features = CPU_DEFAULT_FEATURES,
269 .name = "Sun UltraSparc IV+",
270 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
271 .fpu_version = 0x00000000,
272 .mmu_version = mmu_us_12,
273 .nwindows = 8,
274 .maxtl = 5,
275 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
278 .name = "Sun UltraSparc IIIi+",
279 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
280 .fpu_version = 0x00000000,
281 .mmu_version = mmu_us_3,
282 .nwindows = 8,
283 .maxtl = 5,
284 .features = CPU_DEFAULT_FEATURES,
287 .name = "Sun UltraSparc T1",
288 /* defined in sparc_ifu_fdp.v and ctu.h */
289 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
290 .fpu_version = 0x00000000,
291 .mmu_version = mmu_sun4v,
292 .nwindows = 8,
293 .maxtl = 6,
294 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
295 | CPU_FEATURE_GL,
298 .name = "Sun UltraSparc T2",
299 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
300 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
301 .fpu_version = 0x00000000,
302 .mmu_version = mmu_sun4v,
303 .nwindows = 8,
304 .maxtl = 6,
305 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
306 | CPU_FEATURE_GL,
309 .name = "NEC UltraSparc I",
310 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
311 .fpu_version = 0x00000000,
312 .mmu_version = mmu_us_12,
313 .nwindows = 8,
314 .maxtl = 5,
315 .features = CPU_DEFAULT_FEATURES,
317 #else
319 .name = "Fujitsu MB86904",
320 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
321 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
322 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
323 .mmu_bm = 0x00004000,
324 .mmu_ctpr_mask = 0x00ffffc0,
325 .mmu_cxr_mask = 0x000000ff,
326 .mmu_sfsr_mask = 0x00016fff,
327 .mmu_trcr_mask = 0x00ffffff,
328 .nwindows = 8,
329 .features = CPU_DEFAULT_FEATURES,
332 .name = "Fujitsu MB86907",
333 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
334 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
335 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
336 .mmu_bm = 0x00004000,
337 .mmu_ctpr_mask = 0xffffffc0,
338 .mmu_cxr_mask = 0x000000ff,
339 .mmu_sfsr_mask = 0x00016fff,
340 .mmu_trcr_mask = 0xffffffff,
341 .nwindows = 8,
342 .features = CPU_DEFAULT_FEATURES,
345 .name = "TI MicroSparc I",
346 .iu_version = 0x41000000,
347 .fpu_version = 4 << 17,
348 .mmu_version = 0x41000000,
349 .mmu_bm = 0x00004000,
350 .mmu_ctpr_mask = 0x007ffff0,
351 .mmu_cxr_mask = 0x0000003f,
352 .mmu_sfsr_mask = 0x00016fff,
353 .mmu_trcr_mask = 0x0000003f,
354 .nwindows = 7,
355 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
356 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
357 CPU_FEATURE_FMUL,
360 .name = "TI MicroSparc II",
361 .iu_version = 0x42000000,
362 .fpu_version = 4 << 17,
363 .mmu_version = 0x02000000,
364 .mmu_bm = 0x00004000,
365 .mmu_ctpr_mask = 0x00ffffc0,
366 .mmu_cxr_mask = 0x000000ff,
367 .mmu_sfsr_mask = 0x00016fff,
368 .mmu_trcr_mask = 0x00ffffff,
369 .nwindows = 8,
370 .features = CPU_DEFAULT_FEATURES,
373 .name = "TI MicroSparc IIep",
374 .iu_version = 0x42000000,
375 .fpu_version = 4 << 17,
376 .mmu_version = 0x04000000,
377 .mmu_bm = 0x00004000,
378 .mmu_ctpr_mask = 0x00ffffc0,
379 .mmu_cxr_mask = 0x000000ff,
380 .mmu_sfsr_mask = 0x00016bff,
381 .mmu_trcr_mask = 0x00ffffff,
382 .nwindows = 8,
383 .features = CPU_DEFAULT_FEATURES,
386 .name = "TI SuperSparc 40", /* STP1020NPGA */
387 .iu_version = 0x41000000, /* SuperSPARC 2.x */
388 .fpu_version = 0 << 17,
389 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
390 .mmu_bm = 0x00002000,
391 .mmu_ctpr_mask = 0xffffffc0,
392 .mmu_cxr_mask = 0x0000ffff,
393 .mmu_sfsr_mask = 0xffffffff,
394 .mmu_trcr_mask = 0xffffffff,
395 .nwindows = 8,
396 .features = CPU_DEFAULT_FEATURES,
399 .name = "TI SuperSparc 50", /* STP1020PGA */
400 .iu_version = 0x40000000, /* SuperSPARC 3.x */
401 .fpu_version = 0 << 17,
402 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
403 .mmu_bm = 0x00002000,
404 .mmu_ctpr_mask = 0xffffffc0,
405 .mmu_cxr_mask = 0x0000ffff,
406 .mmu_sfsr_mask = 0xffffffff,
407 .mmu_trcr_mask = 0xffffffff,
408 .nwindows = 8,
409 .features = CPU_DEFAULT_FEATURES,
412 .name = "TI SuperSparc 51",
413 .iu_version = 0x40000000, /* SuperSPARC 3.x */
414 .fpu_version = 0 << 17,
415 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
416 .mmu_bm = 0x00002000,
417 .mmu_ctpr_mask = 0xffffffc0,
418 .mmu_cxr_mask = 0x0000ffff,
419 .mmu_sfsr_mask = 0xffffffff,
420 .mmu_trcr_mask = 0xffffffff,
421 .mxcc_version = 0x00000104,
422 .nwindows = 8,
423 .features = CPU_DEFAULT_FEATURES,
426 .name = "TI SuperSparc 60", /* STP1020APGA */
427 .iu_version = 0x40000000, /* SuperSPARC 3.x */
428 .fpu_version = 0 << 17,
429 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no 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 .nwindows = 8,
436 .features = CPU_DEFAULT_FEATURES,
439 .name = "TI SuperSparc 61",
440 .iu_version = 0x44000000, /* SuperSPARC 3.x */
441 .fpu_version = 0 << 17,
442 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
443 .mmu_bm = 0x00002000,
444 .mmu_ctpr_mask = 0xffffffc0,
445 .mmu_cxr_mask = 0x0000ffff,
446 .mmu_sfsr_mask = 0xffffffff,
447 .mmu_trcr_mask = 0xffffffff,
448 .mxcc_version = 0x00000104,
449 .nwindows = 8,
450 .features = CPU_DEFAULT_FEATURES,
453 .name = "TI SuperSparc II",
454 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
455 .fpu_version = 0 << 17,
456 .mmu_version = 0x08000000, /* SuperSPARC II 1.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 = "LEON2",
468 .iu_version = 0xf2000000,
469 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
470 .mmu_version = 0xf2000000,
471 .mmu_bm = 0x00004000,
472 .mmu_ctpr_mask = 0x007ffff0,
473 .mmu_cxr_mask = 0x0000003f,
474 .mmu_sfsr_mask = 0xffffffff,
475 .mmu_trcr_mask = 0xffffffff,
476 .nwindows = 8,
477 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
480 .name = "LEON3",
481 .iu_version = 0xf3000000,
482 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
483 .mmu_version = 0xf3000000,
484 .mmu_bm = 0x00000000,
485 .mmu_ctpr_mask = 0xfffffffc,
486 .mmu_cxr_mask = 0x000000ff,
487 .mmu_sfsr_mask = 0xffffffff,
488 .mmu_trcr_mask = 0xffffffff,
489 .nwindows = 8,
490 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
491 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
492 CPU_FEATURE_CASA,
494 #endif
497 static const char * const feature_name[] = {
498 "float",
499 "float128",
500 "swap",
501 "mul",
502 "div",
503 "flush",
504 "fsqrt",
505 "fmul",
506 "vis1",
507 "vis2",
508 "fsmuld",
509 "hypv",
510 "cmt",
511 "gl",
514 static void print_features(FILE *f, fprintf_function cpu_fprintf,
515 uint32_t features, const char *prefix)
517 unsigned int i;
519 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
520 if (feature_name[i] && (features & (1 << i))) {
521 if (prefix) {
522 (*cpu_fprintf)(f, "%s", prefix);
524 (*cpu_fprintf)(f, "%s ", feature_name[i]);
529 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
531 unsigned int i;
533 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
534 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
535 *features |= 1 << i;
536 return;
539 error_report("CPU feature %s not found", flagname);
542 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
544 unsigned int i;
545 const sparc_def_t *def = NULL;
547 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
548 if (strcasecmp(name, sparc_defs[i].name) == 0) {
549 def = &sparc_defs[i];
552 if (!def) {
553 return -1;
555 memcpy(cpu_def, def, sizeof(*def));
556 return 0;
559 static void sparc_cpu_parse_features(CPUState *cs, char *features,
560 Error **errp)
562 SPARCCPU *cpu = SPARC_CPU(cs);
563 sparc_def_t *cpu_def = cpu->env.def;
564 char *featurestr;
565 uint32_t plus_features = 0;
566 uint32_t minus_features = 0;
567 uint64_t iu_version;
568 uint32_t fpu_version, mmu_version, nwindows;
570 featurestr = features ? strtok(features, ",") : NULL;
571 while (featurestr) {
572 char *val;
574 if (featurestr[0] == '+') {
575 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
576 } else if (featurestr[0] == '-') {
577 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
578 } else if ((val = strchr(featurestr, '='))) {
579 *val = 0; val++;
580 if (!strcmp(featurestr, "iu_version")) {
581 char *err;
583 iu_version = strtoll(val, &err, 0);
584 if (!*val || *err) {
585 error_setg(errp, "bad numerical value %s", val);
586 return;
588 cpu_def->iu_version = iu_version;
589 #ifdef DEBUG_FEATURES
590 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
591 #endif
592 } else if (!strcmp(featurestr, "fpu_version")) {
593 char *err;
595 fpu_version = strtol(val, &err, 0);
596 if (!*val || *err) {
597 error_setg(errp, "bad numerical value %s", val);
598 return;
600 cpu_def->fpu_version = fpu_version;
601 #ifdef DEBUG_FEATURES
602 fprintf(stderr, "fpu_version %x\n", fpu_version);
603 #endif
604 } else if (!strcmp(featurestr, "mmu_version")) {
605 char *err;
607 mmu_version = strtol(val, &err, 0);
608 if (!*val || *err) {
609 error_setg(errp, "bad numerical value %s", val);
610 return;
612 cpu_def->mmu_version = mmu_version;
613 #ifdef DEBUG_FEATURES
614 fprintf(stderr, "mmu_version %x\n", mmu_version);
615 #endif
616 } else if (!strcmp(featurestr, "nwindows")) {
617 char *err;
619 nwindows = strtol(val, &err, 0);
620 if (!*val || *err || nwindows > MAX_NWINDOWS ||
621 nwindows < MIN_NWINDOWS) {
622 error_setg(errp, "bad numerical value %s", val);
623 return;
625 cpu_def->nwindows = nwindows;
626 #ifdef DEBUG_FEATURES
627 fprintf(stderr, "nwindows %d\n", nwindows);
628 #endif
629 } else {
630 error_setg(errp, "unrecognized feature %s", featurestr);
631 return;
633 } else {
634 error_setg(errp, "feature string `%s' not in format "
635 "(+feature|-feature|feature=xyz)", featurestr);
636 return;
638 featurestr = strtok(NULL, ",");
640 cpu_def->features |= plus_features;
641 cpu_def->features &= ~minus_features;
642 #ifdef DEBUG_FEATURES
643 print_features(stderr, fprintf, cpu_def->features, NULL);
644 #endif
647 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
649 unsigned int i;
651 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
652 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
653 " FPU %08x MMU %08x NWINS %d ",
654 sparc_defs[i].name,
655 sparc_defs[i].iu_version,
656 sparc_defs[i].fpu_version,
657 sparc_defs[i].mmu_version,
658 sparc_defs[i].nwindows);
659 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
660 ~sparc_defs[i].features, "-");
661 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
662 sparc_defs[i].features, "+");
663 (*cpu_fprintf)(f, "\n");
665 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
666 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
667 (*cpu_fprintf)(f, "\n");
668 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
669 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
670 (*cpu_fprintf)(f, "\n");
671 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
672 "fpu_version mmu_version nwindows\n");
675 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
676 uint32_t cc)
678 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
679 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
680 cc & PSR_CARRY ? 'C' : '-');
683 #ifdef TARGET_SPARC64
684 #define REGS_PER_LINE 4
685 #else
686 #define REGS_PER_LINE 8
687 #endif
689 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
690 int flags)
692 SPARCCPU *cpu = SPARC_CPU(cs);
693 CPUSPARCState *env = &cpu->env;
694 int i, x;
696 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
697 env->npc);
699 for (i = 0; i < 8; i++) {
700 if (i % REGS_PER_LINE == 0) {
701 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
703 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
704 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
705 cpu_fprintf(f, "\n");
708 for (x = 0; x < 3; x++) {
709 for (i = 0; i < 8; i++) {
710 if (i % REGS_PER_LINE == 0) {
711 cpu_fprintf(f, "%%%c%d-%d: ",
712 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
713 i, i + REGS_PER_LINE - 1);
715 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
716 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
717 cpu_fprintf(f, "\n");
722 for (i = 0; i < TARGET_DPREGS; i++) {
723 if ((i & 3) == 0) {
724 cpu_fprintf(f, "%%f%02d: ", i * 2);
726 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
727 if ((i & 3) == 3) {
728 cpu_fprintf(f, "\n");
731 #ifdef TARGET_SPARC64
732 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
733 (unsigned)cpu_get_ccr(env));
734 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
735 cpu_fprintf(f, " xcc: ");
736 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
737 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
738 env->psrpil);
739 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
740 "cleanwin: %d cwp: %d\n",
741 env->cansave, env->canrestore, env->otherwin, env->wstate,
742 env->cleanwin, env->nwindows - 1 - env->cwp);
743 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
744 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
745 #else
746 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
747 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
748 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
749 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
750 env->wim);
751 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
752 env->fsr, env->y);
753 #endif
754 cpu_fprintf(f, "\n");
757 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
759 SPARCCPU *cpu = SPARC_CPU(cs);
761 cpu->env.pc = value;
762 cpu->env.npc = value + 4;
765 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
767 SPARCCPU *cpu = SPARC_CPU(cs);
769 cpu->env.pc = tb->pc;
770 cpu->env.npc = tb->cs_base;
773 static bool sparc_cpu_has_work(CPUState *cs)
775 SPARCCPU *cpu = SPARC_CPU(cs);
776 CPUSPARCState *env = &cpu->env;
778 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
779 cpu_interrupts_enabled(env);
782 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
784 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
785 #if defined(CONFIG_USER_ONLY)
786 SPARCCPU *cpu = SPARC_CPU(dev);
787 CPUSPARCState *env = &cpu->env;
789 if ((env->def->features & CPU_FEATURE_FLOAT)) {
790 env->def->features |= CPU_FEATURE_FLOAT128;
792 #endif
794 qemu_init_vcpu(CPU(dev));
796 scc->parent_realize(dev, errp);
799 static void sparc_cpu_initfn(Object *obj)
801 CPUState *cs = CPU(obj);
802 SPARCCPU *cpu = SPARC_CPU(obj);
803 CPUSPARCState *env = &cpu->env;
805 cs->env_ptr = env;
806 cpu_exec_init(env);
808 if (tcg_enabled()) {
809 gen_intermediate_code_init(env);
813 static void sparc_cpu_uninitfn(Object *obj)
815 SPARCCPU *cpu = SPARC_CPU(obj);
816 CPUSPARCState *env = &cpu->env;
818 g_free(env->def);
821 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
823 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
824 CPUClass *cc = CPU_CLASS(oc);
825 DeviceClass *dc = DEVICE_CLASS(oc);
827 scc->parent_realize = dc->realize;
828 dc->realize = sparc_cpu_realizefn;
830 scc->parent_reset = cc->reset;
831 cc->reset = sparc_cpu_reset;
833 cc->parse_features = sparc_cpu_parse_features;
834 cc->has_work = sparc_cpu_has_work;
835 cc->do_interrupt = sparc_cpu_do_interrupt;
836 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
837 cc->dump_state = sparc_cpu_dump_state;
838 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
839 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
840 #endif
841 cc->set_pc = sparc_cpu_set_pc;
842 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
843 cc->gdb_read_register = sparc_cpu_gdb_read_register;
844 cc->gdb_write_register = sparc_cpu_gdb_write_register;
845 #ifdef CONFIG_USER_ONLY
846 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
847 #else
848 cc->do_unassigned_access = sparc_cpu_unassigned_access;
849 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
850 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
851 #endif
853 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
854 cc->gdb_num_core_regs = 86;
855 #else
856 cc->gdb_num_core_regs = 72;
857 #endif
860 static const TypeInfo sparc_cpu_type_info = {
861 .name = TYPE_SPARC_CPU,
862 .parent = TYPE_CPU,
863 .instance_size = sizeof(SPARCCPU),
864 .instance_init = sparc_cpu_initfn,
865 .instance_finalize = sparc_cpu_uninitfn,
866 .abstract = false,
867 .class_size = sizeof(SPARCCPUClass),
868 .class_init = sparc_cpu_class_init,
871 static void sparc_cpu_register_types(void)
873 type_register_static(&sparc_cpu_type_info);
876 type_init(sparc_cpu_register_types)