sparc: convert cpu features to qdev properties
[qemu/kevin.git] / target / sparc / cpu.c
blob82ab5ad8d9039dc733cda6d434f4414dc5dc6157
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"
25 #include "hw/qdev-properties.h"
26 #include "qapi/visitor.h"
28 //#define DEBUG_FEATURES
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, end_reset_fields));
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;
61 if (!cpu_has_hypervisor(env)) {
62 env->pstate |= PS_AG;
64 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
65 env->tl = env->maxtl;
66 env->gl = 2;
67 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
68 env->lsu = 0;
69 #else
70 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
71 env->mmuregs[0] |= env->def.mmu_bm;
72 #endif
73 env->pc = 0;
74 env->npc = env->pc + 4;
75 #endif
76 env->cache_control = 0;
79 static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
81 if (interrupt_request & CPU_INTERRUPT_HARD) {
82 SPARCCPU *cpu = SPARC_CPU(cs);
83 CPUSPARCState *env = &cpu->env;
85 if (cpu_interrupts_enabled(env) && env->interrupt_index > 0) {
86 int pil = env->interrupt_index & 0xf;
87 int type = env->interrupt_index & 0xf0;
89 if (type != TT_EXTINT || cpu_pil_allowed(env, pil)) {
90 cs->exception_index = env->interrupt_index;
91 sparc_cpu_do_interrupt(cs);
92 return true;
96 return false;
99 static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
101 info->print_insn = print_insn_sparc;
102 #ifdef TARGET_SPARC64
103 info->mach = bfd_mach_sparc_v9b;
104 #endif
107 static void sparc_cpu_parse_features(CPUState *cs, char *features,
108 Error **errp);
110 static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
112 CPUSPARCState *env = &cpu->env;
113 char *s = g_strdup(cpu_model);
114 char *featurestr = strtok(s, ",");
115 Error *err = NULL;
117 featurestr = strtok(NULL, ",");
118 sparc_cpu_parse_features(CPU(cpu), featurestr, &err);
119 g_free(s);
120 if (err) {
121 error_report_err(err);
122 return -1;
125 env->version = env->def.iu_version;
126 env->fsr = env->def.fpu_version;
127 env->nwindows = env->def.nwindows;
128 #if !defined(TARGET_SPARC64)
129 env->mmuregs[0] |= env->def.mmu_version;
130 cpu_sparc_set_id(env, 0);
131 env->mxccregs[7] |= env->def.mxcc_version;
132 #else
133 env->mmu_version = env->def.mmu_version;
134 env->maxtl = env->def.maxtl;
135 env->version |= env->def.maxtl << 8;
136 env->version |= env->def.nwindows - 1;
137 #endif
138 return 0;
141 SPARCCPU *cpu_sparc_init(const char *cpu_model)
143 SPARCCPU *cpu;
144 ObjectClass *oc;
145 char *str, *name;
147 str = g_strdup(cpu_model);
148 name = strtok(str, ",");
149 oc = cpu_class_by_name(TYPE_SPARC_CPU, name);
150 g_free(str);
151 if (oc == NULL) {
152 return NULL;
155 cpu = SPARC_CPU(object_new(object_class_get_name(oc)));
157 if (cpu_sparc_register(cpu, cpu_model) < 0) {
158 object_unref(OBJECT(cpu));
159 return NULL;
162 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
164 return cpu;
167 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
169 #if !defined(TARGET_SPARC64)
170 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
171 #endif
174 static const sparc_def_t sparc_defs[] = {
175 #ifdef TARGET_SPARC64
177 .name = "Fujitsu Sparc64",
178 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
179 .fpu_version = 0x00000000,
180 .mmu_version = mmu_us_12,
181 .nwindows = 4,
182 .maxtl = 4,
183 .features = CPU_DEFAULT_FEATURES,
186 .name = "Fujitsu Sparc64 III",
187 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
188 .fpu_version = 0x00000000,
189 .mmu_version = mmu_us_12,
190 .nwindows = 5,
191 .maxtl = 4,
192 .features = CPU_DEFAULT_FEATURES,
195 .name = "Fujitsu Sparc64 IV",
196 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
197 .fpu_version = 0x00000000,
198 .mmu_version = mmu_us_12,
199 .nwindows = 8,
200 .maxtl = 5,
201 .features = CPU_DEFAULT_FEATURES,
204 .name = "Fujitsu Sparc64 V",
205 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 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 I",
214 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 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 II",
223 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 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 IIi",
232 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
233 .fpu_version = 0x00000000,
234 .mmu_version = mmu_us_12,
235 .nwindows = 8,
236 .maxtl = 5,
237 .features = CPU_DEFAULT_FEATURES,
240 .name = "TI UltraSparc IIe",
241 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 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",
250 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
251 .fpu_version = 0x00000000,
252 .mmu_version = mmu_us_12,
253 .nwindows = 8,
254 .maxtl = 5,
255 .features = CPU_DEFAULT_FEATURES,
258 .name = "Sun UltraSparc III Cu",
259 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
260 .fpu_version = 0x00000000,
261 .mmu_version = mmu_us_3,
262 .nwindows = 8,
263 .maxtl = 5,
264 .features = CPU_DEFAULT_FEATURES,
267 .name = "Sun UltraSparc IIIi",
268 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
269 .fpu_version = 0x00000000,
270 .mmu_version = mmu_us_12,
271 .nwindows = 8,
272 .maxtl = 5,
273 .features = CPU_DEFAULT_FEATURES,
276 .name = "Sun UltraSparc IV",
277 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
278 .fpu_version = 0x00000000,
279 .mmu_version = mmu_us_4,
280 .nwindows = 8,
281 .maxtl = 5,
282 .features = CPU_DEFAULT_FEATURES,
285 .name = "Sun UltraSparc IV+",
286 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
287 .fpu_version = 0x00000000,
288 .mmu_version = mmu_us_12,
289 .nwindows = 8,
290 .maxtl = 5,
291 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
294 .name = "Sun UltraSparc IIIi+",
295 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
296 .fpu_version = 0x00000000,
297 .mmu_version = mmu_us_3,
298 .nwindows = 8,
299 .maxtl = 5,
300 .features = CPU_DEFAULT_FEATURES,
303 .name = "Sun UltraSparc T1",
304 /* defined in sparc_ifu_fdp.v and ctu.h */
305 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
306 .fpu_version = 0x00000000,
307 .mmu_version = mmu_sun4v,
308 .nwindows = 8,
309 .maxtl = 6,
310 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
311 | CPU_FEATURE_GL,
314 .name = "Sun UltraSparc T2",
315 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
316 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
317 .fpu_version = 0x00000000,
318 .mmu_version = mmu_sun4v,
319 .nwindows = 8,
320 .maxtl = 6,
321 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
322 | CPU_FEATURE_GL,
325 .name = "NEC UltraSparc I",
326 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
327 .fpu_version = 0x00000000,
328 .mmu_version = mmu_us_12,
329 .nwindows = 8,
330 .maxtl = 5,
331 .features = CPU_DEFAULT_FEATURES,
333 #else
335 .name = "Fujitsu MB86904",
336 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
337 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
338 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
339 .mmu_bm = 0x00004000,
340 .mmu_ctpr_mask = 0x00ffffc0,
341 .mmu_cxr_mask = 0x000000ff,
342 .mmu_sfsr_mask = 0x00016fff,
343 .mmu_trcr_mask = 0x00ffffff,
344 .nwindows = 8,
345 .features = CPU_DEFAULT_FEATURES,
348 .name = "Fujitsu MB86907",
349 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
350 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
351 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
352 .mmu_bm = 0x00004000,
353 .mmu_ctpr_mask = 0xffffffc0,
354 .mmu_cxr_mask = 0x000000ff,
355 .mmu_sfsr_mask = 0x00016fff,
356 .mmu_trcr_mask = 0xffffffff,
357 .nwindows = 8,
358 .features = CPU_DEFAULT_FEATURES,
361 .name = "TI MicroSparc I",
362 .iu_version = 0x41000000,
363 .fpu_version = 4 << 17,
364 .mmu_version = 0x41000000,
365 .mmu_bm = 0x00004000,
366 .mmu_ctpr_mask = 0x007ffff0,
367 .mmu_cxr_mask = 0x0000003f,
368 .mmu_sfsr_mask = 0x00016fff,
369 .mmu_trcr_mask = 0x0000003f,
370 .nwindows = 7,
371 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
372 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
373 CPU_FEATURE_FMUL,
376 .name = "TI MicroSparc II",
377 .iu_version = 0x42000000,
378 .fpu_version = 4 << 17,
379 .mmu_version = 0x02000000,
380 .mmu_bm = 0x00004000,
381 .mmu_ctpr_mask = 0x00ffffc0,
382 .mmu_cxr_mask = 0x000000ff,
383 .mmu_sfsr_mask = 0x00016fff,
384 .mmu_trcr_mask = 0x00ffffff,
385 .nwindows = 8,
386 .features = CPU_DEFAULT_FEATURES,
389 .name = "TI MicroSparc IIep",
390 .iu_version = 0x42000000,
391 .fpu_version = 4 << 17,
392 .mmu_version = 0x04000000,
393 .mmu_bm = 0x00004000,
394 .mmu_ctpr_mask = 0x00ffffc0,
395 .mmu_cxr_mask = 0x000000ff,
396 .mmu_sfsr_mask = 0x00016bff,
397 .mmu_trcr_mask = 0x00ffffff,
398 .nwindows = 8,
399 .features = CPU_DEFAULT_FEATURES,
402 .name = "TI SuperSparc 40", /* STP1020NPGA */
403 .iu_version = 0x41000000, /* SuperSPARC 2.x */
404 .fpu_version = 0 << 17,
405 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
406 .mmu_bm = 0x00002000,
407 .mmu_ctpr_mask = 0xffffffc0,
408 .mmu_cxr_mask = 0x0000ffff,
409 .mmu_sfsr_mask = 0xffffffff,
410 .mmu_trcr_mask = 0xffffffff,
411 .nwindows = 8,
412 .features = CPU_DEFAULT_FEATURES,
415 .name = "TI SuperSparc 50", /* STP1020PGA */
416 .iu_version = 0x40000000, /* SuperSPARC 3.x */
417 .fpu_version = 0 << 17,
418 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
419 .mmu_bm = 0x00002000,
420 .mmu_ctpr_mask = 0xffffffc0,
421 .mmu_cxr_mask = 0x0000ffff,
422 .mmu_sfsr_mask = 0xffffffff,
423 .mmu_trcr_mask = 0xffffffff,
424 .nwindows = 8,
425 .features = CPU_DEFAULT_FEATURES,
428 .name = "TI SuperSparc 51",
429 .iu_version = 0x40000000, /* SuperSPARC 3.x */
430 .fpu_version = 0 << 17,
431 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
432 .mmu_bm = 0x00002000,
433 .mmu_ctpr_mask = 0xffffffc0,
434 .mmu_cxr_mask = 0x0000ffff,
435 .mmu_sfsr_mask = 0xffffffff,
436 .mmu_trcr_mask = 0xffffffff,
437 .mxcc_version = 0x00000104,
438 .nwindows = 8,
439 .features = CPU_DEFAULT_FEATURES,
442 .name = "TI SuperSparc 60", /* STP1020APGA */
443 .iu_version = 0x40000000, /* SuperSPARC 3.x */
444 .fpu_version = 0 << 17,
445 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
446 .mmu_bm = 0x00002000,
447 .mmu_ctpr_mask = 0xffffffc0,
448 .mmu_cxr_mask = 0x0000ffff,
449 .mmu_sfsr_mask = 0xffffffff,
450 .mmu_trcr_mask = 0xffffffff,
451 .nwindows = 8,
452 .features = CPU_DEFAULT_FEATURES,
455 .name = "TI SuperSparc 61",
456 .iu_version = 0x44000000, /* SuperSPARC 3.x */
457 .fpu_version = 0 << 17,
458 .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
459 .mmu_bm = 0x00002000,
460 .mmu_ctpr_mask = 0xffffffc0,
461 .mmu_cxr_mask = 0x0000ffff,
462 .mmu_sfsr_mask = 0xffffffff,
463 .mmu_trcr_mask = 0xffffffff,
464 .mxcc_version = 0x00000104,
465 .nwindows = 8,
466 .features = CPU_DEFAULT_FEATURES,
469 .name = "TI SuperSparc II",
470 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
471 .fpu_version = 0 << 17,
472 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
473 .mmu_bm = 0x00002000,
474 .mmu_ctpr_mask = 0xffffffc0,
475 .mmu_cxr_mask = 0x0000ffff,
476 .mmu_sfsr_mask = 0xffffffff,
477 .mmu_trcr_mask = 0xffffffff,
478 .mxcc_version = 0x00000104,
479 .nwindows = 8,
480 .features = CPU_DEFAULT_FEATURES,
483 .name = "LEON2",
484 .iu_version = 0xf2000000,
485 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
486 .mmu_version = 0xf2000000,
487 .mmu_bm = 0x00004000,
488 .mmu_ctpr_mask = 0x007ffff0,
489 .mmu_cxr_mask = 0x0000003f,
490 .mmu_sfsr_mask = 0xffffffff,
491 .mmu_trcr_mask = 0xffffffff,
492 .nwindows = 8,
493 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
496 .name = "LEON3",
497 .iu_version = 0xf3000000,
498 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
499 .mmu_version = 0xf3000000,
500 .mmu_bm = 0x00000000,
501 .mmu_ctpr_mask = 0xfffffffc,
502 .mmu_cxr_mask = 0x000000ff,
503 .mmu_sfsr_mask = 0xffffffff,
504 .mmu_trcr_mask = 0xffffffff,
505 .nwindows = 8,
506 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
507 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
508 CPU_FEATURE_CASA,
510 #endif
513 static const char * const feature_name[] = {
514 "float",
515 "float128",
516 "swap",
517 "mul",
518 "div",
519 "flush",
520 "fsqrt",
521 "fmul",
522 "vis1",
523 "vis2",
524 "fsmuld",
525 "hypv",
526 "cmt",
527 "gl",
530 static void print_features(FILE *f, fprintf_function cpu_fprintf,
531 uint32_t features, const char *prefix)
533 unsigned int i;
535 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
536 if (feature_name[i] && (features & (1 << i))) {
537 if (prefix) {
538 (*cpu_fprintf)(f, "%s", prefix);
540 (*cpu_fprintf)(f, "%s ", feature_name[i]);
545 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
547 unsigned int i;
549 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
550 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
551 *features |= 1 << i;
552 return;
555 error_report("CPU feature %s not found", flagname);
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 gl: %d\n", env->asi, env->tl,
737 env->psrpil, env->gl);
738 cpu_fprintf(f, "tbr: " TARGET_FMT_lx " hpstate: " TARGET_FMT_lx " htba: "
739 TARGET_FMT_lx "\n", env->tbr, env->hpstate, env->htba);
740 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
741 "cleanwin: %d cwp: %d\n",
742 env->cansave, env->canrestore, env->otherwin, env->wstate,
743 env->cleanwin, env->nwindows - 1 - env->cwp);
744 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
745 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
747 #else
748 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
749 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
750 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
751 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
752 env->wim);
753 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
754 env->fsr, env->y);
755 #endif
756 cpu_fprintf(f, "\n");
759 static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
761 SPARCCPU *cpu = SPARC_CPU(cs);
763 cpu->env.pc = value;
764 cpu->env.npc = value + 4;
767 static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
769 SPARCCPU *cpu = SPARC_CPU(cs);
771 cpu->env.pc = tb->pc;
772 cpu->env.npc = tb->cs_base;
775 static bool sparc_cpu_has_work(CPUState *cs)
777 SPARCCPU *cpu = SPARC_CPU(cs);
778 CPUSPARCState *env = &cpu->env;
780 return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
781 cpu_interrupts_enabled(env);
784 static char *sparc_cpu_type_name(const char *cpu_model)
786 char *name = g_strdup_printf("%s-" TYPE_SPARC_CPU, cpu_model);
787 char *s = name;
789 /* SPARC cpu model names happen to have whitespaces,
790 * as type names shouldn't have spaces replace them with '-'
792 while ((s = strchr(s, ' '))) {
793 *s = '-';
796 return name;
799 static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model)
801 ObjectClass *oc;
802 char *typename;
804 if (cpu_model == NULL) {
805 return NULL;
808 typename = sparc_cpu_type_name(cpu_model);
809 oc = object_class_by_name(typename);
810 g_free(typename);
811 return oc;
814 static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
816 CPUState *cs = CPU(dev);
817 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
818 Error *local_err = NULL;
819 #if defined(CONFIG_USER_ONLY)
820 SPARCCPU *cpu = SPARC_CPU(dev);
821 CPUSPARCState *env = &cpu->env;
823 if ((env->def.features & CPU_FEATURE_FLOAT)) {
824 env->def.features |= CPU_FEATURE_FLOAT128;
826 #endif
828 cpu_exec_realizefn(cs, &local_err);
829 if (local_err != NULL) {
830 error_propagate(errp, local_err);
831 return;
834 qemu_init_vcpu(cs);
836 scc->parent_realize(dev, errp);
839 static void sparc_cpu_initfn(Object *obj)
841 CPUState *cs = CPU(obj);
842 SPARCCPU *cpu = SPARC_CPU(obj);
843 SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
844 CPUSPARCState *env = &cpu->env;
846 cs->env_ptr = env;
848 if (tcg_enabled()) {
849 gen_intermediate_code_init(env);
852 if (scc->cpu_def) {
853 env->def = *scc->cpu_def;
857 static void sparc_get_nwindows(Object *obj, Visitor *v, const char *name,
858 void *opaque, Error **errp)
860 SPARCCPU *cpu = SPARC_CPU(obj);
861 int64_t value = cpu->env.def.nwindows;
863 visit_type_int(v, name, &value, errp);
866 static void sparc_set_nwindows(Object *obj, Visitor *v, const char *name,
867 void *opaque, Error **errp)
869 const int64_t min = MIN_NWINDOWS;
870 const int64_t max = MAX_NWINDOWS;
871 SPARCCPU *cpu = SPARC_CPU(obj);
872 Error *err = NULL;
873 int64_t value;
875 visit_type_int(v, name, &value, &err);
876 if (err) {
877 error_propagate(errp, err);
878 return;
881 if (value < min || value > max) {
882 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
883 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
884 object_get_typename(obj), name ? name : "null",
885 value, min, max);
886 return;
888 cpu->env.def.nwindows = value;
891 static PropertyInfo qdev_prop_nwindows = {
892 .name = "int",
893 .get = sparc_get_nwindows,
894 .set = sparc_set_nwindows,
897 static Property sparc_cpu_properties[] = {
898 DEFINE_PROP_BIT("float", SPARCCPU, env.def.features, 0, false),
899 DEFINE_PROP_BIT("float128", SPARCCPU, env.def.features, 1, false),
900 DEFINE_PROP_BIT("swap", SPARCCPU, env.def.features, 2, false),
901 DEFINE_PROP_BIT("mul", SPARCCPU, env.def.features, 3, false),
902 DEFINE_PROP_BIT("div", SPARCCPU, env.def.features, 4, false),
903 DEFINE_PROP_BIT("flush", SPARCCPU, env.def.features, 5, false),
904 DEFINE_PROP_BIT("fsqrt", SPARCCPU, env.def.features, 6, false),
905 DEFINE_PROP_BIT("fmul", SPARCCPU, env.def.features, 7, false),
906 DEFINE_PROP_BIT("vis1", SPARCCPU, env.def.features, 8, false),
907 DEFINE_PROP_BIT("vis2", SPARCCPU, env.def.features, 9, false),
908 DEFINE_PROP_BIT("fsmuld", SPARCCPU, env.def.features, 10, false),
909 DEFINE_PROP_BIT("hypv", SPARCCPU, env.def.features, 11, false),
910 DEFINE_PROP_BIT("cmt", SPARCCPU, env.def.features, 12, false),
911 DEFINE_PROP_BIT("gl", SPARCCPU, env.def.features, 13, false),
912 DEFINE_PROP_UNSIGNED("iu-version", SPARCCPU, env.def.iu_version, 0,
913 qdev_prop_uint64, target_ulong),
914 DEFINE_PROP_UINT32("fpu-version", SPARCCPU, env.def.fpu_version, 0),
915 DEFINE_PROP_UINT32("mmu-version", SPARCCPU, env.def.mmu_version, 0),
916 { .name = "nwindows", .info = &qdev_prop_nwindows },
917 DEFINE_PROP_END_OF_LIST()
920 static void sparc_cpu_class_init(ObjectClass *oc, void *data)
922 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
923 CPUClass *cc = CPU_CLASS(oc);
924 DeviceClass *dc = DEVICE_CLASS(oc);
926 scc->parent_realize = dc->realize;
927 dc->realize = sparc_cpu_realizefn;
928 dc->props = sparc_cpu_properties;
930 scc->parent_reset = cc->reset;
931 cc->reset = sparc_cpu_reset;
933 cc->class_by_name = sparc_cpu_class_by_name;
934 cc->has_work = sparc_cpu_has_work;
935 cc->do_interrupt = sparc_cpu_do_interrupt;
936 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
937 cc->dump_state = sparc_cpu_dump_state;
938 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
939 cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
940 #endif
941 cc->set_pc = sparc_cpu_set_pc;
942 cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
943 cc->gdb_read_register = sparc_cpu_gdb_read_register;
944 cc->gdb_write_register = sparc_cpu_gdb_write_register;
945 #ifdef CONFIG_USER_ONLY
946 cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
947 #else
948 cc->do_unassigned_access = sparc_cpu_unassigned_access;
949 cc->do_unaligned_access = sparc_cpu_do_unaligned_access;
950 cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
951 cc->vmsd = &vmstate_sparc_cpu;
952 #endif
953 cc->disas_set_info = cpu_sparc_disas_set_info;
955 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
956 cc->gdb_num_core_regs = 86;
957 #else
958 cc->gdb_num_core_regs = 72;
959 #endif
962 static const TypeInfo sparc_cpu_type_info = {
963 .name = TYPE_SPARC_CPU,
964 .parent = TYPE_CPU,
965 .instance_size = sizeof(SPARCCPU),
966 .instance_init = sparc_cpu_initfn,
967 .abstract = true,
968 .class_size = sizeof(SPARCCPUClass),
969 .class_init = sparc_cpu_class_init,
972 static void sparc_cpu_cpudef_class_init(ObjectClass *oc, void *data)
974 SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
975 scc->cpu_def = data;
978 static void sparc_register_cpudef_type(const struct sparc_def_t *def)
980 char *typename = sparc_cpu_type_name(def->name);
981 TypeInfo ti = {
982 .name = typename,
983 .parent = TYPE_SPARC_CPU,
984 .class_init = sparc_cpu_cpudef_class_init,
985 .class_data = (void *)def,
988 type_register(&ti);
989 g_free(typename);
992 static void sparc_cpu_register_types(void)
994 int i;
996 type_register_static(&sparc_cpu_type_info);
997 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
998 sparc_register_cpudef_type(&sparc_defs[i]);
1002 type_init(sparc_cpu_register_types)