block: Split bdrv_merge_limits() from bdrv_refresh_limits()
[qemu/ar7.git] / target-sparc / cpu.c
blob5b74cfcd3117e92ebce23dab082ea87bbbe3063e
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 int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
106 CPUClass *cc = CPU_GET_CLASS(cpu);
107 CPUSPARCState *env = &cpu->env;
108 char *s = g_strdup(cpu_model);
109 char *featurestr, *name = strtok(s, ",");
110 sparc_def_t def1, *def = &def1;
111 Error *err = NULL;
113 if (cpu_sparc_find_by_name(def, name) < 0) {
114 g_free(s);
115 return -1;
118 env->def = g_new0(sparc_def_t, 1);
119 memcpy(env->def, def, sizeof(*def));
121 featurestr = strtok(NULL, ",");
122 cc->parse_features(CPU(cpu), featurestr, &err);
123 g_free(s);
124 if (err) {
125 error_report_err(err);
126 return -1;
129 env->version = def->iu_version;
130 env->fsr = def->fpu_version;
131 env->nwindows = def->nwindows;
132 #if !defined(TARGET_SPARC64)
133 env->mmuregs[0] |= def->mmu_version;
134 cpu_sparc_set_id(env, 0);
135 env->mxccregs[7] |= def->mxcc_version;
136 #else
137 env->mmu_version = def->mmu_version;
138 env->maxtl = def->maxtl;
139 env->version |= def->maxtl << 8;
140 env->version |= def->nwindows - 1;
141 #endif
142 return 0;
145 SPARCCPU *cpu_sparc_init(const char *cpu_model)
147 SPARCCPU *cpu;
149 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
151 if (cpu_sparc_register(cpu, cpu_model) < 0) {
152 object_unref(OBJECT(cpu));
153 return NULL;
156 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
158 return cpu;
161 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
163 #if !defined(TARGET_SPARC64)
164 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
165 #endif
168 static const sparc_def_t sparc_defs[] = {
169 #ifdef TARGET_SPARC64
171 .name = "Fujitsu Sparc64",
172 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
173 .fpu_version = 0x00000000,
174 .mmu_version = mmu_us_12,
175 .nwindows = 4,
176 .maxtl = 4,
177 .features = CPU_DEFAULT_FEATURES,
180 .name = "Fujitsu Sparc64 III",
181 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
182 .fpu_version = 0x00000000,
183 .mmu_version = mmu_us_12,
184 .nwindows = 5,
185 .maxtl = 4,
186 .features = CPU_DEFAULT_FEATURES,
189 .name = "Fujitsu Sparc64 IV",
190 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
191 .fpu_version = 0x00000000,
192 .mmu_version = mmu_us_12,
193 .nwindows = 8,
194 .maxtl = 5,
195 .features = CPU_DEFAULT_FEATURES,
198 .name = "Fujitsu Sparc64 V",
199 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
200 .fpu_version = 0x00000000,
201 .mmu_version = mmu_us_12,
202 .nwindows = 8,
203 .maxtl = 5,
204 .features = CPU_DEFAULT_FEATURES,
207 .name = "TI UltraSparc I",
208 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
209 .fpu_version = 0x00000000,
210 .mmu_version = mmu_us_12,
211 .nwindows = 8,
212 .maxtl = 5,
213 .features = CPU_DEFAULT_FEATURES,
216 .name = "TI UltraSparc II",
217 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
218 .fpu_version = 0x00000000,
219 .mmu_version = mmu_us_12,
220 .nwindows = 8,
221 .maxtl = 5,
222 .features = CPU_DEFAULT_FEATURES,
225 .name = "TI UltraSparc IIi",
226 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
227 .fpu_version = 0x00000000,
228 .mmu_version = mmu_us_12,
229 .nwindows = 8,
230 .maxtl = 5,
231 .features = CPU_DEFAULT_FEATURES,
234 .name = "TI UltraSparc IIe",
235 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
236 .fpu_version = 0x00000000,
237 .mmu_version = mmu_us_12,
238 .nwindows = 8,
239 .maxtl = 5,
240 .features = CPU_DEFAULT_FEATURES,
243 .name = "Sun UltraSparc III",
244 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
245 .fpu_version = 0x00000000,
246 .mmu_version = mmu_us_12,
247 .nwindows = 8,
248 .maxtl = 5,
249 .features = CPU_DEFAULT_FEATURES,
252 .name = "Sun UltraSparc III Cu",
253 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
254 .fpu_version = 0x00000000,
255 .mmu_version = mmu_us_3,
256 .nwindows = 8,
257 .maxtl = 5,
258 .features = CPU_DEFAULT_FEATURES,
261 .name = "Sun UltraSparc IIIi",
262 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
263 .fpu_version = 0x00000000,
264 .mmu_version = mmu_us_12,
265 .nwindows = 8,
266 .maxtl = 5,
267 .features = CPU_DEFAULT_FEATURES,
270 .name = "Sun UltraSparc IV",
271 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
272 .fpu_version = 0x00000000,
273 .mmu_version = mmu_us_4,
274 .nwindows = 8,
275 .maxtl = 5,
276 .features = CPU_DEFAULT_FEATURES,
279 .name = "Sun UltraSparc IV+",
280 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
281 .fpu_version = 0x00000000,
282 .mmu_version = mmu_us_12,
283 .nwindows = 8,
284 .maxtl = 5,
285 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
288 .name = "Sun UltraSparc IIIi+",
289 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
290 .fpu_version = 0x00000000,
291 .mmu_version = mmu_us_3,
292 .nwindows = 8,
293 .maxtl = 5,
294 .features = CPU_DEFAULT_FEATURES,
297 .name = "Sun UltraSparc T1",
298 /* defined in sparc_ifu_fdp.v and ctu.h */
299 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
300 .fpu_version = 0x00000000,
301 .mmu_version = mmu_sun4v,
302 .nwindows = 8,
303 .maxtl = 6,
304 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
305 | CPU_FEATURE_GL,
308 .name = "Sun UltraSparc T2",
309 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
310 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
311 .fpu_version = 0x00000000,
312 .mmu_version = mmu_sun4v,
313 .nwindows = 8,
314 .maxtl = 6,
315 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
316 | CPU_FEATURE_GL,
319 .name = "NEC UltraSparc I",
320 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
321 .fpu_version = 0x00000000,
322 .mmu_version = mmu_us_12,
323 .nwindows = 8,
324 .maxtl = 5,
325 .features = CPU_DEFAULT_FEATURES,
327 #else
329 .name = "Fujitsu MB86904",
330 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
331 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
332 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
333 .mmu_bm = 0x00004000,
334 .mmu_ctpr_mask = 0x00ffffc0,
335 .mmu_cxr_mask = 0x000000ff,
336 .mmu_sfsr_mask = 0x00016fff,
337 .mmu_trcr_mask = 0x00ffffff,
338 .nwindows = 8,
339 .features = CPU_DEFAULT_FEATURES,
342 .name = "Fujitsu MB86907",
343 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
344 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
345 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
346 .mmu_bm = 0x00004000,
347 .mmu_ctpr_mask = 0xffffffc0,
348 .mmu_cxr_mask = 0x000000ff,
349 .mmu_sfsr_mask = 0x00016fff,
350 .mmu_trcr_mask = 0xffffffff,
351 .nwindows = 8,
352 .features = CPU_DEFAULT_FEATURES,
355 .name = "TI MicroSparc I",
356 .iu_version = 0x41000000,
357 .fpu_version = 4 << 17,
358 .mmu_version = 0x41000000,
359 .mmu_bm = 0x00004000,
360 .mmu_ctpr_mask = 0x007ffff0,
361 .mmu_cxr_mask = 0x0000003f,
362 .mmu_sfsr_mask = 0x00016fff,
363 .mmu_trcr_mask = 0x0000003f,
364 .nwindows = 7,
365 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
366 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
367 CPU_FEATURE_FMUL,
370 .name = "TI MicroSparc II",
371 .iu_version = 0x42000000,
372 .fpu_version = 4 << 17,
373 .mmu_version = 0x02000000,
374 .mmu_bm = 0x00004000,
375 .mmu_ctpr_mask = 0x00ffffc0,
376 .mmu_cxr_mask = 0x000000ff,
377 .mmu_sfsr_mask = 0x00016fff,
378 .mmu_trcr_mask = 0x00ffffff,
379 .nwindows = 8,
380 .features = CPU_DEFAULT_FEATURES,
383 .name = "TI MicroSparc IIep",
384 .iu_version = 0x42000000,
385 .fpu_version = 4 << 17,
386 .mmu_version = 0x04000000,
387 .mmu_bm = 0x00004000,
388 .mmu_ctpr_mask = 0x00ffffc0,
389 .mmu_cxr_mask = 0x000000ff,
390 .mmu_sfsr_mask = 0x00016bff,
391 .mmu_trcr_mask = 0x00ffffff,
392 .nwindows = 8,
393 .features = CPU_DEFAULT_FEATURES,
396 .name = "TI SuperSparc 40", /* STP1020NPGA */
397 .iu_version = 0x41000000, /* SuperSPARC 2.x */
398 .fpu_version = 0 << 17,
399 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
400 .mmu_bm = 0x00002000,
401 .mmu_ctpr_mask = 0xffffffc0,
402 .mmu_cxr_mask = 0x0000ffff,
403 .mmu_sfsr_mask = 0xffffffff,
404 .mmu_trcr_mask = 0xffffffff,
405 .nwindows = 8,
406 .features = CPU_DEFAULT_FEATURES,
409 .name = "TI SuperSparc 50", /* STP1020PGA */
410 .iu_version = 0x40000000, /* SuperSPARC 3.x */
411 .fpu_version = 0 << 17,
412 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
413 .mmu_bm = 0x00002000,
414 .mmu_ctpr_mask = 0xffffffc0,
415 .mmu_cxr_mask = 0x0000ffff,
416 .mmu_sfsr_mask = 0xffffffff,
417 .mmu_trcr_mask = 0xffffffff,
418 .nwindows = 8,
419 .features = CPU_DEFAULT_FEATURES,
422 .name = "TI SuperSparc 51",
423 .iu_version = 0x40000000, /* SuperSPARC 3.x */
424 .fpu_version = 0 << 17,
425 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
426 .mmu_bm = 0x00002000,
427 .mmu_ctpr_mask = 0xffffffc0,
428 .mmu_cxr_mask = 0x0000ffff,
429 .mmu_sfsr_mask = 0xffffffff,
430 .mmu_trcr_mask = 0xffffffff,
431 .mxcc_version = 0x00000104,
432 .nwindows = 8,
433 .features = CPU_DEFAULT_FEATURES,
436 .name = "TI SuperSparc 60", /* STP1020APGA */
437 .iu_version = 0x40000000, /* SuperSPARC 3.x */
438 .fpu_version = 0 << 17,
439 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
440 .mmu_bm = 0x00002000,
441 .mmu_ctpr_mask = 0xffffffc0,
442 .mmu_cxr_mask = 0x0000ffff,
443 .mmu_sfsr_mask = 0xffffffff,
444 .mmu_trcr_mask = 0xffffffff,
445 .nwindows = 8,
446 .features = CPU_DEFAULT_FEATURES,
449 .name = "TI SuperSparc 61",
450 .iu_version = 0x44000000, /* SuperSPARC 3.x */
451 .fpu_version = 0 << 17,
452 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
453 .mmu_bm = 0x00002000,
454 .mmu_ctpr_mask = 0xffffffc0,
455 .mmu_cxr_mask = 0x0000ffff,
456 .mmu_sfsr_mask = 0xffffffff,
457 .mmu_trcr_mask = 0xffffffff,
458 .mxcc_version = 0x00000104,
459 .nwindows = 8,
460 .features = CPU_DEFAULT_FEATURES,
463 .name = "TI SuperSparc II",
464 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
465 .fpu_version = 0 << 17,
466 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
467 .mmu_bm = 0x00002000,
468 .mmu_ctpr_mask = 0xffffffc0,
469 .mmu_cxr_mask = 0x0000ffff,
470 .mmu_sfsr_mask = 0xffffffff,
471 .mmu_trcr_mask = 0xffffffff,
472 .mxcc_version = 0x00000104,
473 .nwindows = 8,
474 .features = CPU_DEFAULT_FEATURES,
477 .name = "LEON2",
478 .iu_version = 0xf2000000,
479 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
480 .mmu_version = 0xf2000000,
481 .mmu_bm = 0x00004000,
482 .mmu_ctpr_mask = 0x007ffff0,
483 .mmu_cxr_mask = 0x0000003f,
484 .mmu_sfsr_mask = 0xffffffff,
485 .mmu_trcr_mask = 0xffffffff,
486 .nwindows = 8,
487 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
490 .name = "LEON3",
491 .iu_version = 0xf3000000,
492 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
493 .mmu_version = 0xf3000000,
494 .mmu_bm = 0x00000000,
495 .mmu_ctpr_mask = 0xfffffffc,
496 .mmu_cxr_mask = 0x000000ff,
497 .mmu_sfsr_mask = 0xffffffff,
498 .mmu_trcr_mask = 0xffffffff,
499 .nwindows = 8,
500 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
501 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
502 CPU_FEATURE_CASA,
504 #endif
507 static const char * const feature_name[] = {
508 "float",
509 "float128",
510 "swap",
511 "mul",
512 "div",
513 "flush",
514 "fsqrt",
515 "fmul",
516 "vis1",
517 "vis2",
518 "fsmuld",
519 "hypv",
520 "cmt",
521 "gl",
524 static void print_features(FILE *f, fprintf_function cpu_fprintf,
525 uint32_t features, const char *prefix)
527 unsigned int i;
529 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
530 if (feature_name[i] && (features & (1 << i))) {
531 if (prefix) {
532 (*cpu_fprintf)(f, "%s", prefix);
534 (*cpu_fprintf)(f, "%s ", feature_name[i]);
539 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
541 unsigned int i;
543 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
544 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
545 *features |= 1 << i;
546 return;
549 error_report("CPU feature %s not found", flagname);
552 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
554 unsigned int i;
555 const sparc_def_t *def = NULL;
557 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
558 if (strcasecmp(name, sparc_defs[i].name) == 0) {
559 def = &sparc_defs[i];
562 if (!def) {
563 return -1;
565 memcpy(cpu_def, def, sizeof(*def));
566 return 0;
569 static void sparc_cpu_parse_features(CPUState *cs, char *features,
570 Error **errp)
572 SPARCCPU *cpu = SPARC_CPU(cs);
573 sparc_def_t *cpu_def = cpu->env.def;
574 char *featurestr;
575 uint32_t plus_features = 0;
576 uint32_t minus_features = 0;
577 uint64_t iu_version;
578 uint32_t fpu_version, mmu_version, nwindows;
580 featurestr = features ? strtok(features, ",") : NULL;
581 while (featurestr) {
582 char *val;
584 if (featurestr[0] == '+') {
585 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
586 } else if (featurestr[0] == '-') {
587 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
588 } else if ((val = strchr(featurestr, '='))) {
589 *val = 0; val++;
590 if (!strcmp(featurestr, "iu_version")) {
591 char *err;
593 iu_version = strtoll(val, &err, 0);
594 if (!*val || *err) {
595 error_setg(errp, "bad numerical value %s", val);
596 return;
598 cpu_def->iu_version = iu_version;
599 #ifdef DEBUG_FEATURES
600 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
601 #endif
602 } else if (!strcmp(featurestr, "fpu_version")) {
603 char *err;
605 fpu_version = strtol(val, &err, 0);
606 if (!*val || *err) {
607 error_setg(errp, "bad numerical value %s", val);
608 return;
610 cpu_def->fpu_version = fpu_version;
611 #ifdef DEBUG_FEATURES
612 fprintf(stderr, "fpu_version %x\n", fpu_version);
613 #endif
614 } else if (!strcmp(featurestr, "mmu_version")) {
615 char *err;
617 mmu_version = strtol(val, &err, 0);
618 if (!*val || *err) {
619 error_setg(errp, "bad numerical value %s", val);
620 return;
622 cpu_def->mmu_version = mmu_version;
623 #ifdef DEBUG_FEATURES
624 fprintf(stderr, "mmu_version %x\n", mmu_version);
625 #endif
626 } else if (!strcmp(featurestr, "nwindows")) {
627 char *err;
629 nwindows = strtol(val, &err, 0);
630 if (!*val || *err || nwindows > MAX_NWINDOWS ||
631 nwindows < MIN_NWINDOWS) {
632 error_setg(errp, "bad numerical value %s", val);
633 return;
635 cpu_def->nwindows = nwindows;
636 #ifdef DEBUG_FEATURES
637 fprintf(stderr, "nwindows %d\n", nwindows);
638 #endif
639 } else {
640 error_setg(errp, "unrecognized feature %s", featurestr);
641 return;
643 } else {
644 error_setg(errp, "feature string `%s' not in format "
645 "(+feature|-feature|feature=xyz)", featurestr);
646 return;
648 featurestr = strtok(NULL, ",");
650 cpu_def->features |= plus_features;
651 cpu_def->features &= ~minus_features;
652 #ifdef DEBUG_FEATURES
653 print_features(stderr, fprintf, cpu_def->features, NULL);
654 #endif
657 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
659 unsigned int i;
661 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
662 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
663 " FPU %08x MMU %08x NWINS %d ",
664 sparc_defs[i].name,
665 sparc_defs[i].iu_version,
666 sparc_defs[i].fpu_version,
667 sparc_defs[i].mmu_version,
668 sparc_defs[i].nwindows);
669 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
670 ~sparc_defs[i].features, "-");
671 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
672 sparc_defs[i].features, "+");
673 (*cpu_fprintf)(f, "\n");
675 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
676 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
677 (*cpu_fprintf)(f, "\n");
678 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
679 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
680 (*cpu_fprintf)(f, "\n");
681 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
682 "fpu_version mmu_version nwindows\n");
685 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
686 uint32_t cc)
688 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
689 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
690 cc & PSR_CARRY ? 'C' : '-');
693 #ifdef TARGET_SPARC64
694 #define REGS_PER_LINE 4
695 #else
696 #define REGS_PER_LINE 8
697 #endif
699 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
700 int flags)
702 SPARCCPU *cpu = SPARC_CPU(cs);
703 CPUSPARCState *env = &cpu->env;
704 int i, x;
706 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
707 env->npc);
709 for (i = 0; i < 8; i++) {
710 if (i % REGS_PER_LINE == 0) {
711 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
713 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
714 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
715 cpu_fprintf(f, "\n");
718 for (x = 0; x < 3; x++) {
719 for (i = 0; i < 8; i++) {
720 if (i % REGS_PER_LINE == 0) {
721 cpu_fprintf(f, "%%%c%d-%d: ",
722 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
723 i, i + REGS_PER_LINE - 1);
725 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
726 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
727 cpu_fprintf(f, "\n");
732 for (i = 0; i < TARGET_DPREGS; i++) {
733 if ((i & 3) == 0) {
734 cpu_fprintf(f, "%%f%02d: ", i * 2);
736 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
737 if ((i & 3) == 3) {
738 cpu_fprintf(f, "\n");
741 #ifdef TARGET_SPARC64
742 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
743 (unsigned)cpu_get_ccr(env));
744 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
745 cpu_fprintf(f, " xcc: ");
746 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
747 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
748 env->psrpil);
749 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
750 "cleanwin: %d cwp: %d\n",
751 env->cansave, env->canrestore, env->otherwin, env->wstate,
752 env->cleanwin, env->nwindows - 1 - env->cwp);
753 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
754 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
755 #else
756 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
757 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
758 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
759 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
760 env->wim);
761 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
762 env->fsr, env->y);
763 #endif
764 cpu_fprintf(f, "\n");
767 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
769 SPARCCPU *cpu = SPARC_CPU(cs);
771 cpu->env.pc = value;
772 cpu->env.npc = value + 4;
775 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
777 SPARCCPU *cpu = SPARC_CPU(cs);
779 cpu->env.pc = tb->pc;
780 cpu->env.npc = tb->cs_base;
783 static bool sparc_cpu_has_work(CPUState *cs)
785 SPARCCPU *cpu = SPARC_CPU(cs);
786 CPUSPARCState *env = &cpu->env;
788 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
789 cpu_interrupts_enabled(env);
792 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
794 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
795 #if defined(CONFIG_USER_ONLY)
796 SPARCCPU *cpu = SPARC_CPU(dev);
797 CPUSPARCState *env = &cpu->env;
799 if ((env->def->features & CPU_FEATURE_FLOAT)) {
800 env->def->features |= CPU_FEATURE_FLOAT128;
802 #endif
804 qemu_init_vcpu(CPU(dev));
806 scc->parent_realize(dev, errp);
809 static void sparc_cpu_initfn(Object *obj)
811 CPUState *cs = CPU(obj);
812 SPARCCPU *cpu = SPARC_CPU(obj);
813 CPUSPARCState *env = &cpu->env;
815 cs->env_ptr = env;
816 cpu_exec_init(cs, &error_abort);
818 if (tcg_enabled()) {
819 gen_intermediate_code_init(env);
823 static void sparc_cpu_uninitfn(Object *obj)
825 SPARCCPU *cpu = SPARC_CPU(obj);
826 CPUSPARCState *env = &cpu->env;
828 g_free(env->def);
831 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
833 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
834 CPUClass *cc = CPU_CLASS(oc);
835 DeviceClass *dc = DEVICE_CLASS(oc);
837 scc->parent_realize = dc->realize;
838 dc->realize = sparc_cpu_realizefn;
840 scc->parent_reset = cc->reset;
841 cc->reset = sparc_cpu_reset;
843 cc->parse_features = sparc_cpu_parse_features;
844 cc->has_work = sparc_cpu_has_work;
845 cc->do_interrupt = sparc_cpu_do_interrupt;
846 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
847 cc->dump_state = sparc_cpu_dump_state;
848 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
849 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
850 #endif
851 cc->set_pc = sparc_cpu_set_pc;
852 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
853 cc->gdb_read_register = sparc_cpu_gdb_read_register;
854 cc->gdb_write_register = sparc_cpu_gdb_write_register;
855 #ifdef CONFIG_USER_ONLY
856 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
857 #else
858 cc->do_unassigned_access = sparc_cpu_unassigned_access;
859 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
860 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
861 cc->vmsd = &vmstate_sparc_cpu;
862 #endif
863 cc->disas_set_info = cpu_sparc_disas_set_info;
865 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
866 cc->gdb_num_core_regs = 86;
867 #else
868 cc->gdb_num_core_regs = 72;
869 #endif
872 * Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
873 * the object in cpus -> dangling pointer after final
874 * object_unref().
876 dc->cannot_destroy_with_object_finalize_yet = true;
879 static const TypeInfo sparc_cpu_type_info = {
880 .name = TYPE_SPARC_CPU,
881 .parent = TYPE_CPU,
882 .instance_size = sizeof(SPARCCPU),
883 .instance_init = sparc_cpu_initfn,
884 .instance_finalize = sparc_cpu_uninitfn,
885 .abstract = false,
886 .class_size = sizeof(SPARCCPUClass),
887 .class_init = sparc_cpu_class_init,
890 static void sparc_cpu_register_types(void)
892 type_register_static(&sparc_cpu_type_info);
895 type_init(sparc_cpu_register_types)