exec: fix error handling in file_ram_alloc
[qemu/ar7.git] / target-sparc / cpu.c
blobfe4119e2bc93661338244a3ff65d62b3efe78511
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"
25 //#define DEBUG_FEATURES
27 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
29 /* CPUClass::reset() */
30 static void sparc_cpu_reset(CPUState *s)
32 SPARCCPU *cpu = SPARC_CPU(s);
33 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
34 CPUSPARCState *env = &cpu->env;
36 scc->parent_reset(s);
38 memset(env, 0, offsetof(CPUSPARCState, version));
39 tlb_flush(s, 1);
40 env->cwp = 0;
41 #ifndef TARGET_SPARC64
42 env->wim = 1;
43 #endif
44 env->regwptr = env->regbase + (env->cwp * 16);
45 CC_OP = CC_OP_FLAGS;
46 #if defined(CONFIG_USER_ONLY)
47 #ifdef TARGET_SPARC64
48 env->cleanwin = env->nwindows - 2;
49 env->cansave = env->nwindows - 2;
50 env->pstate = PS_RMO | PS_PEF | PS_IE;
51 env->asi = 0x82; /* Primary no-fault */
52 #endif
53 #else
54 #if !defined(TARGET_SPARC64)
55 env->psret = 0;
56 env->psrs = 1;
57 env->psrps = 1;
58 #endif
59 #ifdef TARGET_SPARC64
60 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
61 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
62 env->tl = env->maxtl;
63 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
64 env->lsu = 0;
65 #else
66 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
67 env->mmuregs[0] |= env->def->mmu_bm;
68 #endif
69 env->pc = 0;
70 env->npc = env->pc + 4;
71 #endif
72 env->cache_control = 0;
75 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
77 if (interrupt_request & CPU_INTERRUPT_HARD) {
78 SPARCCPU *cpu = SPARC_CPU(cs);
79 CPUSPARCState *env = &cpu->env;
81 if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
82 int pil = env->interrupt_index & 0xf;
83 int type = env->interrupt_index & 0xf0;
85 if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
86 cs->exception_index = env->interrupt_index;
87 sparc_cpu_do_interrupt(cs);
88 return true;
92 return false;
95 static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
97 info->print_insn = print_insn_sparc;
98 #ifdef TARGET_SPARC64
99 info->mach = bfd_mach_sparc_v9b;
100 #endif
103 static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
105 CPUClass *cc = CPU_GET_CLASS(cpu);
106 CPUSPARCState *env = &cpu->env;
107 char *s = g_strdup(cpu_model);
108 char *featurestr, *name = strtok(s, ",");
109 sparc_def_t def1, *def = &def1;
110 Error *err = NULL;
112 if (cpu_sparc_find_by_name(def, name) < 0) {
113 g_free(s);
114 return -1;
117 env->def = g_new0(sparc_def_t, 1);
118 memcpy(env->def, def, sizeof(*def));
120 featurestr = strtok(NULL, ",");
121 cc->parse_features(CPU(cpu), featurestr, &err);
122 g_free(s);
123 if (err) {
124 error_report_err(err);
125 return -1;
128 env->version = def->iu_version;
129 env->fsr = def->fpu_version;
130 env->nwindows = def->nwindows;
131 #if !defined(TARGET_SPARC64)
132 env->mmuregs[0] |= def->mmu_version;
133 cpu_sparc_set_id(env, 0);
134 env->mxccregs[7] |= def->mxcc_version;
135 #else
136 env->mmu_version = def->mmu_version;
137 env->maxtl = def->maxtl;
138 env->version |= def->maxtl << 8;
139 env->version |= def->nwindows - 1;
140 #endif
141 return 0;
144 SPARCCPU *cpu_sparc_init(const char *cpu_model)
146 SPARCCPU *cpu;
148 cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
150 if (cpu_sparc_register(cpu, cpu_model) < 0) {
151 object_unref(OBJECT(cpu));
152 return NULL;
155 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
157 return cpu;
160 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
162 #if !defined(TARGET_SPARC64)
163 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
164 #endif
167 static const sparc_def_t sparc_defs[] = {
168 #ifdef TARGET_SPARC64
170 .name = "Fujitsu Sparc64",
171 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
172 .fpu_version = 0x00000000,
173 .mmu_version = mmu_us_12,
174 .nwindows = 4,
175 .maxtl = 4,
176 .features = CPU_DEFAULT_FEATURES,
179 .name = "Fujitsu Sparc64 III",
180 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
181 .fpu_version = 0x00000000,
182 .mmu_version = mmu_us_12,
183 .nwindows = 5,
184 .maxtl = 4,
185 .features = CPU_DEFAULT_FEATURES,
188 .name = "Fujitsu Sparc64 IV",
189 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
190 .fpu_version = 0x00000000,
191 .mmu_version = mmu_us_12,
192 .nwindows = 8,
193 .maxtl = 5,
194 .features = CPU_DEFAULT_FEATURES,
197 .name = "Fujitsu Sparc64 V",
198 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
199 .fpu_version = 0x00000000,
200 .mmu_version = mmu_us_12,
201 .nwindows = 8,
202 .maxtl = 5,
203 .features = CPU_DEFAULT_FEATURES,
206 .name = "TI UltraSparc I",
207 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
208 .fpu_version = 0x00000000,
209 .mmu_version = mmu_us_12,
210 .nwindows = 8,
211 .maxtl = 5,
212 .features = CPU_DEFAULT_FEATURES,
215 .name = "TI UltraSparc II",
216 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
217 .fpu_version = 0x00000000,
218 .mmu_version = mmu_us_12,
219 .nwindows = 8,
220 .maxtl = 5,
221 .features = CPU_DEFAULT_FEATURES,
224 .name = "TI UltraSparc IIi",
225 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
226 .fpu_version = 0x00000000,
227 .mmu_version = mmu_us_12,
228 .nwindows = 8,
229 .maxtl = 5,
230 .features = CPU_DEFAULT_FEATURES,
233 .name = "TI UltraSparc IIe",
234 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
235 .fpu_version = 0x00000000,
236 .mmu_version = mmu_us_12,
237 .nwindows = 8,
238 .maxtl = 5,
239 .features = CPU_DEFAULT_FEATURES,
242 .name = "Sun UltraSparc III",
243 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
244 .fpu_version = 0x00000000,
245 .mmu_version = mmu_us_12,
246 .nwindows = 8,
247 .maxtl = 5,
248 .features = CPU_DEFAULT_FEATURES,
251 .name = "Sun UltraSparc III Cu",
252 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
253 .fpu_version = 0x00000000,
254 .mmu_version = mmu_us_3,
255 .nwindows = 8,
256 .maxtl = 5,
257 .features = CPU_DEFAULT_FEATURES,
260 .name = "Sun UltraSparc IIIi",
261 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
262 .fpu_version = 0x00000000,
263 .mmu_version = mmu_us_12,
264 .nwindows = 8,
265 .maxtl = 5,
266 .features = CPU_DEFAULT_FEATURES,
269 .name = "Sun UltraSparc IV",
270 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
271 .fpu_version = 0x00000000,
272 .mmu_version = mmu_us_4,
273 .nwindows = 8,
274 .maxtl = 5,
275 .features = CPU_DEFAULT_FEATURES,
278 .name = "Sun UltraSparc IV+",
279 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
280 .fpu_version = 0x00000000,
281 .mmu_version = mmu_us_12,
282 .nwindows = 8,
283 .maxtl = 5,
284 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
287 .name = "Sun UltraSparc IIIi+",
288 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
289 .fpu_version = 0x00000000,
290 .mmu_version = mmu_us_3,
291 .nwindows = 8,
292 .maxtl = 5,
293 .features = CPU_DEFAULT_FEATURES,
296 .name = "Sun UltraSparc T1",
297 /* defined in sparc_ifu_fdp.v and ctu.h */
298 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
299 .fpu_version = 0x00000000,
300 .mmu_version = mmu_sun4v,
301 .nwindows = 8,
302 .maxtl = 6,
303 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
304 | CPU_FEATURE_GL,
307 .name = "Sun UltraSparc T2",
308 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
309 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
310 .fpu_version = 0x00000000,
311 .mmu_version = mmu_sun4v,
312 .nwindows = 8,
313 .maxtl = 6,
314 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
315 | CPU_FEATURE_GL,
318 .name = "NEC UltraSparc I",
319 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
320 .fpu_version = 0x00000000,
321 .mmu_version = mmu_us_12,
322 .nwindows = 8,
323 .maxtl = 5,
324 .features = CPU_DEFAULT_FEATURES,
326 #else
328 .name = "Fujitsu MB86904",
329 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
330 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
331 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
332 .mmu_bm = 0x00004000,
333 .mmu_ctpr_mask = 0x00ffffc0,
334 .mmu_cxr_mask = 0x000000ff,
335 .mmu_sfsr_mask = 0x00016fff,
336 .mmu_trcr_mask = 0x00ffffff,
337 .nwindows = 8,
338 .features = CPU_DEFAULT_FEATURES,
341 .name = "Fujitsu MB86907",
342 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
343 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
344 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
345 .mmu_bm = 0x00004000,
346 .mmu_ctpr_mask = 0xffffffc0,
347 .mmu_cxr_mask = 0x000000ff,
348 .mmu_sfsr_mask = 0x00016fff,
349 .mmu_trcr_mask = 0xffffffff,
350 .nwindows = 8,
351 .features = CPU_DEFAULT_FEATURES,
354 .name = "TI MicroSparc I",
355 .iu_version = 0x41000000,
356 .fpu_version = 4 << 17,
357 .mmu_version = 0x41000000,
358 .mmu_bm = 0x00004000,
359 .mmu_ctpr_mask = 0x007ffff0,
360 .mmu_cxr_mask = 0x0000003f,
361 .mmu_sfsr_mask = 0x00016fff,
362 .mmu_trcr_mask = 0x0000003f,
363 .nwindows = 7,
364 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
365 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
366 CPU_FEATURE_FMUL,
369 .name = "TI MicroSparc II",
370 .iu_version = 0x42000000,
371 .fpu_version = 4 << 17,
372 .mmu_version = 0x02000000,
373 .mmu_bm = 0x00004000,
374 .mmu_ctpr_mask = 0x00ffffc0,
375 .mmu_cxr_mask = 0x000000ff,
376 .mmu_sfsr_mask = 0x00016fff,
377 .mmu_trcr_mask = 0x00ffffff,
378 .nwindows = 8,
379 .features = CPU_DEFAULT_FEATURES,
382 .name = "TI MicroSparc IIep",
383 .iu_version = 0x42000000,
384 .fpu_version = 4 << 17,
385 .mmu_version = 0x04000000,
386 .mmu_bm = 0x00004000,
387 .mmu_ctpr_mask = 0x00ffffc0,
388 .mmu_cxr_mask = 0x000000ff,
389 .mmu_sfsr_mask = 0x00016bff,
390 .mmu_trcr_mask = 0x00ffffff,
391 .nwindows = 8,
392 .features = CPU_DEFAULT_FEATURES,
395 .name = "TI SuperSparc 40", /* STP1020NPGA */
396 .iu_version = 0x41000000, /* SuperSPARC 2.x */
397 .fpu_version = 0 << 17,
398 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
399 .mmu_bm = 0x00002000,
400 .mmu_ctpr_mask = 0xffffffc0,
401 .mmu_cxr_mask = 0x0000ffff,
402 .mmu_sfsr_mask = 0xffffffff,
403 .mmu_trcr_mask = 0xffffffff,
404 .nwindows = 8,
405 .features = CPU_DEFAULT_FEATURES,
408 .name = "TI SuperSparc 50", /* STP1020PGA */
409 .iu_version = 0x40000000, /* SuperSPARC 3.x */
410 .fpu_version = 0 << 17,
411 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
412 .mmu_bm = 0x00002000,
413 .mmu_ctpr_mask = 0xffffffc0,
414 .mmu_cxr_mask = 0x0000ffff,
415 .mmu_sfsr_mask = 0xffffffff,
416 .mmu_trcr_mask = 0xffffffff,
417 .nwindows = 8,
418 .features = CPU_DEFAULT_FEATURES,
421 .name = "TI SuperSparc 51",
422 .iu_version = 0x40000000, /* SuperSPARC 3.x */
423 .fpu_version = 0 << 17,
424 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
425 .mmu_bm = 0x00002000,
426 .mmu_ctpr_mask = 0xffffffc0,
427 .mmu_cxr_mask = 0x0000ffff,
428 .mmu_sfsr_mask = 0xffffffff,
429 .mmu_trcr_mask = 0xffffffff,
430 .mxcc_version = 0x00000104,
431 .nwindows = 8,
432 .features = CPU_DEFAULT_FEATURES,
435 .name = "TI SuperSparc 60", /* STP1020APGA */
436 .iu_version = 0x40000000, /* SuperSPARC 3.x */
437 .fpu_version = 0 << 17,
438 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
439 .mmu_bm = 0x00002000,
440 .mmu_ctpr_mask = 0xffffffc0,
441 .mmu_cxr_mask = 0x0000ffff,
442 .mmu_sfsr_mask = 0xffffffff,
443 .mmu_trcr_mask = 0xffffffff,
444 .nwindows = 8,
445 .features = CPU_DEFAULT_FEATURES,
448 .name = "TI SuperSparc 61",
449 .iu_version = 0x44000000, /* SuperSPARC 3.x */
450 .fpu_version = 0 << 17,
451 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
452 .mmu_bm = 0x00002000,
453 .mmu_ctpr_mask = 0xffffffc0,
454 .mmu_cxr_mask = 0x0000ffff,
455 .mmu_sfsr_mask = 0xffffffff,
456 .mmu_trcr_mask = 0xffffffff,
457 .mxcc_version = 0x00000104,
458 .nwindows = 8,
459 .features = CPU_DEFAULT_FEATURES,
462 .name = "TI SuperSparc II",
463 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
464 .fpu_version = 0 << 17,
465 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
466 .mmu_bm = 0x00002000,
467 .mmu_ctpr_mask = 0xffffffc0,
468 .mmu_cxr_mask = 0x0000ffff,
469 .mmu_sfsr_mask = 0xffffffff,
470 .mmu_trcr_mask = 0xffffffff,
471 .mxcc_version = 0x00000104,
472 .nwindows = 8,
473 .features = CPU_DEFAULT_FEATURES,
476 .name = "LEON2",
477 .iu_version = 0xf2000000,
478 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
479 .mmu_version = 0xf2000000,
480 .mmu_bm = 0x00004000,
481 .mmu_ctpr_mask = 0x007ffff0,
482 .mmu_cxr_mask = 0x0000003f,
483 .mmu_sfsr_mask = 0xffffffff,
484 .mmu_trcr_mask = 0xffffffff,
485 .nwindows = 8,
486 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
489 .name = "LEON3",
490 .iu_version = 0xf3000000,
491 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
492 .mmu_version = 0xf3000000,
493 .mmu_bm = 0x00000000,
494 .mmu_ctpr_mask = 0xfffffffc,
495 .mmu_cxr_mask = 0x000000ff,
496 .mmu_sfsr_mask = 0xffffffff,
497 .mmu_trcr_mask = 0xffffffff,
498 .nwindows = 8,
499 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
500 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
501 CPU_FEATURE_CASA,
503 #endif
506 static const char * const feature_name[] = {
507 "float",
508 "float128",
509 "swap",
510 "mul",
511 "div",
512 "flush",
513 "fsqrt",
514 "fmul",
515 "vis1",
516 "vis2",
517 "fsmuld",
518 "hypv",
519 "cmt",
520 "gl",
523 static void print_features(FILE *f, fprintf_function cpu_fprintf,
524 uint32_t features, const char *prefix)
526 unsigned int i;
528 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
529 if (feature_name[i] && (features & (1 << i))) {
530 if (prefix) {
531 (*cpu_fprintf)(f, "%s", prefix);
533 (*cpu_fprintf)(f, "%s ", feature_name[i]);
538 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
540 unsigned int i;
542 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
543 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
544 *features |= 1 << i;
545 return;
548 error_report("CPU feature %s not found", flagname);
551 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
553 unsigned int i;
554 const sparc_def_t *def = NULL;
556 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
557 if (strcasecmp(name, sparc_defs[i].name) == 0) {
558 def = &sparc_defs[i];
561 if (!def) {
562 return -1;
564 memcpy(cpu_def, def, sizeof(*def));
565 return 0;
568 static void sparc_cpu_parse_features(CPUState *cs, char *features,
569 Error **errp)
571 SPARCCPU *cpu = SPARC_CPU(cs);
572 sparc_def_t *cpu_def = cpu->env.def;
573 char *featurestr;
574 uint32_t plus_features = 0;
575 uint32_t minus_features = 0;
576 uint64_t iu_version;
577 uint32_t fpu_version, mmu_version, nwindows;
579 featurestr = features ? strtok(features, ",") : NULL;
580 while (featurestr) {
581 char *val;
583 if (featurestr[0] == '+') {
584 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
585 } else if (featurestr[0] == '-') {
586 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
587 } else if ((val = strchr(featurestr, '='))) {
588 *val = 0; val++;
589 if (!strcmp(featurestr, "iu_version")) {
590 char *err;
592 iu_version = strtoll(val, &err, 0);
593 if (!*val || *err) {
594 error_setg(errp, "bad numerical value %s", val);
595 return;
597 cpu_def->iu_version = iu_version;
598 #ifdef DEBUG_FEATURES
599 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
600 #endif
601 } else if (!strcmp(featurestr, "fpu_version")) {
602 char *err;
604 fpu_version = strtol(val, &err, 0);
605 if (!*val || *err) {
606 error_setg(errp, "bad numerical value %s", val);
607 return;
609 cpu_def->fpu_version = fpu_version;
610 #ifdef DEBUG_FEATURES
611 fprintf(stderr, "fpu_version %x\n", fpu_version);
612 #endif
613 } else if (!strcmp(featurestr, "mmu_version")) {
614 char *err;
616 mmu_version = strtol(val, &err, 0);
617 if (!*val || *err) {
618 error_setg(errp, "bad numerical value %s", val);
619 return;
621 cpu_def->mmu_version = mmu_version;
622 #ifdef DEBUG_FEATURES
623 fprintf(stderr, "mmu_version %x\n", mmu_version);
624 #endif
625 } else if (!strcmp(featurestr, "nwindows")) {
626 char *err;
628 nwindows = strtol(val, &err, 0);
629 if (!*val || *err || nwindows > MAX_NWINDOWS ||
630 nwindows < MIN_NWINDOWS) {
631 error_setg(errp, "bad numerical value %s", val);
632 return;
634 cpu_def->nwindows = nwindows;
635 #ifdef DEBUG_FEATURES
636 fprintf(stderr, "nwindows %d\n", nwindows);
637 #endif
638 } else {
639 error_setg(errp, "unrecognized feature %s", featurestr);
640 return;
642 } else {
643 error_setg(errp, "feature string `%s' not in format "
644 "(+feature|-feature|feature=xyz)", featurestr);
645 return;
647 featurestr = strtok(NULL, ",");
649 cpu_def->features |= plus_features;
650 cpu_def->features &= ~minus_features;
651 #ifdef DEBUG_FEATURES
652 print_features(stderr, fprintf, cpu_def->features, NULL);
653 #endif
656 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
658 unsigned int i;
660 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
661 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
662 " FPU %08x MMU %08x NWINS %d ",
663 sparc_defs[i].name,
664 sparc_defs[i].iu_version,
665 sparc_defs[i].fpu_version,
666 sparc_defs[i].mmu_version,
667 sparc_defs[i].nwindows);
668 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
669 ~sparc_defs[i].features, "-");
670 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
671 sparc_defs[i].features, "+");
672 (*cpu_fprintf)(f, "\n");
674 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
675 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
676 (*cpu_fprintf)(f, "\n");
677 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
678 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
679 (*cpu_fprintf)(f, "\n");
680 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
681 "fpu_version mmu_version nwindows\n");
684 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
685 uint32_t cc)
687 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
688 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
689 cc & PSR_CARRY ? 'C' : '-');
692 #ifdef TARGET_SPARC64
693 #define REGS_PER_LINE 4
694 #else
695 #define REGS_PER_LINE 8
696 #endif
698 void sparc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
699 int flags)
701 SPARCCPU *cpu = SPARC_CPU(cs);
702 CPUSPARCState *env = &cpu->env;
703 int i, x;
705 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
706 env->npc);
708 for (i = 0; i < 8; i++) {
709 if (i % REGS_PER_LINE == 0) {
710 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
712 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
713 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
714 cpu_fprintf(f, "\n");
717 for (x = 0; x < 3; x++) {
718 for (i = 0; i < 8; i++) {
719 if (i % REGS_PER_LINE == 0) {
720 cpu_fprintf(f, "%%%c%d-%d: ",
721 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
722 i, i + REGS_PER_LINE - 1);
724 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
725 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
726 cpu_fprintf(f, "\n");
731 for (i = 0; i < TARGET_DPREGS; i++) {
732 if ((i & 3) == 0) {
733 cpu_fprintf(f, "%%f%02d: ", i * 2);
735 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
736 if ((i & 3) == 3) {
737 cpu_fprintf(f, "\n");
740 #ifdef TARGET_SPARC64
741 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
742 (unsigned)cpu_get_ccr(env));
743 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
744 cpu_fprintf(f, " xcc: ");
745 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
746 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
747 env->psrpil);
748 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
749 "cleanwin: %d cwp: %d\n",
750 env->cansave, env->canrestore, env->otherwin, env->wstate,
751 env->cleanwin, env->nwindows - 1 - env->cwp);
752 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
753 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
754 #else
755 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
756 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
757 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
758 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
759 env->wim);
760 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
761 env->fsr, env->y);
762 #endif
763 cpu_fprintf(f, "\n");
766 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
768 SPARCCPU *cpu = SPARC_CPU(cs);
770 cpu->env.pc = value;
771 cpu->env.npc = value + 4;
774 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
776 SPARCCPU *cpu = SPARC_CPU(cs);
778 cpu->env.pc = tb->pc;
779 cpu->env.npc = tb->cs_base;
782 static bool sparc_cpu_has_work(CPUState *cs)
784 SPARCCPU *cpu = SPARC_CPU(cs);
785 CPUSPARCState *env = &cpu->env;
787 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
788 cpu_interrupts_enabled(env);
791 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
793 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
794 #if defined(CONFIG_USER_ONLY)
795 SPARCCPU *cpu = SPARC_CPU(dev);
796 CPUSPARCState *env = &cpu->env;
798 if ((env->def->features & CPU_FEATURE_FLOAT)) {
799 env->def->features |= CPU_FEATURE_FLOAT128;
801 #endif
803 qemu_init_vcpu(CPU(dev));
805 scc->parent_realize(dev, errp);
808 static void sparc_cpu_initfn(Object *obj)
810 CPUState *cs = CPU(obj);
811 SPARCCPU *cpu = SPARC_CPU(obj);
812 CPUSPARCState *env = &cpu->env;
814 cs->env_ptr = env;
815 cpu_exec_init(cs, &error_abort);
817 if (tcg_enabled()) {
818 gen_intermediate_code_init(env);
822 static void sparc_cpu_uninitfn(Object *obj)
824 SPARCCPU *cpu = SPARC_CPU(obj);
825 CPUSPARCState *env = &cpu->env;
827 g_free(env->def);
830 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
832 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
833 CPUClass *cc = CPU_CLASS(oc);
834 DeviceClass *dc = DEVICE_CLASS(oc);
836 scc->parent_realize = dc->realize;
837 dc->realize = sparc_cpu_realizefn;
839 scc->parent_reset = cc->reset;
840 cc->reset = sparc_cpu_reset;
842 cc->parse_features = sparc_cpu_parse_features;
843 cc->has_work = sparc_cpu_has_work;
844 cc->do_interrupt = sparc_cpu_do_interrupt;
845 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
846 cc->dump_state = sparc_cpu_dump_state;
847 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
848 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
849 #endif
850 cc->set_pc = sparc_cpu_set_pc;
851 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
852 cc->gdb_read_register = sparc_cpu_gdb_read_register;
853 cc->gdb_write_register = sparc_cpu_gdb_write_register;
854 #ifdef CONFIG_USER_ONLY
855 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
856 #else
857 cc->do_unassigned_access = sparc_cpu_unassigned_access;
858 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
859 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
860 cc->vmsd = &vmstate_sparc_cpu;
861 #endif
862 cc->disas_set_info = cpu_sparc_disas_set_info;
864 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
865 cc->gdb_num_core_regs = 86;
866 #else
867 cc->gdb_num_core_regs = 72;
868 #endif
871 * Reason: sparc_cpu_initfn() calls cpu_exec_init(), which saves
872 * the object in cpus -> dangling pointer after final
873 * object_unref().
875 dc->cannot_destroy_with_object_finalize_yet = true;
878 static const TypeInfo sparc_cpu_type_info = {
879 .name = TYPE_SPARC_CPU,
880 .parent = TYPE_CPU,
881 .instance_size = sizeof(SPARCCPU),
882 .instance_init = sparc_cpu_initfn,
883 .instance_finalize = sparc_cpu_uninitfn,
884 .abstract = false,
885 .class_size = sizeof(SPARCCPUClass),
886 .class_init = sparc_cpu_class_init,
889 static void sparc_cpu_register_types(void)
891 type_register_static(&sparc_cpu_type_info);
894 type_init(sparc_cpu_register_types)