Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[qemu/ar7.git] / target-sparc / cpu.c
bloba9520970964bb1672c08ff7f7fddfa7281b0d907
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_err(err);
115 return -1;
118 env->version = def->iu_version;
119 env->fsr = def->fpu_version;
120 env->nwindows = def->nwindows;
121 #if !defined(TARGET_SPARC64)
122 env->mmuregs[0] |= def->mmu_version;
123 cpu_sparc_set_id(env, 0);
124 env->mxccregs[7] |= def->mxcc_version;
125 #else
126 env->mmu_version = def->mmu_version;
127 env->maxtl = def->maxtl;
128 env->version |= def->maxtl << 8;
129 env->version |= def->nwindows - 1;
130 #endif
131 return 0;
134 SPARCCPU *cpu_sparc_init(const char *cpu_model)
136 SPARCCPU *cpu;
138 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
140 if (cpu_sparc_register(cpu, cpu_model) < 0) {
141 object_unref(OBJECT(cpu));
142 return NULL;
145 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
147 return cpu;
150 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
152 #if !defined(TARGET_SPARC64)
153 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
154 #endif
157 static const sparc_def_t sparc_defs[] = {
158 #ifdef TARGET_SPARC64
160 .name = "Fujitsu Sparc64",
161 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
162 .fpu_version = 0x00000000,
163 .mmu_version = mmu_us_12,
164 .nwindows = 4,
165 .maxtl = 4,
166 .features = CPU_DEFAULT_FEATURES,
169 .name = "Fujitsu Sparc64 III",
170 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
171 .fpu_version = 0x00000000,
172 .mmu_version = mmu_us_12,
173 .nwindows = 5,
174 .maxtl = 4,
175 .features = CPU_DEFAULT_FEATURES,
178 .name = "Fujitsu Sparc64 IV",
179 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
180 .fpu_version = 0x00000000,
181 .mmu_version = mmu_us_12,
182 .nwindows = 8,
183 .maxtl = 5,
184 .features = CPU_DEFAULT_FEATURES,
187 .name = "Fujitsu Sparc64 V",
188 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
189 .fpu_version = 0x00000000,
190 .mmu_version = mmu_us_12,
191 .nwindows = 8,
192 .maxtl = 5,
193 .features = CPU_DEFAULT_FEATURES,
196 .name = "TI UltraSparc I",
197 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
198 .fpu_version = 0x00000000,
199 .mmu_version = mmu_us_12,
200 .nwindows = 8,
201 .maxtl = 5,
202 .features = CPU_DEFAULT_FEATURES,
205 .name = "TI UltraSparc II",
206 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
207 .fpu_version = 0x00000000,
208 .mmu_version = mmu_us_12,
209 .nwindows = 8,
210 .maxtl = 5,
211 .features = CPU_DEFAULT_FEATURES,
214 .name = "TI UltraSparc IIi",
215 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
216 .fpu_version = 0x00000000,
217 .mmu_version = mmu_us_12,
218 .nwindows = 8,
219 .maxtl = 5,
220 .features = CPU_DEFAULT_FEATURES,
223 .name = "TI UltraSparc IIe",
224 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
225 .fpu_version = 0x00000000,
226 .mmu_version = mmu_us_12,
227 .nwindows = 8,
228 .maxtl = 5,
229 .features = CPU_DEFAULT_FEATURES,
232 .name = "Sun UltraSparc III",
233 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
234 .fpu_version = 0x00000000,
235 .mmu_version = mmu_us_12,
236 .nwindows = 8,
237 .maxtl = 5,
238 .features = CPU_DEFAULT_FEATURES,
241 .name = "Sun UltraSparc III Cu",
242 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
243 .fpu_version = 0x00000000,
244 .mmu_version = mmu_us_3,
245 .nwindows = 8,
246 .maxtl = 5,
247 .features = CPU_DEFAULT_FEATURES,
250 .name = "Sun UltraSparc IIIi",
251 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
252 .fpu_version = 0x00000000,
253 .mmu_version = mmu_us_12,
254 .nwindows = 8,
255 .maxtl = 5,
256 .features = CPU_DEFAULT_FEATURES,
259 .name = "Sun UltraSparc IV",
260 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
261 .fpu_version = 0x00000000,
262 .mmu_version = mmu_us_4,
263 .nwindows = 8,
264 .maxtl = 5,
265 .features = CPU_DEFAULT_FEATURES,
268 .name = "Sun UltraSparc IV+",
269 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
270 .fpu_version = 0x00000000,
271 .mmu_version = mmu_us_12,
272 .nwindows = 8,
273 .maxtl = 5,
274 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
277 .name = "Sun UltraSparc IIIi+",
278 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
279 .fpu_version = 0x00000000,
280 .mmu_version = mmu_us_3,
281 .nwindows = 8,
282 .maxtl = 5,
283 .features = CPU_DEFAULT_FEATURES,
286 .name = "Sun UltraSparc T1",
287 /* defined in sparc_ifu_fdp.v and ctu.h */
288 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
289 .fpu_version = 0x00000000,
290 .mmu_version = mmu_sun4v,
291 .nwindows = 8,
292 .maxtl = 6,
293 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
294 | CPU_FEATURE_GL,
297 .name = "Sun UltraSparc T2",
298 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
299 .iu_version = ((0x3eULL << 48) | (0x24ULL << 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 = "NEC UltraSparc I",
309 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
310 .fpu_version = 0x00000000,
311 .mmu_version = mmu_us_12,
312 .nwindows = 8,
313 .maxtl = 5,
314 .features = CPU_DEFAULT_FEATURES,
316 #else
318 .name = "Fujitsu MB86904",
319 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
320 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
321 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
322 .mmu_bm = 0x00004000,
323 .mmu_ctpr_mask = 0x00ffffc0,
324 .mmu_cxr_mask = 0x000000ff,
325 .mmu_sfsr_mask = 0x00016fff,
326 .mmu_trcr_mask = 0x00ffffff,
327 .nwindows = 8,
328 .features = CPU_DEFAULT_FEATURES,
331 .name = "Fujitsu MB86907",
332 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
333 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
334 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
335 .mmu_bm = 0x00004000,
336 .mmu_ctpr_mask = 0xffffffc0,
337 .mmu_cxr_mask = 0x000000ff,
338 .mmu_sfsr_mask = 0x00016fff,
339 .mmu_trcr_mask = 0xffffffff,
340 .nwindows = 8,
341 .features = CPU_DEFAULT_FEATURES,
344 .name = "TI MicroSparc I",
345 .iu_version = 0x41000000,
346 .fpu_version = 4 << 17,
347 .mmu_version = 0x41000000,
348 .mmu_bm = 0x00004000,
349 .mmu_ctpr_mask = 0x007ffff0,
350 .mmu_cxr_mask = 0x0000003f,
351 .mmu_sfsr_mask = 0x00016fff,
352 .mmu_trcr_mask = 0x0000003f,
353 .nwindows = 7,
354 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
355 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
356 CPU_FEATURE_FMUL,
359 .name = "TI MicroSparc II",
360 .iu_version = 0x42000000,
361 .fpu_version = 4 << 17,
362 .mmu_version = 0x02000000,
363 .mmu_bm = 0x00004000,
364 .mmu_ctpr_mask = 0x00ffffc0,
365 .mmu_cxr_mask = 0x000000ff,
366 .mmu_sfsr_mask = 0x00016fff,
367 .mmu_trcr_mask = 0x00ffffff,
368 .nwindows = 8,
369 .features = CPU_DEFAULT_FEATURES,
372 .name = "TI MicroSparc IIep",
373 .iu_version = 0x42000000,
374 .fpu_version = 4 << 17,
375 .mmu_version = 0x04000000,
376 .mmu_bm = 0x00004000,
377 .mmu_ctpr_mask = 0x00ffffc0,
378 .mmu_cxr_mask = 0x000000ff,
379 .mmu_sfsr_mask = 0x00016bff,
380 .mmu_trcr_mask = 0x00ffffff,
381 .nwindows = 8,
382 .features = CPU_DEFAULT_FEATURES,
385 .name = "TI SuperSparc 40", /* STP1020NPGA */
386 .iu_version = 0x41000000, /* SuperSPARC 2.x */
387 .fpu_version = 0 << 17,
388 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
389 .mmu_bm = 0x00002000,
390 .mmu_ctpr_mask = 0xffffffc0,
391 .mmu_cxr_mask = 0x0000ffff,
392 .mmu_sfsr_mask = 0xffffffff,
393 .mmu_trcr_mask = 0xffffffff,
394 .nwindows = 8,
395 .features = CPU_DEFAULT_FEATURES,
398 .name = "TI SuperSparc 50", /* STP1020PGA */
399 .iu_version = 0x40000000, /* SuperSPARC 3.x */
400 .fpu_version = 0 << 17,
401 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
402 .mmu_bm = 0x00002000,
403 .mmu_ctpr_mask = 0xffffffc0,
404 .mmu_cxr_mask = 0x0000ffff,
405 .mmu_sfsr_mask = 0xffffffff,
406 .mmu_trcr_mask = 0xffffffff,
407 .nwindows = 8,
408 .features = CPU_DEFAULT_FEATURES,
411 .name = "TI SuperSparc 51",
412 .iu_version = 0x40000000, /* SuperSPARC 3.x */
413 .fpu_version = 0 << 17,
414 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
415 .mmu_bm = 0x00002000,
416 .mmu_ctpr_mask = 0xffffffc0,
417 .mmu_cxr_mask = 0x0000ffff,
418 .mmu_sfsr_mask = 0xffffffff,
419 .mmu_trcr_mask = 0xffffffff,
420 .mxcc_version = 0x00000104,
421 .nwindows = 8,
422 .features = CPU_DEFAULT_FEATURES,
425 .name = "TI SuperSparc 60", /* STP1020APGA */
426 .iu_version = 0x40000000, /* SuperSPARC 3.x */
427 .fpu_version = 0 << 17,
428 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
429 .mmu_bm = 0x00002000,
430 .mmu_ctpr_mask = 0xffffffc0,
431 .mmu_cxr_mask = 0x0000ffff,
432 .mmu_sfsr_mask = 0xffffffff,
433 .mmu_trcr_mask = 0xffffffff,
434 .nwindows = 8,
435 .features = CPU_DEFAULT_FEATURES,
438 .name = "TI SuperSparc 61",
439 .iu_version = 0x44000000, /* SuperSPARC 3.x */
440 .fpu_version = 0 << 17,
441 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
442 .mmu_bm = 0x00002000,
443 .mmu_ctpr_mask = 0xffffffc0,
444 .mmu_cxr_mask = 0x0000ffff,
445 .mmu_sfsr_mask = 0xffffffff,
446 .mmu_trcr_mask = 0xffffffff,
447 .mxcc_version = 0x00000104,
448 .nwindows = 8,
449 .features = CPU_DEFAULT_FEATURES,
452 .name = "TI SuperSparc II",
453 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
454 .fpu_version = 0 << 17,
455 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
456 .mmu_bm = 0x00002000,
457 .mmu_ctpr_mask = 0xffffffc0,
458 .mmu_cxr_mask = 0x0000ffff,
459 .mmu_sfsr_mask = 0xffffffff,
460 .mmu_trcr_mask = 0xffffffff,
461 .mxcc_version = 0x00000104,
462 .nwindows = 8,
463 .features = CPU_DEFAULT_FEATURES,
466 .name = "LEON2",
467 .iu_version = 0xf2000000,
468 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
469 .mmu_version = 0xf2000000,
470 .mmu_bm = 0x00004000,
471 .mmu_ctpr_mask = 0x007ffff0,
472 .mmu_cxr_mask = 0x0000003f,
473 .mmu_sfsr_mask = 0xffffffff,
474 .mmu_trcr_mask = 0xffffffff,
475 .nwindows = 8,
476 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
479 .name = "LEON3",
480 .iu_version = 0xf3000000,
481 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
482 .mmu_version = 0xf3000000,
483 .mmu_bm = 0x00000000,
484 .mmu_ctpr_mask = 0xfffffffc,
485 .mmu_cxr_mask = 0x000000ff,
486 .mmu_sfsr_mask = 0xffffffff,
487 .mmu_trcr_mask = 0xffffffff,
488 .nwindows = 8,
489 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
490 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
491 CPU_FEATURE_CASA,
493 #endif
496 static const char * const feature_name[] = {
497 "float",
498 "float128",
499 "swap",
500 "mul",
501 "div",
502 "flush",
503 "fsqrt",
504 "fmul",
505 "vis1",
506 "vis2",
507 "fsmuld",
508 "hypv",
509 "cmt",
510 "gl",
513 static void print_features(FILE *f, fprintf_function cpu_fprintf,
514 uint32_t features, const char *prefix)
516 unsigned int i;
518 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
519 if (feature_name[i] && (features & (1 << i))) {
520 if (prefix) {
521 (*cpu_fprintf)(f, "%s", prefix);
523 (*cpu_fprintf)(f, "%s ", feature_name[i]);
528 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
530 unsigned int i;
532 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
533 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
534 *features |= 1 << i;
535 return;
538 error_report("CPU feature %s not found", flagname);
541 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
543 unsigned int i;
544 const sparc_def_t *def = NULL;
546 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
547 if (strcasecmp(name, sparc_defs[i].name) == 0) {
548 def = &sparc_defs[i];
551 if (!def) {
552 return -1;
554 memcpy(cpu_def, def, sizeof(*def));
555 return 0;
558 static void sparc_cpu_parse_features(CPUState *cs, char *features,
559 Error **errp)
561 SPARCCPU *cpu = SPARC_CPU(cs);
562 sparc_def_t *cpu_def = cpu->env.def;
563 char *featurestr;
564 uint32_t plus_features = 0;
565 uint32_t minus_features = 0;
566 uint64_t iu_version;
567 uint32_t fpu_version, mmu_version, nwindows;
569 featurestr = features ? strtok(features, ",") : NULL;
570 while (featurestr) {
571 char *val;
573 if (featurestr[0] == '+') {
574 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
575 } else if (featurestr[0] == '-') {
576 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
577 } else if ((val = strchr(featurestr, '='))) {
578 *val = 0; val++;
579 if (!strcmp(featurestr, "iu_version")) {
580 char *err;
582 iu_version = strtoll(val, &err, 0);
583 if (!*val || *err) {
584 error_setg(errp, "bad numerical value %s", val);
585 return;
587 cpu_def->iu_version = iu_version;
588 #ifdef DEBUG_FEATURES
589 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
590 #endif
591 } else if (!strcmp(featurestr, "fpu_version")) {
592 char *err;
594 fpu_version = strtol(val, &err, 0);
595 if (!*val || *err) {
596 error_setg(errp, "bad numerical value %s", val);
597 return;
599 cpu_def->fpu_version = fpu_version;
600 #ifdef DEBUG_FEATURES
601 fprintf(stderr, "fpu_version %x\n", fpu_version);
602 #endif
603 } else if (!strcmp(featurestr, "mmu_version")) {
604 char *err;
606 mmu_version = strtol(val, &err, 0);
607 if (!*val || *err) {
608 error_setg(errp, "bad numerical value %s", val);
609 return;
611 cpu_def->mmu_version = mmu_version;
612 #ifdef DEBUG_FEATURES
613 fprintf(stderr, "mmu_version %x\n", mmu_version);
614 #endif
615 } else if (!strcmp(featurestr, "nwindows")) {
616 char *err;
618 nwindows = strtol(val, &err, 0);
619 if (!*val || *err || nwindows > MAX_NWINDOWS ||
620 nwindows < MIN_NWINDOWS) {
621 error_setg(errp, "bad numerical value %s", val);
622 return;
624 cpu_def->nwindows = nwindows;
625 #ifdef DEBUG_FEATURES
626 fprintf(stderr, "nwindows %d\n", nwindows);
627 #endif
628 } else {
629 error_setg(errp, "unrecognized feature %s", featurestr);
630 return;
632 } else {
633 error_setg(errp, "feature string `%s' not in format "
634 "(+feature|-feature|feature=xyz)", featurestr);
635 return;
637 featurestr = strtok(NULL, ",");
639 cpu_def->features |= plus_features;
640 cpu_def->features &= ~minus_features;
641 #ifdef DEBUG_FEATURES
642 print_features(stderr, fprintf, cpu_def->features, NULL);
643 #endif
646 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
648 unsigned int i;
650 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
651 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
652 " FPU %08x MMU %08x NWINS %d ",
653 sparc_defs[i].name,
654 sparc_defs[i].iu_version,
655 sparc_defs[i].fpu_version,
656 sparc_defs[i].mmu_version,
657 sparc_defs[i].nwindows);
658 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
659 ~sparc_defs[i].features, "-");
660 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
661 sparc_defs[i].features, "+");
662 (*cpu_fprintf)(f, "\n");
664 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
665 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
666 (*cpu_fprintf)(f, "\n");
667 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
668 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
669 (*cpu_fprintf)(f, "\n");
670 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
671 "fpu_version mmu_version nwindows\n");
674 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
675 uint32_t cc)
677 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
678 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
679 cc & PSR_CARRY ? 'C' : '-');
682 #ifdef TARGET_SPARC64
683 #define REGS_PER_LINE 4
684 #else
685 #define REGS_PER_LINE 8
686 #endif
688 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
689 int flags)
691 SPARCCPU *cpu = SPARC_CPU(cs);
692 CPUSPARCState *env = &cpu->env;
693 int i, x;
695 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
696 env->npc);
698 for (i = 0; i < 8; i++) {
699 if (i % REGS_PER_LINE == 0) {
700 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
702 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
703 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
704 cpu_fprintf(f, "\n");
707 for (x = 0; x < 3; x++) {
708 for (i = 0; i < 8; i++) {
709 if (i % REGS_PER_LINE == 0) {
710 cpu_fprintf(f, "%%%c%d-%d: ",
711 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
712 i, i + REGS_PER_LINE - 1);
714 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
715 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
716 cpu_fprintf(f, "\n");
721 for (i = 0; i < TARGET_DPREGS; i++) {
722 if ((i & 3) == 0) {
723 cpu_fprintf(f, "%%f%02d: ", i * 2);
725 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
726 if ((i & 3) == 3) {
727 cpu_fprintf(f, "\n");
730 #ifdef TARGET_SPARC64
731 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
732 (unsigned)cpu_get_ccr(env));
733 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
734 cpu_fprintf(f, " xcc: ");
735 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
736 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
737 env->psrpil);
738 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
739 "cleanwin: %d cwp: %d\n",
740 env->cansave, env->canrestore, env->otherwin, env->wstate,
741 env->cleanwin, env->nwindows - 1 - env->cwp);
742 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
743 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
744 #else
745 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
746 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
747 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
748 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
749 env->wim);
750 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
751 env->fsr, env->y);
752 #endif
753 cpu_fprintf(f, "\n");
756 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
758 SPARCCPU *cpu = SPARC_CPU(cs);
760 cpu->env.pc = value;
761 cpu->env.npc = value + 4;
764 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
766 SPARCCPU *cpu = SPARC_CPU(cs);
768 cpu->env.pc = tb->pc;
769 cpu->env.npc = tb->cs_base;
772 static bool sparc_cpu_has_work(CPUState *cs)
774 SPARCCPU *cpu = SPARC_CPU(cs);
775 CPUSPARCState *env = &cpu->env;
777 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
778 cpu_interrupts_enabled(env);
781 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
783 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
784 #if defined(CONFIG_USER_ONLY)
785 SPARCCPU *cpu = SPARC_CPU(dev);
786 CPUSPARCState *env = &cpu->env;
788 if ((env->def->features & CPU_FEATURE_FLOAT)) {
789 env->def->features |= CPU_FEATURE_FLOAT128;
791 #endif
793 qemu_init_vcpu(CPU(dev));
795 scc->parent_realize(dev, errp);
798 static void sparc_cpu_initfn(Object *obj)
800 CPUState *cs = CPU(obj);
801 SPARCCPU *cpu = SPARC_CPU(obj);
802 CPUSPARCState *env = &cpu->env;
804 cs->env_ptr = env;
805 cpu_exec_init(env);
807 if (tcg_enabled()) {
808 gen_intermediate_code_init(env);
812 static void sparc_cpu_uninitfn(Object *obj)
814 SPARCCPU *cpu = SPARC_CPU(obj);
815 CPUSPARCState *env = &cpu->env;
817 g_free(env->def);
820 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
822 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
823 CPUClass *cc = CPU_CLASS(oc);
824 DeviceClass *dc = DEVICE_CLASS(oc);
826 scc->parent_realize = dc->realize;
827 dc->realize = sparc_cpu_realizefn;
829 scc->parent_reset = cc->reset;
830 cc->reset = sparc_cpu_reset;
832 cc->parse_features = sparc_cpu_parse_features;
833 cc->has_work = sparc_cpu_has_work;
834 cc->do_interrupt = sparc_cpu_do_interrupt;
835 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
836 cc->dump_state = sparc_cpu_dump_state;
837 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
838 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
839 #endif
840 cc->set_pc = sparc_cpu_set_pc;
841 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
842 cc->gdb_read_register = sparc_cpu_gdb_read_register;
843 cc->gdb_write_register = sparc_cpu_gdb_write_register;
844 #ifdef CONFIG_USER_ONLY
845 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
846 #else
847 cc->do_unassigned_access = sparc_cpu_unassigned_access;
848 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
849 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
850 #endif
852 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
853 cc->gdb_num_core_regs = 86;
854 #else
855 cc->gdb_num_core_regs = 72;
856 #endif
859 static const TypeInfo sparc_cpu_type_info = {
860 .name = TYPE_SPARC_CPU,
861 .parent = TYPE_CPU,
862 .instance_size = sizeof(SPARCCPU),
863 .instance_init = sparc_cpu_initfn,
864 .instance_finalize = sparc_cpu_uninitfn,
865 .abstract = false,
866 .class_size = sizeof(SPARCCPUClass),
867 .class_init = sparc_cpu_class_init,
870 static void sparc_cpu_register_types(void)
872 type_register_static(&sparc_cpu_type_info);
875 type_init(sparc_cpu_register_types)