docs/rcu.txt: Fix minor typo
[qemu/ar7.git] / target-sparc / cpu.c
blob4e07b92fbd70cc16480c1abb2c37b0c928e976b7
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 void sparc_cpu_parse_features(CPUState *cs, char *features,
105 Error **errp);
107 static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
109 CPUSPARCState *env = &cpu->env;
110 char *s = g_strdup(cpu_model);
111 char *featurestr, *name = strtok(s, ",");
112 sparc_def_t def1, *def = &def1;
113 Error *err = NULL;
115 if (cpu_sparc_find_by_name(def, name) < 0) {
116 g_free(s);
117 return -1;
120 env->def = g_memdup(def, sizeof(*def));
122 featurestr = strtok(NULL, ",");
123 sparc_cpu_parse_features(CPU(cpu), featurestr, &err);
124 g_free(s);
125 if (err) {
126 error_report_err(err);
127 return -1;
130 env->version = def->iu_version;
131 env->fsr = def->fpu_version;
132 env->nwindows = def->nwindows;
133 #if !defined(TARGET_SPARC64)
134 env->mmuregs[0] |= def->mmu_version;
135 cpu_sparc_set_id(env, 0);
136 env->mxccregs[7] |= def->mxcc_version;
137 #else
138 env->mmu_version = def->mmu_version;
139 env->maxtl = def->maxtl;
140 env->version |= def->maxtl << 8;
141 env->version |= def->nwindows - 1;
142 #endif
143 return 0;
146 SPARCCPU *cpu_sparc_init(const char *cpu_model)
148 SPARCCPU *cpu;
150 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
152 if (cpu_sparc_register(cpu, cpu_model) < 0) {
153 object_unref(OBJECT(cpu));
154 return NULL;
157 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
159 return cpu;
162 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
164 #if !defined(TARGET_SPARC64)
165 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
166 #endif
169 static const sparc_def_t sparc_defs[] = {
170 #ifdef TARGET_SPARC64
172 .name = "Fujitsu Sparc64",
173 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
174 .fpu_version = 0x00000000,
175 .mmu_version = mmu_us_12,
176 .nwindows = 4,
177 .maxtl = 4,
178 .features = CPU_DEFAULT_FEATURES,
181 .name = "Fujitsu Sparc64 III",
182 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
183 .fpu_version = 0x00000000,
184 .mmu_version = mmu_us_12,
185 .nwindows = 5,
186 .maxtl = 4,
187 .features = CPU_DEFAULT_FEATURES,
190 .name = "Fujitsu Sparc64 IV",
191 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
192 .fpu_version = 0x00000000,
193 .mmu_version = mmu_us_12,
194 .nwindows = 8,
195 .maxtl = 5,
196 .features = CPU_DEFAULT_FEATURES,
199 .name = "Fujitsu Sparc64 V",
200 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
201 .fpu_version = 0x00000000,
202 .mmu_version = mmu_us_12,
203 .nwindows = 8,
204 .maxtl = 5,
205 .features = CPU_DEFAULT_FEATURES,
208 .name = "TI UltraSparc I",
209 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
210 .fpu_version = 0x00000000,
211 .mmu_version = mmu_us_12,
212 .nwindows = 8,
213 .maxtl = 5,
214 .features = CPU_DEFAULT_FEATURES,
217 .name = "TI UltraSparc II",
218 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
219 .fpu_version = 0x00000000,
220 .mmu_version = mmu_us_12,
221 .nwindows = 8,
222 .maxtl = 5,
223 .features = CPU_DEFAULT_FEATURES,
226 .name = "TI UltraSparc IIi",
227 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
228 .fpu_version = 0x00000000,
229 .mmu_version = mmu_us_12,
230 .nwindows = 8,
231 .maxtl = 5,
232 .features = CPU_DEFAULT_FEATURES,
235 .name = "TI UltraSparc IIe",
236 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
237 .fpu_version = 0x00000000,
238 .mmu_version = mmu_us_12,
239 .nwindows = 8,
240 .maxtl = 5,
241 .features = CPU_DEFAULT_FEATURES,
244 .name = "Sun UltraSparc III",
245 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
246 .fpu_version = 0x00000000,
247 .mmu_version = mmu_us_12,
248 .nwindows = 8,
249 .maxtl = 5,
250 .features = CPU_DEFAULT_FEATURES,
253 .name = "Sun UltraSparc III Cu",
254 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
255 .fpu_version = 0x00000000,
256 .mmu_version = mmu_us_3,
257 .nwindows = 8,
258 .maxtl = 5,
259 .features = CPU_DEFAULT_FEATURES,
262 .name = "Sun UltraSparc IIIi",
263 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
264 .fpu_version = 0x00000000,
265 .mmu_version = mmu_us_12,
266 .nwindows = 8,
267 .maxtl = 5,
268 .features = CPU_DEFAULT_FEATURES,
271 .name = "Sun UltraSparc IV",
272 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
273 .fpu_version = 0x00000000,
274 .mmu_version = mmu_us_4,
275 .nwindows = 8,
276 .maxtl = 5,
277 .features = CPU_DEFAULT_FEATURES,
280 .name = "Sun UltraSparc IV+",
281 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
282 .fpu_version = 0x00000000,
283 .mmu_version = mmu_us_12,
284 .nwindows = 8,
285 .maxtl = 5,
286 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
289 .name = "Sun UltraSparc IIIi+",
290 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
291 .fpu_version = 0x00000000,
292 .mmu_version = mmu_us_3,
293 .nwindows = 8,
294 .maxtl = 5,
295 .features = CPU_DEFAULT_FEATURES,
298 .name = "Sun UltraSparc T1",
299 /* defined in sparc_ifu_fdp.v and ctu.h */
300 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
301 .fpu_version = 0x00000000,
302 .mmu_version = mmu_sun4v,
303 .nwindows = 8,
304 .maxtl = 6,
305 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
306 | CPU_FEATURE_GL,
309 .name = "Sun UltraSparc T2",
310 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
311 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
312 .fpu_version = 0x00000000,
313 .mmu_version = mmu_sun4v,
314 .nwindows = 8,
315 .maxtl = 6,
316 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
317 | CPU_FEATURE_GL,
320 .name = "NEC UltraSparc I",
321 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
322 .fpu_version = 0x00000000,
323 .mmu_version = mmu_us_12,
324 .nwindows = 8,
325 .maxtl = 5,
326 .features = CPU_DEFAULT_FEATURES,
328 #else
330 .name = "Fujitsu MB86904",
331 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
332 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
333 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
334 .mmu_bm = 0x00004000,
335 .mmu_ctpr_mask = 0x00ffffc0,
336 .mmu_cxr_mask = 0x000000ff,
337 .mmu_sfsr_mask = 0x00016fff,
338 .mmu_trcr_mask = 0x00ffffff,
339 .nwindows = 8,
340 .features = CPU_DEFAULT_FEATURES,
343 .name = "Fujitsu MB86907",
344 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
345 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
346 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
347 .mmu_bm = 0x00004000,
348 .mmu_ctpr_mask = 0xffffffc0,
349 .mmu_cxr_mask = 0x000000ff,
350 .mmu_sfsr_mask = 0x00016fff,
351 .mmu_trcr_mask = 0xffffffff,
352 .nwindows = 8,
353 .features = CPU_DEFAULT_FEATURES,
356 .name = "TI MicroSparc I",
357 .iu_version = 0x41000000,
358 .fpu_version = 4 << 17,
359 .mmu_version = 0x41000000,
360 .mmu_bm = 0x00004000,
361 .mmu_ctpr_mask = 0x007ffff0,
362 .mmu_cxr_mask = 0x0000003f,
363 .mmu_sfsr_mask = 0x00016fff,
364 .mmu_trcr_mask = 0x0000003f,
365 .nwindows = 7,
366 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
367 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
368 CPU_FEATURE_FMUL,
371 .name = "TI MicroSparc II",
372 .iu_version = 0x42000000,
373 .fpu_version = 4 << 17,
374 .mmu_version = 0x02000000,
375 .mmu_bm = 0x00004000,
376 .mmu_ctpr_mask = 0x00ffffc0,
377 .mmu_cxr_mask = 0x000000ff,
378 .mmu_sfsr_mask = 0x00016fff,
379 .mmu_trcr_mask = 0x00ffffff,
380 .nwindows = 8,
381 .features = CPU_DEFAULT_FEATURES,
384 .name = "TI MicroSparc IIep",
385 .iu_version = 0x42000000,
386 .fpu_version = 4 << 17,
387 .mmu_version = 0x04000000,
388 .mmu_bm = 0x00004000,
389 .mmu_ctpr_mask = 0x00ffffc0,
390 .mmu_cxr_mask = 0x000000ff,
391 .mmu_sfsr_mask = 0x00016bff,
392 .mmu_trcr_mask = 0x00ffffff,
393 .nwindows = 8,
394 .features = CPU_DEFAULT_FEATURES,
397 .name = "TI SuperSparc 40", /* STP1020NPGA */
398 .iu_version = 0x41000000, /* SuperSPARC 2.x */
399 .fpu_version = 0 << 17,
400 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
401 .mmu_bm = 0x00002000,
402 .mmu_ctpr_mask = 0xffffffc0,
403 .mmu_cxr_mask = 0x0000ffff,
404 .mmu_sfsr_mask = 0xffffffff,
405 .mmu_trcr_mask = 0xffffffff,
406 .nwindows = 8,
407 .features = CPU_DEFAULT_FEATURES,
410 .name = "TI SuperSparc 50", /* STP1020PGA */
411 .iu_version = 0x40000000, /* SuperSPARC 3.x */
412 .fpu_version = 0 << 17,
413 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
414 .mmu_bm = 0x00002000,
415 .mmu_ctpr_mask = 0xffffffc0,
416 .mmu_cxr_mask = 0x0000ffff,
417 .mmu_sfsr_mask = 0xffffffff,
418 .mmu_trcr_mask = 0xffffffff,
419 .nwindows = 8,
420 .features = CPU_DEFAULT_FEATURES,
423 .name = "TI SuperSparc 51",
424 .iu_version = 0x40000000, /* SuperSPARC 3.x */
425 .fpu_version = 0 << 17,
426 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
427 .mmu_bm = 0x00002000,
428 .mmu_ctpr_mask = 0xffffffc0,
429 .mmu_cxr_mask = 0x0000ffff,
430 .mmu_sfsr_mask = 0xffffffff,
431 .mmu_trcr_mask = 0xffffffff,
432 .mxcc_version = 0x00000104,
433 .nwindows = 8,
434 .features = CPU_DEFAULT_FEATURES,
437 .name = "TI SuperSparc 60", /* STP1020APGA */
438 .iu_version = 0x40000000, /* SuperSPARC 3.x */
439 .fpu_version = 0 << 17,
440 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
441 .mmu_bm = 0x00002000,
442 .mmu_ctpr_mask = 0xffffffc0,
443 .mmu_cxr_mask = 0x0000ffff,
444 .mmu_sfsr_mask = 0xffffffff,
445 .mmu_trcr_mask = 0xffffffff,
446 .nwindows = 8,
447 .features = CPU_DEFAULT_FEATURES,
450 .name = "TI SuperSparc 61",
451 .iu_version = 0x44000000, /* SuperSPARC 3.x */
452 .fpu_version = 0 << 17,
453 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
454 .mmu_bm = 0x00002000,
455 .mmu_ctpr_mask = 0xffffffc0,
456 .mmu_cxr_mask = 0x0000ffff,
457 .mmu_sfsr_mask = 0xffffffff,
458 .mmu_trcr_mask = 0xffffffff,
459 .mxcc_version = 0x00000104,
460 .nwindows = 8,
461 .features = CPU_DEFAULT_FEATURES,
464 .name = "TI SuperSparc II",
465 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
466 .fpu_version = 0 << 17,
467 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
468 .mmu_bm = 0x00002000,
469 .mmu_ctpr_mask = 0xffffffc0,
470 .mmu_cxr_mask = 0x0000ffff,
471 .mmu_sfsr_mask = 0xffffffff,
472 .mmu_trcr_mask = 0xffffffff,
473 .mxcc_version = 0x00000104,
474 .nwindows = 8,
475 .features = CPU_DEFAULT_FEATURES,
478 .name = "LEON2",
479 .iu_version = 0xf2000000,
480 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
481 .mmu_version = 0xf2000000,
482 .mmu_bm = 0x00004000,
483 .mmu_ctpr_mask = 0x007ffff0,
484 .mmu_cxr_mask = 0x0000003f,
485 .mmu_sfsr_mask = 0xffffffff,
486 .mmu_trcr_mask = 0xffffffff,
487 .nwindows = 8,
488 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
491 .name = "LEON3",
492 .iu_version = 0xf3000000,
493 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
494 .mmu_version = 0xf3000000,
495 .mmu_bm = 0x00000000,
496 .mmu_ctpr_mask = 0xfffffffc,
497 .mmu_cxr_mask = 0x000000ff,
498 .mmu_sfsr_mask = 0xffffffff,
499 .mmu_trcr_mask = 0xffffffff,
500 .nwindows = 8,
501 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
502 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
503 CPU_FEATURE_CASA,
505 #endif
508 static const char * const feature_name[] = {
509 "float",
510 "float128",
511 "swap",
512 "mul",
513 "div",
514 "flush",
515 "fsqrt",
516 "fmul",
517 "vis1",
518 "vis2",
519 "fsmuld",
520 "hypv",
521 "cmt",
522 "gl",
525 static void print_features(FILE *f, fprintf_function cpu_fprintf,
526 uint32_t features, const char *prefix)
528 unsigned int i;
530 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
531 if (feature_name[i] && (features & (1 << i))) {
532 if (prefix) {
533 (*cpu_fprintf)(f, "%s", prefix);
535 (*cpu_fprintf)(f, "%s ", feature_name[i]);
540 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
542 unsigned int i;
544 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
545 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
546 *features |= 1 << i;
547 return;
550 error_report("CPU feature %s not found", flagname);
553 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
555 unsigned int i;
556 const sparc_def_t *def = NULL;
558 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
559 if (strcasecmp(name, sparc_defs[i].name) == 0) {
560 def = &sparc_defs[i];
563 if (!def) {
564 return -1;
566 memcpy(cpu_def, def, sizeof(*def));
567 return 0;
570 static void sparc_cpu_parse_features(CPUState *cs, char *features,
571 Error **errp)
573 SPARCCPU *cpu = SPARC_CPU(cs);
574 sparc_def_t *cpu_def = cpu->env.def;
575 char *featurestr;
576 uint32_t plus_features = 0;
577 uint32_t minus_features = 0;
578 uint64_t iu_version;
579 uint32_t fpu_version, mmu_version, nwindows;
581 featurestr = features ? strtok(features, ",") : NULL;
582 while (featurestr) {
583 char *val;
585 if (featurestr[0] == '+') {
586 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
587 } else if (featurestr[0] == '-') {
588 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
589 } else if ((val = strchr(featurestr, '='))) {
590 *val = 0; val++;
591 if (!strcmp(featurestr, "iu_version")) {
592 char *err;
594 iu_version = strtoll(val, &err, 0);
595 if (!*val || *err) {
596 error_setg(errp, "bad numerical value %s", val);
597 return;
599 cpu_def->iu_version = iu_version;
600 #ifdef DEBUG_FEATURES
601 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
602 #endif
603 } else if (!strcmp(featurestr, "fpu_version")) {
604 char *err;
606 fpu_version = strtol(val, &err, 0);
607 if (!*val || *err) {
608 error_setg(errp, "bad numerical value %s", val);
609 return;
611 cpu_def->fpu_version = fpu_version;
612 #ifdef DEBUG_FEATURES
613 fprintf(stderr, "fpu_version %x\n", fpu_version);
614 #endif
615 } else if (!strcmp(featurestr, "mmu_version")) {
616 char *err;
618 mmu_version = strtol(val, &err, 0);
619 if (!*val || *err) {
620 error_setg(errp, "bad numerical value %s", val);
621 return;
623 cpu_def->mmu_version = mmu_version;
624 #ifdef DEBUG_FEATURES
625 fprintf(stderr, "mmu_version %x\n", mmu_version);
626 #endif
627 } else if (!strcmp(featurestr, "nwindows")) {
628 char *err;
630 nwindows = strtol(val, &err, 0);
631 if (!*val || *err || nwindows > MAX_NWINDOWS ||
632 nwindows < MIN_NWINDOWS) {
633 error_setg(errp, "bad numerical value %s", val);
634 return;
636 cpu_def->nwindows = nwindows;
637 #ifdef DEBUG_FEATURES
638 fprintf(stderr, "nwindows %d\n", nwindows);
639 #endif
640 } else {
641 error_setg(errp, "unrecognized feature %s", featurestr);
642 return;
644 } else {
645 error_setg(errp, "feature string `%s' not in format "
646 "(+feature|-feature|feature=xyz)", featurestr);
647 return;
649 featurestr = strtok(NULL, ",");
651 cpu_def->features |= plus_features;
652 cpu_def->features &= ~minus_features;
653 #ifdef DEBUG_FEATURES
654 print_features(stderr, fprintf, cpu_def->features, NULL);
655 #endif
658 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
660 unsigned int i;
662 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
663 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
664 " FPU %08x MMU %08x NWINS %d ",
665 sparc_defs[i].name,
666 sparc_defs[i].iu_version,
667 sparc_defs[i].fpu_version,
668 sparc_defs[i].mmu_version,
669 sparc_defs[i].nwindows);
670 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
671 ~sparc_defs[i].features, "-");
672 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
673 sparc_defs[i].features, "+");
674 (*cpu_fprintf)(f, "\n");
676 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
677 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
678 (*cpu_fprintf)(f, "\n");
679 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
680 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
681 (*cpu_fprintf)(f, "\n");
682 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
683 "fpu_version mmu_version nwindows\n");
686 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
687 uint32_t cc)
689 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
690 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
691 cc & PSR_CARRY ? 'C' : '-');
694 #ifdef TARGET_SPARC64
695 #define REGS_PER_LINE 4
696 #else
697 #define REGS_PER_LINE 8
698 #endif
700 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
701 int flags)
703 SPARCCPU *cpu = SPARC_CPU(cs);
704 CPUSPARCState *env = &cpu->env;
705 int i, x;
707 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
708 env->npc);
710 for (i = 0; i < 8; i++) {
711 if (i % REGS_PER_LINE == 0) {
712 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
714 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
715 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
716 cpu_fprintf(f, "\n");
719 for (x = 0; x < 3; x++) {
720 for (i = 0; i < 8; i++) {
721 if (i % REGS_PER_LINE == 0) {
722 cpu_fprintf(f, "%%%c%d-%d: ",
723 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
724 i, i + REGS_PER_LINE - 1);
726 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
727 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
728 cpu_fprintf(f, "\n");
733 for (i = 0; i < TARGET_DPREGS; i++) {
734 if ((i & 3) == 0) {
735 cpu_fprintf(f, "%%f%02d: ", i * 2);
737 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
738 if ((i & 3) == 3) {
739 cpu_fprintf(f, "\n");
742 #ifdef TARGET_SPARC64
743 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
744 (unsigned)cpu_get_ccr(env));
745 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
746 cpu_fprintf(f, " xcc: ");
747 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
748 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
749 env->psrpil);
750 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
751 "cleanwin: %d cwp: %d\n",
752 env->cansave, env->canrestore, env->otherwin, env->wstate,
753 env->cleanwin, env->nwindows - 1 - env->cwp);
754 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
755 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
756 #else
757 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
758 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
759 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
760 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
761 env->wim);
762 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
763 env->fsr, env->y);
764 #endif
765 cpu_fprintf(f, "\n");
768 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
770 SPARCCPU *cpu = SPARC_CPU(cs);
772 cpu->env.pc = value;
773 cpu->env.npc = value + 4;
776 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
778 SPARCCPU *cpu = SPARC_CPU(cs);
780 cpu->env.pc = tb->pc;
781 cpu->env.npc = tb->cs_base;
784 static bool sparc_cpu_has_work(CPUState *cs)
786 SPARCCPU *cpu = SPARC_CPU(cs);
787 CPUSPARCState *env = &cpu->env;
789 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
790 cpu_interrupts_enabled(env);
793 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
795 CPUState *cs = CPU(dev);
796 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
797 Error *local_err = NULL;
798 #if defined(CONFIG_USER_ONLY)
799 SPARCCPU *cpu = SPARC_CPU(dev);
800 CPUSPARCState *env = &cpu->env;
802 if ((env->def->features & CPU_FEATURE_FLOAT)) {
803 env->def->features |= CPU_FEATURE_FLOAT128;
805 #endif
807 cpu_exec_realizefn(cs, &local_err);
808 if (local_err != NULL) {
809 error_propagate(errp, local_err);
810 return;
813 qemu_init_vcpu(cs);
815 scc->parent_realize(dev, errp);
818 static void sparc_cpu_initfn(Object *obj)
820 CPUState *cs = CPU(obj);
821 SPARCCPU *cpu = SPARC_CPU(obj);
822 CPUSPARCState *env = &cpu->env;
824 cs->env_ptr = env;
826 if (tcg_enabled()) {
827 gen_intermediate_code_init(env);
831 static void sparc_cpu_uninitfn(Object *obj)
833 SPARCCPU *cpu = SPARC_CPU(obj);
834 CPUSPARCState *env = &cpu->env;
836 g_free(env->def);
839 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
841 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
842 CPUClass *cc = CPU_CLASS(oc);
843 DeviceClass *dc = DEVICE_CLASS(oc);
845 scc->parent_realize = dc->realize;
846 dc->realize = sparc_cpu_realizefn;
848 scc->parent_reset = cc->reset;
849 cc->reset = sparc_cpu_reset;
851 cc->has_work = sparc_cpu_has_work;
852 cc->do_interrupt = sparc_cpu_do_interrupt;
853 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
854 cc->dump_state = sparc_cpu_dump_state;
855 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
856 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
857 #endif
858 cc->set_pc = sparc_cpu_set_pc;
859 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
860 cc->gdb_read_register = sparc_cpu_gdb_read_register;
861 cc->gdb_write_register = sparc_cpu_gdb_write_register;
862 #ifdef CONFIG_USER_ONLY
863 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
864 #else
865 cc->do_unassigned_access = sparc_cpu_unassigned_access;
866 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
867 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
868 cc->vmsd = &vmstate_sparc_cpu;
869 #endif
870 cc->disas_set_info = cpu_sparc_disas_set_info;
872 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
873 cc->gdb_num_core_regs = 86;
874 #else
875 cc->gdb_num_core_regs = 72;
876 #endif
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)