Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
[qemu/ar7.git] / target-sparc / cpu.c
blobd9f37e9b6a19dde1a30abacd8ea35f97a7a36810
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 int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
75 CPUClass *cc = CPU_GET_CLASS(cpu);
76 CPUSPARCState *env = &cpu->env;
77 char *s = g_strdup(cpu_model);
78 char *featurestr, *name = strtok(s, ",");
79 sparc_def_t def1, *def = &def1;
80 Error *err = NULL;
82 if (cpu_sparc_find_by_name(def, name) < 0) {
83 g_free(s);
84 return -1;
87 env->def = g_new0(sparc_def_t, 1);
88 memcpy(env->def, def, sizeof(*def));
90 featurestr = strtok(NULL, ",");
91 cc->parse_features(CPU(cpu), featurestr, &err);
92 g_free(s);
93 if (err) {
94 error_report("%s", error_get_pretty(err));
95 error_free(err);
96 return -1;
99 env->version = def->iu_version;
100 env->fsr = def->fpu_version;
101 env->nwindows = def->nwindows;
102 #if !defined(TARGET_SPARC64)
103 env->mmuregs[0] |= def->mmu_version;
104 cpu_sparc_set_id(env, 0);
105 env->mxccregs[7] |= def->mxcc_version;
106 #else
107 env->mmu_version = def->mmu_version;
108 env->maxtl = def->maxtl;
109 env->version |= def->maxtl << 8;
110 env->version |= def->nwindows - 1;
111 #endif
112 return 0;
115 SPARCCPU *cpu_sparc_init(const char *cpu_model)
117 SPARCCPU *cpu;
119 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
121 if (cpu_sparc_register(cpu, cpu_model) < 0) {
122 object_unref(OBJECT(cpu));
123 return NULL;
126 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
128 return cpu;
131 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
133 #if !defined(TARGET_SPARC64)
134 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
135 #endif
138 static const sparc_def_t sparc_defs[] = {
139 #ifdef TARGET_SPARC64
141 .name = "Fujitsu Sparc64",
142 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
143 .fpu_version = 0x00000000,
144 .mmu_version = mmu_us_12,
145 .nwindows = 4,
146 .maxtl = 4,
147 .features = CPU_DEFAULT_FEATURES,
150 .name = "Fujitsu Sparc64 III",
151 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
152 .fpu_version = 0x00000000,
153 .mmu_version = mmu_us_12,
154 .nwindows = 5,
155 .maxtl = 4,
156 .features = CPU_DEFAULT_FEATURES,
159 .name = "Fujitsu Sparc64 IV",
160 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
161 .fpu_version = 0x00000000,
162 .mmu_version = mmu_us_12,
163 .nwindows = 8,
164 .maxtl = 5,
165 .features = CPU_DEFAULT_FEATURES,
168 .name = "Fujitsu Sparc64 V",
169 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
170 .fpu_version = 0x00000000,
171 .mmu_version = mmu_us_12,
172 .nwindows = 8,
173 .maxtl = 5,
174 .features = CPU_DEFAULT_FEATURES,
177 .name = "TI UltraSparc I",
178 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
179 .fpu_version = 0x00000000,
180 .mmu_version = mmu_us_12,
181 .nwindows = 8,
182 .maxtl = 5,
183 .features = CPU_DEFAULT_FEATURES,
186 .name = "TI UltraSparc II",
187 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
188 .fpu_version = 0x00000000,
189 .mmu_version = mmu_us_12,
190 .nwindows = 8,
191 .maxtl = 5,
192 .features = CPU_DEFAULT_FEATURES,
195 .name = "TI UltraSparc IIi",
196 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
197 .fpu_version = 0x00000000,
198 .mmu_version = mmu_us_12,
199 .nwindows = 8,
200 .maxtl = 5,
201 .features = CPU_DEFAULT_FEATURES,
204 .name = "TI UltraSparc IIe",
205 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
206 .fpu_version = 0x00000000,
207 .mmu_version = mmu_us_12,
208 .nwindows = 8,
209 .maxtl = 5,
210 .features = CPU_DEFAULT_FEATURES,
213 .name = "Sun UltraSparc III",
214 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
215 .fpu_version = 0x00000000,
216 .mmu_version = mmu_us_12,
217 .nwindows = 8,
218 .maxtl = 5,
219 .features = CPU_DEFAULT_FEATURES,
222 .name = "Sun UltraSparc III Cu",
223 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
224 .fpu_version = 0x00000000,
225 .mmu_version = mmu_us_3,
226 .nwindows = 8,
227 .maxtl = 5,
228 .features = CPU_DEFAULT_FEATURES,
231 .name = "Sun UltraSparc IIIi",
232 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
233 .fpu_version = 0x00000000,
234 .mmu_version = mmu_us_12,
235 .nwindows = 8,
236 .maxtl = 5,
237 .features = CPU_DEFAULT_FEATURES,
240 .name = "Sun UltraSparc IV",
241 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
242 .fpu_version = 0x00000000,
243 .mmu_version = mmu_us_4,
244 .nwindows = 8,
245 .maxtl = 5,
246 .features = CPU_DEFAULT_FEATURES,
249 .name = "Sun UltraSparc IV+",
250 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
251 .fpu_version = 0x00000000,
252 .mmu_version = mmu_us_12,
253 .nwindows = 8,
254 .maxtl = 5,
255 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
258 .name = "Sun UltraSparc IIIi+",
259 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
260 .fpu_version = 0x00000000,
261 .mmu_version = mmu_us_3,
262 .nwindows = 8,
263 .maxtl = 5,
264 .features = CPU_DEFAULT_FEATURES,
267 .name = "Sun UltraSparc T1",
268 /* defined in sparc_ifu_fdp.v and ctu.h */
269 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
270 .fpu_version = 0x00000000,
271 .mmu_version = mmu_sun4v,
272 .nwindows = 8,
273 .maxtl = 6,
274 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
275 | CPU_FEATURE_GL,
278 .name = "Sun UltraSparc T2",
279 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
280 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
281 .fpu_version = 0x00000000,
282 .mmu_version = mmu_sun4v,
283 .nwindows = 8,
284 .maxtl = 6,
285 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
286 | CPU_FEATURE_GL,
289 .name = "NEC UltraSparc I",
290 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
291 .fpu_version = 0x00000000,
292 .mmu_version = mmu_us_12,
293 .nwindows = 8,
294 .maxtl = 5,
295 .features = CPU_DEFAULT_FEATURES,
297 #else
299 .name = "Fujitsu MB86904",
300 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
301 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
302 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
303 .mmu_bm = 0x00004000,
304 .mmu_ctpr_mask = 0x00ffffc0,
305 .mmu_cxr_mask = 0x000000ff,
306 .mmu_sfsr_mask = 0x00016fff,
307 .mmu_trcr_mask = 0x00ffffff,
308 .nwindows = 8,
309 .features = CPU_DEFAULT_FEATURES,
312 .name = "Fujitsu MB86907",
313 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
314 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
315 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
316 .mmu_bm = 0x00004000,
317 .mmu_ctpr_mask = 0xffffffc0,
318 .mmu_cxr_mask = 0x000000ff,
319 .mmu_sfsr_mask = 0x00016fff,
320 .mmu_trcr_mask = 0xffffffff,
321 .nwindows = 8,
322 .features = CPU_DEFAULT_FEATURES,
325 .name = "TI MicroSparc I",
326 .iu_version = 0x41000000,
327 .fpu_version = 4 << 17,
328 .mmu_version = 0x41000000,
329 .mmu_bm = 0x00004000,
330 .mmu_ctpr_mask = 0x007ffff0,
331 .mmu_cxr_mask = 0x0000003f,
332 .mmu_sfsr_mask = 0x00016fff,
333 .mmu_trcr_mask = 0x0000003f,
334 .nwindows = 7,
335 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
336 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
337 CPU_FEATURE_FMUL,
340 .name = "TI MicroSparc II",
341 .iu_version = 0x42000000,
342 .fpu_version = 4 << 17,
343 .mmu_version = 0x02000000,
344 .mmu_bm = 0x00004000,
345 .mmu_ctpr_mask = 0x00ffffc0,
346 .mmu_cxr_mask = 0x000000ff,
347 .mmu_sfsr_mask = 0x00016fff,
348 .mmu_trcr_mask = 0x00ffffff,
349 .nwindows = 8,
350 .features = CPU_DEFAULT_FEATURES,
353 .name = "TI MicroSparc IIep",
354 .iu_version = 0x42000000,
355 .fpu_version = 4 << 17,
356 .mmu_version = 0x04000000,
357 .mmu_bm = 0x00004000,
358 .mmu_ctpr_mask = 0x00ffffc0,
359 .mmu_cxr_mask = 0x000000ff,
360 .mmu_sfsr_mask = 0x00016bff,
361 .mmu_trcr_mask = 0x00ffffff,
362 .nwindows = 8,
363 .features = CPU_DEFAULT_FEATURES,
366 .name = "TI SuperSparc 40", /* STP1020NPGA */
367 .iu_version = 0x41000000, /* SuperSPARC 2.x */
368 .fpu_version = 0 << 17,
369 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
370 .mmu_bm = 0x00002000,
371 .mmu_ctpr_mask = 0xffffffc0,
372 .mmu_cxr_mask = 0x0000ffff,
373 .mmu_sfsr_mask = 0xffffffff,
374 .mmu_trcr_mask = 0xffffffff,
375 .nwindows = 8,
376 .features = CPU_DEFAULT_FEATURES,
379 .name = "TI SuperSparc 50", /* STP1020PGA */
380 .iu_version = 0x40000000, /* SuperSPARC 3.x */
381 .fpu_version = 0 << 17,
382 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
383 .mmu_bm = 0x00002000,
384 .mmu_ctpr_mask = 0xffffffc0,
385 .mmu_cxr_mask = 0x0000ffff,
386 .mmu_sfsr_mask = 0xffffffff,
387 .mmu_trcr_mask = 0xffffffff,
388 .nwindows = 8,
389 .features = CPU_DEFAULT_FEATURES,
392 .name = "TI SuperSparc 51",
393 .iu_version = 0x40000000, /* SuperSPARC 3.x */
394 .fpu_version = 0 << 17,
395 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
396 .mmu_bm = 0x00002000,
397 .mmu_ctpr_mask = 0xffffffc0,
398 .mmu_cxr_mask = 0x0000ffff,
399 .mmu_sfsr_mask = 0xffffffff,
400 .mmu_trcr_mask = 0xffffffff,
401 .mxcc_version = 0x00000104,
402 .nwindows = 8,
403 .features = CPU_DEFAULT_FEATURES,
406 .name = "TI SuperSparc 60", /* STP1020APGA */
407 .iu_version = 0x40000000, /* SuperSPARC 3.x */
408 .fpu_version = 0 << 17,
409 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
410 .mmu_bm = 0x00002000,
411 .mmu_ctpr_mask = 0xffffffc0,
412 .mmu_cxr_mask = 0x0000ffff,
413 .mmu_sfsr_mask = 0xffffffff,
414 .mmu_trcr_mask = 0xffffffff,
415 .nwindows = 8,
416 .features = CPU_DEFAULT_FEATURES,
419 .name = "TI SuperSparc 61",
420 .iu_version = 0x44000000, /* SuperSPARC 3.x */
421 .fpu_version = 0 << 17,
422 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
423 .mmu_bm = 0x00002000,
424 .mmu_ctpr_mask = 0xffffffc0,
425 .mmu_cxr_mask = 0x0000ffff,
426 .mmu_sfsr_mask = 0xffffffff,
427 .mmu_trcr_mask = 0xffffffff,
428 .mxcc_version = 0x00000104,
429 .nwindows = 8,
430 .features = CPU_DEFAULT_FEATURES,
433 .name = "TI SuperSparc II",
434 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
435 .fpu_version = 0 << 17,
436 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
437 .mmu_bm = 0x00002000,
438 .mmu_ctpr_mask = 0xffffffc0,
439 .mmu_cxr_mask = 0x0000ffff,
440 .mmu_sfsr_mask = 0xffffffff,
441 .mmu_trcr_mask = 0xffffffff,
442 .mxcc_version = 0x00000104,
443 .nwindows = 8,
444 .features = CPU_DEFAULT_FEATURES,
447 .name = "LEON2",
448 .iu_version = 0xf2000000,
449 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
450 .mmu_version = 0xf2000000,
451 .mmu_bm = 0x00004000,
452 .mmu_ctpr_mask = 0x007ffff0,
453 .mmu_cxr_mask = 0x0000003f,
454 .mmu_sfsr_mask = 0xffffffff,
455 .mmu_trcr_mask = 0xffffffff,
456 .nwindows = 8,
457 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
460 .name = "LEON3",
461 .iu_version = 0xf3000000,
462 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
463 .mmu_version = 0xf3000000,
464 .mmu_bm = 0x00000000,
465 .mmu_ctpr_mask = 0xfffffffc,
466 .mmu_cxr_mask = 0x000000ff,
467 .mmu_sfsr_mask = 0xffffffff,
468 .mmu_trcr_mask = 0xffffffff,
469 .nwindows = 8,
470 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
471 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
472 CPU_FEATURE_CASA,
474 #endif
477 static const char * const feature_name[] = {
478 "float",
479 "float128",
480 "swap",
481 "mul",
482 "div",
483 "flush",
484 "fsqrt",
485 "fmul",
486 "vis1",
487 "vis2",
488 "fsmuld",
489 "hypv",
490 "cmt",
491 "gl",
494 static void print_features(FILE *f, fprintf_function cpu_fprintf,
495 uint32_t features, const char *prefix)
497 unsigned int i;
499 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
500 if (feature_name[i] && (features & (1 << i))) {
501 if (prefix) {
502 (*cpu_fprintf)(f, "%s", prefix);
504 (*cpu_fprintf)(f, "%s ", feature_name[i]);
509 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
511 unsigned int i;
513 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
514 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
515 *features |= 1 << i;
516 return;
519 error_report("CPU feature %s not found", flagname);
522 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
524 unsigned int i;
525 const sparc_def_t *def = NULL;
527 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
528 if (strcasecmp(name, sparc_defs[i].name) == 0) {
529 def = &sparc_defs[i];
532 if (!def) {
533 return -1;
535 memcpy(cpu_def, def, sizeof(*def));
536 return 0;
539 static void sparc_cpu_parse_features(CPUState *cs, char *features,
540 Error **errp)
542 SPARCCPU *cpu = SPARC_CPU(cs);
543 sparc_def_t *cpu_def = cpu->env.def;
544 char *featurestr;
545 uint32_t plus_features = 0;
546 uint32_t minus_features = 0;
547 uint64_t iu_version;
548 uint32_t fpu_version, mmu_version, nwindows;
550 featurestr = features ? strtok(features, ",") : NULL;
551 while (featurestr) {
552 char *val;
554 if (featurestr[0] == '+') {
555 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
556 } else if (featurestr[0] == '-') {
557 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
558 } else if ((val = strchr(featurestr, '='))) {
559 *val = 0; val++;
560 if (!strcmp(featurestr, "iu_version")) {
561 char *err;
563 iu_version = strtoll(val, &err, 0);
564 if (!*val || *err) {
565 error_setg(errp, "bad numerical value %s", val);
566 return;
568 cpu_def->iu_version = iu_version;
569 #ifdef DEBUG_FEATURES
570 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
571 #endif
572 } else if (!strcmp(featurestr, "fpu_version")) {
573 char *err;
575 fpu_version = strtol(val, &err, 0);
576 if (!*val || *err) {
577 error_setg(errp, "bad numerical value %s", val);
578 return;
580 cpu_def->fpu_version = fpu_version;
581 #ifdef DEBUG_FEATURES
582 fprintf(stderr, "fpu_version %x\n", fpu_version);
583 #endif
584 } else if (!strcmp(featurestr, "mmu_version")) {
585 char *err;
587 mmu_version = strtol(val, &err, 0);
588 if (!*val || *err) {
589 error_setg(errp, "bad numerical value %s", val);
590 return;
592 cpu_def->mmu_version = mmu_version;
593 #ifdef DEBUG_FEATURES
594 fprintf(stderr, "mmu_version %x\n", mmu_version);
595 #endif
596 } else if (!strcmp(featurestr, "nwindows")) {
597 char *err;
599 nwindows = strtol(val, &err, 0);
600 if (!*val || *err || nwindows > MAX_NWINDOWS ||
601 nwindows < MIN_NWINDOWS) {
602 error_setg(errp, "bad numerical value %s", val);
603 return;
605 cpu_def->nwindows = nwindows;
606 #ifdef DEBUG_FEATURES
607 fprintf(stderr, "nwindows %d\n", nwindows);
608 #endif
609 } else {
610 error_setg(errp, "unrecognized feature %s", featurestr);
611 return;
613 } else {
614 error_setg(errp, "feature string `%s' not in format "
615 "(+feature|-feature|feature=xyz)", featurestr);
616 return;
618 featurestr = strtok(NULL, ",");
620 cpu_def->features |= plus_features;
621 cpu_def->features &= ~minus_features;
622 #ifdef DEBUG_FEATURES
623 print_features(stderr, fprintf, cpu_def->features, NULL);
624 #endif
627 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
629 unsigned int i;
631 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
632 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
633 " FPU %08x MMU %08x NWINS %d ",
634 sparc_defs[i].name,
635 sparc_defs[i].iu_version,
636 sparc_defs[i].fpu_version,
637 sparc_defs[i].mmu_version,
638 sparc_defs[i].nwindows);
639 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
640 ~sparc_defs[i].features, "-");
641 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
642 sparc_defs[i].features, "+");
643 (*cpu_fprintf)(f, "\n");
645 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
646 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
647 (*cpu_fprintf)(f, "\n");
648 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
649 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
650 (*cpu_fprintf)(f, "\n");
651 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
652 "fpu_version mmu_version nwindows\n");
655 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
656 uint32_t cc)
658 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
659 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
660 cc & PSR_CARRY ? 'C' : '-');
663 #ifdef TARGET_SPARC64
664 #define REGS_PER_LINE 4
665 #else
666 #define REGS_PER_LINE 8
667 #endif
669 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
670 int flags)
672 SPARCCPU *cpu = SPARC_CPU(cs);
673 CPUSPARCState *env = &cpu->env;
674 int i, x;
676 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
677 env->npc);
679 for (i = 0; i < 8; i++) {
680 if (i % REGS_PER_LINE == 0) {
681 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
683 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
684 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
685 cpu_fprintf(f, "\n");
688 for (x = 0; x < 3; x++) {
689 for (i = 0; i < 8; i++) {
690 if (i % REGS_PER_LINE == 0) {
691 cpu_fprintf(f, "%%%c%d-%d: ",
692 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
693 i, i + REGS_PER_LINE - 1);
695 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
696 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
697 cpu_fprintf(f, "\n");
702 for (i = 0; i < TARGET_DPREGS; i++) {
703 if ((i & 3) == 0) {
704 cpu_fprintf(f, "%%f%02d: ", i * 2);
706 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
707 if ((i & 3) == 3) {
708 cpu_fprintf(f, "\n");
711 #ifdef TARGET_SPARC64
712 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
713 (unsigned)cpu_get_ccr(env));
714 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
715 cpu_fprintf(f, " xcc: ");
716 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
717 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
718 env->psrpil);
719 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
720 "cleanwin: %d cwp: %d\n",
721 env->cansave, env->canrestore, env->otherwin, env->wstate,
722 env->cleanwin, env->nwindows - 1 - env->cwp);
723 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
724 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
725 #else
726 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
727 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
728 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
729 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
730 env->wim);
731 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
732 env->fsr, env->y);
733 #endif
734 cpu_fprintf(f, "\n");
737 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
739 SPARCCPU *cpu = SPARC_CPU(cs);
741 cpu->env.pc = value;
742 cpu->env.npc = value + 4;
745 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
747 SPARCCPU *cpu = SPARC_CPU(cs);
749 cpu->env.pc = tb->pc;
750 cpu->env.npc = tb->cs_base;
753 static bool sparc_cpu_has_work(CPUState *cs)
755 SPARCCPU *cpu = SPARC_CPU(cs);
756 CPUSPARCState *env = &cpu->env;
758 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
759 cpu_interrupts_enabled(env);
762 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
764 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
765 #if defined(CONFIG_USER_ONLY)
766 SPARCCPU *cpu = SPARC_CPU(dev);
767 CPUSPARCState *env = &cpu->env;
769 if ((env->def->features & CPU_FEATURE_FLOAT)) {
770 env->def->features |= CPU_FEATURE_FLOAT128;
772 #endif
774 qemu_init_vcpu(CPU(dev));
776 scc->parent_realize(dev, errp);
779 static void sparc_cpu_initfn(Object *obj)
781 CPUState *cs = CPU(obj);
782 SPARCCPU *cpu = SPARC_CPU(obj);
783 CPUSPARCState *env = &cpu->env;
785 cs->env_ptr = env;
786 cpu_exec_init(env);
788 if (tcg_enabled()) {
789 gen_intermediate_code_init(env);
793 static void sparc_cpu_uninitfn(Object *obj)
795 SPARCCPU *cpu = SPARC_CPU(obj);
796 CPUSPARCState *env = &cpu->env;
798 g_free(env->def);
801 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
803 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
804 CPUClass *cc = CPU_CLASS(oc);
805 DeviceClass *dc = DEVICE_CLASS(oc);
807 scc->parent_realize = dc->realize;
808 dc->realize = sparc_cpu_realizefn;
810 scc->parent_reset = cc->reset;
811 cc->reset = sparc_cpu_reset;
813 cc->parse_features = sparc_cpu_parse_features;
814 cc->has_work = sparc_cpu_has_work;
815 cc->do_interrupt = sparc_cpu_do_interrupt;
816 cc->dump_state = sparc_cpu_dump_state;
817 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
818 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
819 #endif
820 cc->set_pc = sparc_cpu_set_pc;
821 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
822 cc->gdb_read_register = sparc_cpu_gdb_read_register;
823 cc->gdb_write_register = sparc_cpu_gdb_write_register;
824 #ifdef CONFIG_USER_ONLY
825 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
826 #else
827 cc->do_unassigned_access = sparc_cpu_unassigned_access;
828 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
829 #endif
831 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
832 cc->gdb_num_core_regs = 86;
833 #else
834 cc->gdb_num_core_regs = 72;
835 #endif
838 static const TypeInfo sparc_cpu_type_info = {
839 .name = TYPE_SPARC_CPU,
840 .parent = TYPE_CPU,
841 .instance_size = sizeof(SPARCCPU),
842 .instance_init = sparc_cpu_initfn,
843 .instance_finalize = sparc_cpu_uninitfn,
844 .abstract = false,
845 .class_size = sizeof(SPARCCPUClass),
846 .class_init = sparc_cpu_class_init,
849 static void sparc_cpu_register_types(void)
851 type_register_static(&sparc_cpu_type_info);
854 type_init(sparc_cpu_register_types)