iotests: 124: Split into two test classes
[qemu/ar7.git] / target-sparc / cpu.c
blobd98682b563e37aa472cb772534d08a5396f212ef
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 void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
95 info->print_insn = print_insn_sparc;
96 #ifdef TARGET_SPARC64
97 info->mach = bfd_mach_sparc_v9b;
98 #endif
101 static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
103 CPUClass *cc = CPU_GET_CLASS(cpu);
104 CPUSPARCState *env = &cpu->env;
105 char *s = g_strdup(cpu_model);
106 char *featurestr, *name = strtok(s, ",");
107 sparc_def_t def1, *def = &def1;
108 Error *err = NULL;
110 if (cpu_sparc_find_by_name(def, name) < 0) {
111 g_free(s);
112 return -1;
115 env->def = g_new0(sparc_def_t, 1);
116 memcpy(env->def, def, sizeof(*def));
118 featurestr = strtok(NULL, ",");
119 cc->parse_features(CPU(cpu), featurestr, &err);
120 g_free(s);
121 if (err) {
122 error_report_err(err);
123 return -1;
126 env->version = def->iu_version;
127 env->fsr = def->fpu_version;
128 env->nwindows = def->nwindows;
129 #if !defined(TARGET_SPARC64)
130 env->mmuregs[0] |= def->mmu_version;
131 cpu_sparc_set_id(env, 0);
132 env->mxccregs[7] |= def->mxcc_version;
133 #else
134 env->mmu_version = def->mmu_version;
135 env->maxtl = def->maxtl;
136 env->version |= def->maxtl << 8;
137 env->version |= def->nwindows - 1;
138 #endif
139 return 0;
142 SPARCCPU *cpu_sparc_init(const char *cpu_model)
144 SPARCCPU *cpu;
146 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
148 if (cpu_sparc_register(cpu, cpu_model) < 0) {
149 object_unref(OBJECT(cpu));
150 return NULL;
153 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
155 return cpu;
158 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
160 #if !defined(TARGET_SPARC64)
161 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
162 #endif
165 static const sparc_def_t sparc_defs[] = {
166 #ifdef TARGET_SPARC64
168 .name = "Fujitsu Sparc64",
169 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
170 .fpu_version = 0x00000000,
171 .mmu_version = mmu_us_12,
172 .nwindows = 4,
173 .maxtl = 4,
174 .features = CPU_DEFAULT_FEATURES,
177 .name = "Fujitsu Sparc64 III",
178 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
179 .fpu_version = 0x00000000,
180 .mmu_version = mmu_us_12,
181 .nwindows = 5,
182 .maxtl = 4,
183 .features = CPU_DEFAULT_FEATURES,
186 .name = "Fujitsu Sparc64 IV",
187 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
188 .fpu_version = 0x00000000,
189 .mmu_version = mmu_us_12,
190 .nwindows = 8,
191 .maxtl = 5,
192 .features = CPU_DEFAULT_FEATURES,
195 .name = "Fujitsu Sparc64 V",
196 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 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 I",
205 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
206 .fpu_version = 0x00000000,
207 .mmu_version = mmu_us_12,
208 .nwindows = 8,
209 .maxtl = 5,
210 .features = CPU_DEFAULT_FEATURES,
213 .name = "TI UltraSparc II",
214 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
215 .fpu_version = 0x00000000,
216 .mmu_version = mmu_us_12,
217 .nwindows = 8,
218 .maxtl = 5,
219 .features = CPU_DEFAULT_FEATURES,
222 .name = "TI UltraSparc IIi",
223 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
224 .fpu_version = 0x00000000,
225 .mmu_version = mmu_us_12,
226 .nwindows = 8,
227 .maxtl = 5,
228 .features = CPU_DEFAULT_FEATURES,
231 .name = "TI UltraSparc IIe",
232 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 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 III",
241 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
242 .fpu_version = 0x00000000,
243 .mmu_version = mmu_us_12,
244 .nwindows = 8,
245 .maxtl = 5,
246 .features = CPU_DEFAULT_FEATURES,
249 .name = "Sun UltraSparc III Cu",
250 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
251 .fpu_version = 0x00000000,
252 .mmu_version = mmu_us_3,
253 .nwindows = 8,
254 .maxtl = 5,
255 .features = CPU_DEFAULT_FEATURES,
258 .name = "Sun UltraSparc IIIi",
259 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
260 .fpu_version = 0x00000000,
261 .mmu_version = mmu_us_12,
262 .nwindows = 8,
263 .maxtl = 5,
264 .features = CPU_DEFAULT_FEATURES,
267 .name = "Sun UltraSparc IV",
268 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
269 .fpu_version = 0x00000000,
270 .mmu_version = mmu_us_4,
271 .nwindows = 8,
272 .maxtl = 5,
273 .features = CPU_DEFAULT_FEATURES,
276 .name = "Sun UltraSparc IV+",
277 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
278 .fpu_version = 0x00000000,
279 .mmu_version = mmu_us_12,
280 .nwindows = 8,
281 .maxtl = 5,
282 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
285 .name = "Sun UltraSparc IIIi+",
286 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
287 .fpu_version = 0x00000000,
288 .mmu_version = mmu_us_3,
289 .nwindows = 8,
290 .maxtl = 5,
291 .features = CPU_DEFAULT_FEATURES,
294 .name = "Sun UltraSparc T1",
295 /* defined in sparc_ifu_fdp.v and ctu.h */
296 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
297 .fpu_version = 0x00000000,
298 .mmu_version = mmu_sun4v,
299 .nwindows = 8,
300 .maxtl = 6,
301 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
302 | CPU_FEATURE_GL,
305 .name = "Sun UltraSparc T2",
306 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
307 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
308 .fpu_version = 0x00000000,
309 .mmu_version = mmu_sun4v,
310 .nwindows = 8,
311 .maxtl = 6,
312 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
313 | CPU_FEATURE_GL,
316 .name = "NEC UltraSparc I",
317 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
318 .fpu_version = 0x00000000,
319 .mmu_version = mmu_us_12,
320 .nwindows = 8,
321 .maxtl = 5,
322 .features = CPU_DEFAULT_FEATURES,
324 #else
326 .name = "Fujitsu MB86904",
327 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
328 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
329 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
330 .mmu_bm = 0x00004000,
331 .mmu_ctpr_mask = 0x00ffffc0,
332 .mmu_cxr_mask = 0x000000ff,
333 .mmu_sfsr_mask = 0x00016fff,
334 .mmu_trcr_mask = 0x00ffffff,
335 .nwindows = 8,
336 .features = CPU_DEFAULT_FEATURES,
339 .name = "Fujitsu MB86907",
340 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
341 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
342 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
343 .mmu_bm = 0x00004000,
344 .mmu_ctpr_mask = 0xffffffc0,
345 .mmu_cxr_mask = 0x000000ff,
346 .mmu_sfsr_mask = 0x00016fff,
347 .mmu_trcr_mask = 0xffffffff,
348 .nwindows = 8,
349 .features = CPU_DEFAULT_FEATURES,
352 .name = "TI MicroSparc I",
353 .iu_version = 0x41000000,
354 .fpu_version = 4 << 17,
355 .mmu_version = 0x41000000,
356 .mmu_bm = 0x00004000,
357 .mmu_ctpr_mask = 0x007ffff0,
358 .mmu_cxr_mask = 0x0000003f,
359 .mmu_sfsr_mask = 0x00016fff,
360 .mmu_trcr_mask = 0x0000003f,
361 .nwindows = 7,
362 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
363 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
364 CPU_FEATURE_FMUL,
367 .name = "TI MicroSparc II",
368 .iu_version = 0x42000000,
369 .fpu_version = 4 << 17,
370 .mmu_version = 0x02000000,
371 .mmu_bm = 0x00004000,
372 .mmu_ctpr_mask = 0x00ffffc0,
373 .mmu_cxr_mask = 0x000000ff,
374 .mmu_sfsr_mask = 0x00016fff,
375 .mmu_trcr_mask = 0x00ffffff,
376 .nwindows = 8,
377 .features = CPU_DEFAULT_FEATURES,
380 .name = "TI MicroSparc IIep",
381 .iu_version = 0x42000000,
382 .fpu_version = 4 << 17,
383 .mmu_version = 0x04000000,
384 .mmu_bm = 0x00004000,
385 .mmu_ctpr_mask = 0x00ffffc0,
386 .mmu_cxr_mask = 0x000000ff,
387 .mmu_sfsr_mask = 0x00016bff,
388 .mmu_trcr_mask = 0x00ffffff,
389 .nwindows = 8,
390 .features = CPU_DEFAULT_FEATURES,
393 .name = "TI SuperSparc 40", /* STP1020NPGA */
394 .iu_version = 0x41000000, /* SuperSPARC 2.x */
395 .fpu_version = 0 << 17,
396 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
397 .mmu_bm = 0x00002000,
398 .mmu_ctpr_mask = 0xffffffc0,
399 .mmu_cxr_mask = 0x0000ffff,
400 .mmu_sfsr_mask = 0xffffffff,
401 .mmu_trcr_mask = 0xffffffff,
402 .nwindows = 8,
403 .features = CPU_DEFAULT_FEATURES,
406 .name = "TI SuperSparc 50", /* STP1020PGA */
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 51",
420 .iu_version = 0x40000000, /* 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 60", /* STP1020APGA */
434 .iu_version = 0x40000000, /* SuperSPARC 3.x */
435 .fpu_version = 0 << 17,
436 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no 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 .nwindows = 8,
443 .features = CPU_DEFAULT_FEATURES,
446 .name = "TI SuperSparc 61",
447 .iu_version = 0x44000000, /* SuperSPARC 3.x */
448 .fpu_version = 0 << 17,
449 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
450 .mmu_bm = 0x00002000,
451 .mmu_ctpr_mask = 0xffffffc0,
452 .mmu_cxr_mask = 0x0000ffff,
453 .mmu_sfsr_mask = 0xffffffff,
454 .mmu_trcr_mask = 0xffffffff,
455 .mxcc_version = 0x00000104,
456 .nwindows = 8,
457 .features = CPU_DEFAULT_FEATURES,
460 .name = "TI SuperSparc II",
461 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
462 .fpu_version = 0 << 17,
463 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
464 .mmu_bm = 0x00002000,
465 .mmu_ctpr_mask = 0xffffffc0,
466 .mmu_cxr_mask = 0x0000ffff,
467 .mmu_sfsr_mask = 0xffffffff,
468 .mmu_trcr_mask = 0xffffffff,
469 .mxcc_version = 0x00000104,
470 .nwindows = 8,
471 .features = CPU_DEFAULT_FEATURES,
474 .name = "LEON2",
475 .iu_version = 0xf2000000,
476 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
477 .mmu_version = 0xf2000000,
478 .mmu_bm = 0x00004000,
479 .mmu_ctpr_mask = 0x007ffff0,
480 .mmu_cxr_mask = 0x0000003f,
481 .mmu_sfsr_mask = 0xffffffff,
482 .mmu_trcr_mask = 0xffffffff,
483 .nwindows = 8,
484 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
487 .name = "LEON3",
488 .iu_version = 0xf3000000,
489 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
490 .mmu_version = 0xf3000000,
491 .mmu_bm = 0x00000000,
492 .mmu_ctpr_mask = 0xfffffffc,
493 .mmu_cxr_mask = 0x000000ff,
494 .mmu_sfsr_mask = 0xffffffff,
495 .mmu_trcr_mask = 0xffffffff,
496 .nwindows = 8,
497 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
498 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
499 CPU_FEATURE_CASA,
501 #endif
504 static const char * const feature_name[] = {
505 "float",
506 "float128",
507 "swap",
508 "mul",
509 "div",
510 "flush",
511 "fsqrt",
512 "fmul",
513 "vis1",
514 "vis2",
515 "fsmuld",
516 "hypv",
517 "cmt",
518 "gl",
521 static void print_features(FILE *f, fprintf_function cpu_fprintf,
522 uint32_t features, const char *prefix)
524 unsigned int i;
526 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
527 if (feature_name[i] && (features & (1 << i))) {
528 if (prefix) {
529 (*cpu_fprintf)(f, "%s", prefix);
531 (*cpu_fprintf)(f, "%s ", feature_name[i]);
536 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
538 unsigned int i;
540 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
541 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
542 *features |= 1 << i;
543 return;
546 error_report("CPU feature %s not found", flagname);
549 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
551 unsigned int i;
552 const sparc_def_t *def = NULL;
554 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
555 if (strcasecmp(name, sparc_defs[i].name) == 0) {
556 def = &sparc_defs[i];
559 if (!def) {
560 return -1;
562 memcpy(cpu_def, def, sizeof(*def));
563 return 0;
566 static void sparc_cpu_parse_features(CPUState *cs, char *features,
567 Error **errp)
569 SPARCCPU *cpu = SPARC_CPU(cs);
570 sparc_def_t *cpu_def = cpu->env.def;
571 char *featurestr;
572 uint32_t plus_features = 0;
573 uint32_t minus_features = 0;
574 uint64_t iu_version;
575 uint32_t fpu_version, mmu_version, nwindows;
577 featurestr = features ? strtok(features, ",") : NULL;
578 while (featurestr) {
579 char *val;
581 if (featurestr[0] == '+') {
582 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
583 } else if (featurestr[0] == '-') {
584 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
585 } else if ((val = strchr(featurestr, '='))) {
586 *val = 0; val++;
587 if (!strcmp(featurestr, "iu_version")) {
588 char *err;
590 iu_version = strtoll(val, &err, 0);
591 if (!*val || *err) {
592 error_setg(errp, "bad numerical value %s", val);
593 return;
595 cpu_def->iu_version = iu_version;
596 #ifdef DEBUG_FEATURES
597 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
598 #endif
599 } else if (!strcmp(featurestr, "fpu_version")) {
600 char *err;
602 fpu_version = strtol(val, &err, 0);
603 if (!*val || *err) {
604 error_setg(errp, "bad numerical value %s", val);
605 return;
607 cpu_def->fpu_version = fpu_version;
608 #ifdef DEBUG_FEATURES
609 fprintf(stderr, "fpu_version %x\n", fpu_version);
610 #endif
611 } else if (!strcmp(featurestr, "mmu_version")) {
612 char *err;
614 mmu_version = strtol(val, &err, 0);
615 if (!*val || *err) {
616 error_setg(errp, "bad numerical value %s", val);
617 return;
619 cpu_def->mmu_version = mmu_version;
620 #ifdef DEBUG_FEATURES
621 fprintf(stderr, "mmu_version %x\n", mmu_version);
622 #endif
623 } else if (!strcmp(featurestr, "nwindows")) {
624 char *err;
626 nwindows = strtol(val, &err, 0);
627 if (!*val || *err || nwindows > MAX_NWINDOWS ||
628 nwindows < MIN_NWINDOWS) {
629 error_setg(errp, "bad numerical value %s", val);
630 return;
632 cpu_def->nwindows = nwindows;
633 #ifdef DEBUG_FEATURES
634 fprintf(stderr, "nwindows %d\n", nwindows);
635 #endif
636 } else {
637 error_setg(errp, "unrecognized feature %s", featurestr);
638 return;
640 } else {
641 error_setg(errp, "feature string `%s' not in format "
642 "(+feature|-feature|feature=xyz)", featurestr);
643 return;
645 featurestr = strtok(NULL, ",");
647 cpu_def->features |= plus_features;
648 cpu_def->features &= ~minus_features;
649 #ifdef DEBUG_FEATURES
650 print_features(stderr, fprintf, cpu_def->features, NULL);
651 #endif
654 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
656 unsigned int i;
658 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
659 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
660 " FPU %08x MMU %08x NWINS %d ",
661 sparc_defs[i].name,
662 sparc_defs[i].iu_version,
663 sparc_defs[i].fpu_version,
664 sparc_defs[i].mmu_version,
665 sparc_defs[i].nwindows);
666 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
667 ~sparc_defs[i].features, "-");
668 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
669 sparc_defs[i].features, "+");
670 (*cpu_fprintf)(f, "\n");
672 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
673 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
674 (*cpu_fprintf)(f, "\n");
675 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
676 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
677 (*cpu_fprintf)(f, "\n");
678 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
679 "fpu_version mmu_version nwindows\n");
682 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
683 uint32_t cc)
685 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
686 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
687 cc & PSR_CARRY ? 'C' : '-');
690 #ifdef TARGET_SPARC64
691 #define REGS_PER_LINE 4
692 #else
693 #define REGS_PER_LINE 8
694 #endif
696 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
697 int flags)
699 SPARCCPU *cpu = SPARC_CPU(cs);
700 CPUSPARCState *env = &cpu->env;
701 int i, x;
703 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
704 env->npc);
706 for (i = 0; i < 8; i++) {
707 if (i % REGS_PER_LINE == 0) {
708 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
710 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
711 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
712 cpu_fprintf(f, "\n");
715 for (x = 0; x < 3; x++) {
716 for (i = 0; i < 8; i++) {
717 if (i % REGS_PER_LINE == 0) {
718 cpu_fprintf(f, "%%%c%d-%d: ",
719 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
720 i, i + REGS_PER_LINE - 1);
722 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
723 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
724 cpu_fprintf(f, "\n");
729 for (i = 0; i < TARGET_DPREGS; i++) {
730 if ((i & 3) == 0) {
731 cpu_fprintf(f, "%%f%02d: ", i * 2);
733 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
734 if ((i & 3) == 3) {
735 cpu_fprintf(f, "\n");
738 #ifdef TARGET_SPARC64
739 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
740 (unsigned)cpu_get_ccr(env));
741 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
742 cpu_fprintf(f, " xcc: ");
743 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
744 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
745 env->psrpil);
746 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
747 "cleanwin: %d cwp: %d\n",
748 env->cansave, env->canrestore, env->otherwin, env->wstate,
749 env->cleanwin, env->nwindows - 1 - env->cwp);
750 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
751 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
752 #else
753 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
754 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
755 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
756 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
757 env->wim);
758 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
759 env->fsr, env->y);
760 #endif
761 cpu_fprintf(f, "\n");
764 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
766 SPARCCPU *cpu = SPARC_CPU(cs);
768 cpu->env.pc = value;
769 cpu->env.npc = value + 4;
772 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
774 SPARCCPU *cpu = SPARC_CPU(cs);
776 cpu->env.pc = tb->pc;
777 cpu->env.npc = tb->cs_base;
780 static bool sparc_cpu_has_work(CPUState *cs)
782 SPARCCPU *cpu = SPARC_CPU(cs);
783 CPUSPARCState *env = &cpu->env;
785 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
786 cpu_interrupts_enabled(env);
789 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
791 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
792 #if defined(CONFIG_USER_ONLY)
793 SPARCCPU *cpu = SPARC_CPU(dev);
794 CPUSPARCState *env = &cpu->env;
796 if ((env->def->features & CPU_FEATURE_FLOAT)) {
797 env->def->features |= CPU_FEATURE_FLOAT128;
799 #endif
801 qemu_init_vcpu(CPU(dev));
803 scc->parent_realize(dev, errp);
806 static void sparc_cpu_initfn(Object *obj)
808 CPUState *cs = CPU(obj);
809 SPARCCPU *cpu = SPARC_CPU(obj);
810 CPUSPARCState *env = &cpu->env;
812 cs->env_ptr = env;
813 cpu_exec_init(cs, &error_abort);
815 if (tcg_enabled()) {
816 gen_intermediate_code_init(env);
820 static void sparc_cpu_uninitfn(Object *obj)
822 SPARCCPU *cpu = SPARC_CPU(obj);
823 CPUSPARCState *env = &cpu->env;
825 g_free(env->def);
828 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
830 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
831 CPUClass *cc = CPU_CLASS(oc);
832 DeviceClass *dc = DEVICE_CLASS(oc);
834 scc->parent_realize = dc->realize;
835 dc->realize = sparc_cpu_realizefn;
837 scc->parent_reset = cc->reset;
838 cc->reset = sparc_cpu_reset;
840 cc->parse_features = sparc_cpu_parse_features;
841 cc->has_work = sparc_cpu_has_work;
842 cc->do_interrupt = sparc_cpu_do_interrupt;
843 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
844 cc->dump_state = sparc_cpu_dump_state;
845 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
846 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
847 #endif
848 cc->set_pc = sparc_cpu_set_pc;
849 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
850 cc->gdb_read_register = sparc_cpu_gdb_read_register;
851 cc->gdb_write_register = sparc_cpu_gdb_write_register;
852 #ifdef CONFIG_USER_ONLY
853 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
854 #else
855 cc->do_unassigned_access = sparc_cpu_unassigned_access;
856 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
857 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
858 #endif
859 cc->disas_set_info = cpu_sparc_disas_set_info;
861 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
862 cc->gdb_num_core_regs = 86;
863 #else
864 cc->gdb_num_core_regs = 72;
865 #endif
868 * Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
869 * the object in cpus -> dangling pointer after final
870 * object_unref().
872 dc->cannot_destroy_with_object_finalize_yet = true;
875 static const TypeInfo sparc_cpu_type_info = {
876 .name = TYPE_SPARC_CPU,
877 .parent = TYPE_CPU,
878 .instance_size = sizeof(SPARCCPU),
879 .instance_init = sparc_cpu_initfn,
880 .instance_finalize = sparc_cpu_uninitfn,
881 .abstract = false,
882 .class_size = sizeof(SPARCCPUClass),
883 .class_init = sparc_cpu_class_init,
886 static void sparc_cpu_register_types(void)
888 type_register_static(&sparc_cpu_type_info);
891 type_init(sparc_cpu_register_types)