]> git.proxmox.com Git - mirror_qemu.git/blob - target-sparc/cpu_init.c
qed: remove incoming live migration blocker
[mirror_qemu.git] / target-sparc / cpu_init.c
1 /*
2 * Sparc CPU init helpers
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20 #include "cpu.h"
21
22 //#define DEBUG_FEATURES
23
24 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
25
26 void cpu_state_reset(CPUSPARCState *env)
27 {
28 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
29 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
30 log_cpu_state(env, 0);
31 }
32
33 memset(env, 0, offsetof(CPUSPARCState, breakpoints));
34 tlb_flush(env, 1);
35 env->cwp = 0;
36 #ifndef TARGET_SPARC64
37 env->wim = 1;
38 #endif
39 env->regwptr = env->regbase + (env->cwp * 16);
40 CC_OP = CC_OP_FLAGS;
41 #if defined(CONFIG_USER_ONLY)
42 #ifdef TARGET_SPARC64
43 env->cleanwin = env->nwindows - 2;
44 env->cansave = env->nwindows - 2;
45 env->pstate = PS_RMO | PS_PEF | PS_IE;
46 env->asi = 0x82; /* Primary no-fault */
47 #endif
48 #else
49 #if !defined(TARGET_SPARC64)
50 env->psret = 0;
51 env->psrs = 1;
52 env->psrps = 1;
53 #endif
54 #ifdef TARGET_SPARC64
55 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
56 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
57 env->tl = env->maxtl;
58 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
59 env->lsu = 0;
60 #else
61 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
62 env->mmuregs[0] |= env->def->mmu_bm;
63 #endif
64 env->pc = 0;
65 env->npc = env->pc + 4;
66 #endif
67 env->cache_control = 0;
68 }
69
70 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
71 {
72 sparc_def_t def1, *def = &def1;
73
74 if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
75 return -1;
76 }
77
78 env->def = g_new0(sparc_def_t, 1);
79 memcpy(env->def, def, sizeof(*def));
80 #if defined(CONFIG_USER_ONLY)
81 if ((env->def->features & CPU_FEATURE_FLOAT)) {
82 env->def->features |= CPU_FEATURE_FLOAT128;
83 }
84 #endif
85 env->cpu_model_str = cpu_model;
86 env->version = def->iu_version;
87 env->fsr = def->fpu_version;
88 env->nwindows = def->nwindows;
89 #if !defined(TARGET_SPARC64)
90 env->mmuregs[0] |= def->mmu_version;
91 cpu_sparc_set_id(env, 0);
92 env->mxccregs[7] |= def->mxcc_version;
93 #else
94 env->mmu_version = def->mmu_version;
95 env->maxtl = def->maxtl;
96 env->version |= def->maxtl << 8;
97 env->version |= def->nwindows - 1;
98 #endif
99 return 0;
100 }
101
102 static void cpu_sparc_close(CPUSPARCState *env)
103 {
104 g_free(env->def);
105 g_free(env);
106 }
107
108 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
109 {
110 CPUSPARCState *env;
111
112 env = g_new0(CPUSPARCState, 1);
113 cpu_exec_init(env);
114
115 gen_intermediate_code_init(env);
116
117 if (cpu_sparc_register(env, cpu_model) < 0) {
118 cpu_sparc_close(env);
119 return NULL;
120 }
121 qemu_init_vcpu(env);
122
123 return env;
124 }
125
126 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
127 {
128 #if !defined(TARGET_SPARC64)
129 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
130 #endif
131 }
132
133 static const sparc_def_t sparc_defs[] = {
134 #ifdef TARGET_SPARC64
135 {
136 .name = "Fujitsu Sparc64",
137 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
138 .fpu_version = 0x00000000,
139 .mmu_version = mmu_us_12,
140 .nwindows = 4,
141 .maxtl = 4,
142 .features = CPU_DEFAULT_FEATURES,
143 },
144 {
145 .name = "Fujitsu Sparc64 III",
146 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
147 .fpu_version = 0x00000000,
148 .mmu_version = mmu_us_12,
149 .nwindows = 5,
150 .maxtl = 4,
151 .features = CPU_DEFAULT_FEATURES,
152 },
153 {
154 .name = "Fujitsu Sparc64 IV",
155 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
156 .fpu_version = 0x00000000,
157 .mmu_version = mmu_us_12,
158 .nwindows = 8,
159 .maxtl = 5,
160 .features = CPU_DEFAULT_FEATURES,
161 },
162 {
163 .name = "Fujitsu Sparc64 V",
164 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
165 .fpu_version = 0x00000000,
166 .mmu_version = mmu_us_12,
167 .nwindows = 8,
168 .maxtl = 5,
169 .features = CPU_DEFAULT_FEATURES,
170 },
171 {
172 .name = "TI UltraSparc I",
173 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
174 .fpu_version = 0x00000000,
175 .mmu_version = mmu_us_12,
176 .nwindows = 8,
177 .maxtl = 5,
178 .features = CPU_DEFAULT_FEATURES,
179 },
180 {
181 .name = "TI UltraSparc II",
182 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
183 .fpu_version = 0x00000000,
184 .mmu_version = mmu_us_12,
185 .nwindows = 8,
186 .maxtl = 5,
187 .features = CPU_DEFAULT_FEATURES,
188 },
189 {
190 .name = "TI UltraSparc IIi",
191 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
192 .fpu_version = 0x00000000,
193 .mmu_version = mmu_us_12,
194 .nwindows = 8,
195 .maxtl = 5,
196 .features = CPU_DEFAULT_FEATURES,
197 },
198 {
199 .name = "TI UltraSparc IIe",
200 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
201 .fpu_version = 0x00000000,
202 .mmu_version = mmu_us_12,
203 .nwindows = 8,
204 .maxtl = 5,
205 .features = CPU_DEFAULT_FEATURES,
206 },
207 {
208 .name = "Sun UltraSparc III",
209 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
210 .fpu_version = 0x00000000,
211 .mmu_version = mmu_us_12,
212 .nwindows = 8,
213 .maxtl = 5,
214 .features = CPU_DEFAULT_FEATURES,
215 },
216 {
217 .name = "Sun UltraSparc III Cu",
218 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
219 .fpu_version = 0x00000000,
220 .mmu_version = mmu_us_3,
221 .nwindows = 8,
222 .maxtl = 5,
223 .features = CPU_DEFAULT_FEATURES,
224 },
225 {
226 .name = "Sun UltraSparc IIIi",
227 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
228 .fpu_version = 0x00000000,
229 .mmu_version = mmu_us_12,
230 .nwindows = 8,
231 .maxtl = 5,
232 .features = CPU_DEFAULT_FEATURES,
233 },
234 {
235 .name = "Sun UltraSparc IV",
236 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
237 .fpu_version = 0x00000000,
238 .mmu_version = mmu_us_4,
239 .nwindows = 8,
240 .maxtl = 5,
241 .features = CPU_DEFAULT_FEATURES,
242 },
243 {
244 .name = "Sun UltraSparc IV+",
245 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
246 .fpu_version = 0x00000000,
247 .mmu_version = mmu_us_12,
248 .nwindows = 8,
249 .maxtl = 5,
250 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
251 },
252 {
253 .name = "Sun UltraSparc IIIi+",
254 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
255 .fpu_version = 0x00000000,
256 .mmu_version = mmu_us_3,
257 .nwindows = 8,
258 .maxtl = 5,
259 .features = CPU_DEFAULT_FEATURES,
260 },
261 {
262 .name = "Sun UltraSparc T1",
263 /* defined in sparc_ifu_fdp.v and ctu.h */
264 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
265 .fpu_version = 0x00000000,
266 .mmu_version = mmu_sun4v,
267 .nwindows = 8,
268 .maxtl = 6,
269 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
270 | CPU_FEATURE_GL,
271 },
272 {
273 .name = "Sun UltraSparc T2",
274 /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
275 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
276 .fpu_version = 0x00000000,
277 .mmu_version = mmu_sun4v,
278 .nwindows = 8,
279 .maxtl = 6,
280 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
281 | CPU_FEATURE_GL,
282 },
283 {
284 .name = "NEC UltraSparc I",
285 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
286 .fpu_version = 0x00000000,
287 .mmu_version = mmu_us_12,
288 .nwindows = 8,
289 .maxtl = 5,
290 .features = CPU_DEFAULT_FEATURES,
291 },
292 #else
293 {
294 .name = "Fujitsu MB86900",
295 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
296 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
297 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
298 .mmu_bm = 0x00004000,
299 .mmu_ctpr_mask = 0x007ffff0,
300 .mmu_cxr_mask = 0x0000003f,
301 .mmu_sfsr_mask = 0xffffffff,
302 .mmu_trcr_mask = 0xffffffff,
303 .nwindows = 7,
304 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
305 },
306 {
307 .name = "Fujitsu MB86904",
308 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
309 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
310 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
311 .mmu_bm = 0x00004000,
312 .mmu_ctpr_mask = 0x00ffffc0,
313 .mmu_cxr_mask = 0x000000ff,
314 .mmu_sfsr_mask = 0x00016fff,
315 .mmu_trcr_mask = 0x00ffffff,
316 .nwindows = 8,
317 .features = CPU_DEFAULT_FEATURES,
318 },
319 {
320 .name = "Fujitsu MB86907",
321 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
322 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
323 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
324 .mmu_bm = 0x00004000,
325 .mmu_ctpr_mask = 0xffffffc0,
326 .mmu_cxr_mask = 0x000000ff,
327 .mmu_sfsr_mask = 0x00016fff,
328 .mmu_trcr_mask = 0xffffffff,
329 .nwindows = 8,
330 .features = CPU_DEFAULT_FEATURES,
331 },
332 {
333 .name = "LSI L64811",
334 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
335 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
336 .mmu_version = 0x10 << 24,
337 .mmu_bm = 0x00004000,
338 .mmu_ctpr_mask = 0x007ffff0,
339 .mmu_cxr_mask = 0x0000003f,
340 .mmu_sfsr_mask = 0xffffffff,
341 .mmu_trcr_mask = 0xffffffff,
342 .nwindows = 8,
343 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
344 CPU_FEATURE_FSMULD,
345 },
346 {
347 .name = "Cypress CY7C601",
348 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
349 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
350 .mmu_version = 0x10 << 24,
351 .mmu_bm = 0x00004000,
352 .mmu_ctpr_mask = 0x007ffff0,
353 .mmu_cxr_mask = 0x0000003f,
354 .mmu_sfsr_mask = 0xffffffff,
355 .mmu_trcr_mask = 0xffffffff,
356 .nwindows = 8,
357 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
358 CPU_FEATURE_FSMULD,
359 },
360 {
361 .name = "Cypress CY7C611",
362 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
363 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
364 .mmu_version = 0x10 << 24,
365 .mmu_bm = 0x00004000,
366 .mmu_ctpr_mask = 0x007ffff0,
367 .mmu_cxr_mask = 0x0000003f,
368 .mmu_sfsr_mask = 0xffffffff,
369 .mmu_trcr_mask = 0xffffffff,
370 .nwindows = 8,
371 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
372 CPU_FEATURE_FSMULD,
373 },
374 {
375 .name = "TI MicroSparc I",
376 .iu_version = 0x41000000,
377 .fpu_version = 4 << 17,
378 .mmu_version = 0x41000000,
379 .mmu_bm = 0x00004000,
380 .mmu_ctpr_mask = 0x007ffff0,
381 .mmu_cxr_mask = 0x0000003f,
382 .mmu_sfsr_mask = 0x00016fff,
383 .mmu_trcr_mask = 0x0000003f,
384 .nwindows = 7,
385 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
386 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
387 CPU_FEATURE_FMUL,
388 },
389 {
390 .name = "TI MicroSparc II",
391 .iu_version = 0x42000000,
392 .fpu_version = 4 << 17,
393 .mmu_version = 0x02000000,
394 .mmu_bm = 0x00004000,
395 .mmu_ctpr_mask = 0x00ffffc0,
396 .mmu_cxr_mask = 0x000000ff,
397 .mmu_sfsr_mask = 0x00016fff,
398 .mmu_trcr_mask = 0x00ffffff,
399 .nwindows = 8,
400 .features = CPU_DEFAULT_FEATURES,
401 },
402 {
403 .name = "TI MicroSparc IIep",
404 .iu_version = 0x42000000,
405 .fpu_version = 4 << 17,
406 .mmu_version = 0x04000000,
407 .mmu_bm = 0x00004000,
408 .mmu_ctpr_mask = 0x00ffffc0,
409 .mmu_cxr_mask = 0x000000ff,
410 .mmu_sfsr_mask = 0x00016bff,
411 .mmu_trcr_mask = 0x00ffffff,
412 .nwindows = 8,
413 .features = CPU_DEFAULT_FEATURES,
414 },
415 {
416 .name = "TI SuperSparc 40", /* STP1020NPGA */
417 .iu_version = 0x41000000, /* SuperSPARC 2.x */
418 .fpu_version = 0 << 17,
419 .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
420 .mmu_bm = 0x00002000,
421 .mmu_ctpr_mask = 0xffffffc0,
422 .mmu_cxr_mask = 0x0000ffff,
423 .mmu_sfsr_mask = 0xffffffff,
424 .mmu_trcr_mask = 0xffffffff,
425 .nwindows = 8,
426 .features = CPU_DEFAULT_FEATURES,
427 },
428 {
429 .name = "TI SuperSparc 50", /* STP1020PGA */
430 .iu_version = 0x40000000, /* SuperSPARC 3.x */
431 .fpu_version = 0 << 17,
432 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
433 .mmu_bm = 0x00002000,
434 .mmu_ctpr_mask = 0xffffffc0,
435 .mmu_cxr_mask = 0x0000ffff,
436 .mmu_sfsr_mask = 0xffffffff,
437 .mmu_trcr_mask = 0xffffffff,
438 .nwindows = 8,
439 .features = CPU_DEFAULT_FEATURES,
440 },
441 {
442 .name = "TI SuperSparc 51",
443 .iu_version = 0x40000000, /* SuperSPARC 3.x */
444 .fpu_version = 0 << 17,
445 .mmu_version = 0x01000000, /* SuperSPARC 3.x, 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 .mxcc_version = 0x00000104,
452 .nwindows = 8,
453 .features = CPU_DEFAULT_FEATURES,
454 },
455 {
456 .name = "TI SuperSparc 60", /* STP1020APGA */
457 .iu_version = 0x40000000, /* SuperSPARC 3.x */
458 .fpu_version = 0 << 17,
459 .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
460 .mmu_bm = 0x00002000,
461 .mmu_ctpr_mask = 0xffffffc0,
462 .mmu_cxr_mask = 0x0000ffff,
463 .mmu_sfsr_mask = 0xffffffff,
464 .mmu_trcr_mask = 0xffffffff,
465 .nwindows = 8,
466 .features = CPU_DEFAULT_FEATURES,
467 },
468 {
469 .name = "TI SuperSparc 61",
470 .iu_version = 0x44000000, /* SuperSPARC 3.x */
471 .fpu_version = 0 << 17,
472 .mmu_version = 0x01000000, /* SuperSPARC 3.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,
481 },
482 {
483 .name = "TI SuperSparc II",
484 .iu_version = 0x40000000, /* SuperSPARC II 1.x */
485 .fpu_version = 0 << 17,
486 .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
487 .mmu_bm = 0x00002000,
488 .mmu_ctpr_mask = 0xffffffc0,
489 .mmu_cxr_mask = 0x0000ffff,
490 .mmu_sfsr_mask = 0xffffffff,
491 .mmu_trcr_mask = 0xffffffff,
492 .mxcc_version = 0x00000104,
493 .nwindows = 8,
494 .features = CPU_DEFAULT_FEATURES,
495 },
496 {
497 .name = "Ross RT625",
498 .iu_version = 0x1e000000,
499 .fpu_version = 1 << 17,
500 .mmu_version = 0x1e000000,
501 .mmu_bm = 0x00004000,
502 .mmu_ctpr_mask = 0x007ffff0,
503 .mmu_cxr_mask = 0x0000003f,
504 .mmu_sfsr_mask = 0xffffffff,
505 .mmu_trcr_mask = 0xffffffff,
506 .nwindows = 8,
507 .features = CPU_DEFAULT_FEATURES,
508 },
509 {
510 .name = "Ross RT620",
511 .iu_version = 0x1f000000,
512 .fpu_version = 1 << 17,
513 .mmu_version = 0x1f000000,
514 .mmu_bm = 0x00004000,
515 .mmu_ctpr_mask = 0x007ffff0,
516 .mmu_cxr_mask = 0x0000003f,
517 .mmu_sfsr_mask = 0xffffffff,
518 .mmu_trcr_mask = 0xffffffff,
519 .nwindows = 8,
520 .features = CPU_DEFAULT_FEATURES,
521 },
522 {
523 .name = "BIT B5010",
524 .iu_version = 0x20000000,
525 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
526 .mmu_version = 0x20000000,
527 .mmu_bm = 0x00004000,
528 .mmu_ctpr_mask = 0x007ffff0,
529 .mmu_cxr_mask = 0x0000003f,
530 .mmu_sfsr_mask = 0xffffffff,
531 .mmu_trcr_mask = 0xffffffff,
532 .nwindows = 8,
533 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
534 CPU_FEATURE_FSMULD,
535 },
536 {
537 .name = "Matsushita MN10501",
538 .iu_version = 0x50000000,
539 .fpu_version = 0 << 17,
540 .mmu_version = 0x50000000,
541 .mmu_bm = 0x00004000,
542 .mmu_ctpr_mask = 0x007ffff0,
543 .mmu_cxr_mask = 0x0000003f,
544 .mmu_sfsr_mask = 0xffffffff,
545 .mmu_trcr_mask = 0xffffffff,
546 .nwindows = 8,
547 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
548 CPU_FEATURE_FSMULD,
549 },
550 {
551 .name = "Weitek W8601",
552 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
553 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
554 .mmu_version = 0x10 << 24,
555 .mmu_bm = 0x00004000,
556 .mmu_ctpr_mask = 0x007ffff0,
557 .mmu_cxr_mask = 0x0000003f,
558 .mmu_sfsr_mask = 0xffffffff,
559 .mmu_trcr_mask = 0xffffffff,
560 .nwindows = 8,
561 .features = CPU_DEFAULT_FEATURES,
562 },
563 {
564 .name = "LEON2",
565 .iu_version = 0xf2000000,
566 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
567 .mmu_version = 0xf2000000,
568 .mmu_bm = 0x00004000,
569 .mmu_ctpr_mask = 0x007ffff0,
570 .mmu_cxr_mask = 0x0000003f,
571 .mmu_sfsr_mask = 0xffffffff,
572 .mmu_trcr_mask = 0xffffffff,
573 .nwindows = 8,
574 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
575 },
576 {
577 .name = "LEON3",
578 .iu_version = 0xf3000000,
579 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
580 .mmu_version = 0xf3000000,
581 .mmu_bm = 0x00000000,
582 .mmu_ctpr_mask = 0x007ffff0,
583 .mmu_cxr_mask = 0x0000003f,
584 .mmu_sfsr_mask = 0xffffffff,
585 .mmu_trcr_mask = 0xffffffff,
586 .nwindows = 8,
587 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
588 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
589 },
590 #endif
591 };
592
593 static const char * const feature_name[] = {
594 "float",
595 "float128",
596 "swap",
597 "mul",
598 "div",
599 "flush",
600 "fsqrt",
601 "fmul",
602 "vis1",
603 "vis2",
604 "fsmuld",
605 "hypv",
606 "cmt",
607 "gl",
608 };
609
610 static void print_features(FILE *f, fprintf_function cpu_fprintf,
611 uint32_t features, const char *prefix)
612 {
613 unsigned int i;
614
615 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
616 if (feature_name[i] && (features & (1 << i))) {
617 if (prefix) {
618 (*cpu_fprintf)(f, "%s", prefix);
619 }
620 (*cpu_fprintf)(f, "%s ", feature_name[i]);
621 }
622 }
623 }
624
625 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
626 {
627 unsigned int i;
628
629 for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
630 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
631 *features |= 1 << i;
632 return;
633 }
634 }
635 fprintf(stderr, "CPU feature %s not found\n", flagname);
636 }
637
638 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
639 {
640 unsigned int i;
641 const sparc_def_t *def = NULL;
642 char *s = strdup(cpu_model);
643 char *featurestr, *name = strtok(s, ",");
644 uint32_t plus_features = 0;
645 uint32_t minus_features = 0;
646 uint64_t iu_version;
647 uint32_t fpu_version, mmu_version, nwindows;
648
649 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
650 if (strcasecmp(name, sparc_defs[i].name) == 0) {
651 def = &sparc_defs[i];
652 }
653 }
654 if (!def) {
655 goto error;
656 }
657 memcpy(cpu_def, def, sizeof(*def));
658
659 featurestr = strtok(NULL, ",");
660 while (featurestr) {
661 char *val;
662
663 if (featurestr[0] == '+') {
664 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
665 } else if (featurestr[0] == '-') {
666 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
667 } else if ((val = strchr(featurestr, '='))) {
668 *val = 0; val++;
669 if (!strcmp(featurestr, "iu_version")) {
670 char *err;
671
672 iu_version = strtoll(val, &err, 0);
673 if (!*val || *err) {
674 fprintf(stderr, "bad numerical value %s\n", val);
675 goto error;
676 }
677 cpu_def->iu_version = iu_version;
678 #ifdef DEBUG_FEATURES
679 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
680 #endif
681 } else if (!strcmp(featurestr, "fpu_version")) {
682 char *err;
683
684 fpu_version = strtol(val, &err, 0);
685 if (!*val || *err) {
686 fprintf(stderr, "bad numerical value %s\n", val);
687 goto error;
688 }
689 cpu_def->fpu_version = fpu_version;
690 #ifdef DEBUG_FEATURES
691 fprintf(stderr, "fpu_version %x\n", fpu_version);
692 #endif
693 } else if (!strcmp(featurestr, "mmu_version")) {
694 char *err;
695
696 mmu_version = strtol(val, &err, 0);
697 if (!*val || *err) {
698 fprintf(stderr, "bad numerical value %s\n", val);
699 goto error;
700 }
701 cpu_def->mmu_version = mmu_version;
702 #ifdef DEBUG_FEATURES
703 fprintf(stderr, "mmu_version %x\n", mmu_version);
704 #endif
705 } else if (!strcmp(featurestr, "nwindows")) {
706 char *err;
707
708 nwindows = strtol(val, &err, 0);
709 if (!*val || *err || nwindows > MAX_NWINDOWS ||
710 nwindows < MIN_NWINDOWS) {
711 fprintf(stderr, "bad numerical value %s\n", val);
712 goto error;
713 }
714 cpu_def->nwindows = nwindows;
715 #ifdef DEBUG_FEATURES
716 fprintf(stderr, "nwindows %d\n", nwindows);
717 #endif
718 } else {
719 fprintf(stderr, "unrecognized feature %s\n", featurestr);
720 goto error;
721 }
722 } else {
723 fprintf(stderr, "feature string `%s' not in format "
724 "(+feature|-feature|feature=xyz)\n", featurestr);
725 goto error;
726 }
727 featurestr = strtok(NULL, ",");
728 }
729 cpu_def->features |= plus_features;
730 cpu_def->features &= ~minus_features;
731 #ifdef DEBUG_FEATURES
732 print_features(stderr, fprintf, cpu_def->features, NULL);
733 #endif
734 free(s);
735 return 0;
736
737 error:
738 free(s);
739 return -1;
740 }
741
742 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
743 {
744 unsigned int i;
745
746 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
747 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
748 " FPU %08x MMU %08x NWINS %d ",
749 sparc_defs[i].name,
750 sparc_defs[i].iu_version,
751 sparc_defs[i].fpu_version,
752 sparc_defs[i].mmu_version,
753 sparc_defs[i].nwindows);
754 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
755 ~sparc_defs[i].features, "-");
756 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
757 sparc_defs[i].features, "+");
758 (*cpu_fprintf)(f, "\n");
759 }
760 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
761 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
762 (*cpu_fprintf)(f, "\n");
763 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
764 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
765 (*cpu_fprintf)(f, "\n");
766 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
767 "fpu_version mmu_version nwindows\n");
768 }
769
770 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
771 uint32_t cc)
772 {
773 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
774 cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
775 cc & PSR_CARRY ? 'C' : '-');
776 }
777
778 #ifdef TARGET_SPARC64
779 #define REGS_PER_LINE 4
780 #else
781 #define REGS_PER_LINE 8
782 #endif
783
784 void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
785 int flags)
786 {
787 int i, x;
788
789 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
790 env->npc);
791 cpu_fprintf(f, "General Registers:\n");
792
793 for (i = 0; i < 8; i++) {
794 if (i % REGS_PER_LINE == 0) {
795 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
796 }
797 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
798 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
799 cpu_fprintf(f, "\n");
800 }
801 }
802 cpu_fprintf(f, "\nCurrent Register Window:\n");
803 for (x = 0; x < 3; x++) {
804 for (i = 0; i < 8; i++) {
805 if (i % REGS_PER_LINE == 0) {
806 cpu_fprintf(f, "%%%c%d-%d: ",
807 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
808 i, i + REGS_PER_LINE - 1);
809 }
810 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
811 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
812 cpu_fprintf(f, "\n");
813 }
814 }
815 }
816 cpu_fprintf(f, "\nFloating Point Registers:\n");
817 for (i = 0; i < TARGET_DPREGS; i++) {
818 if ((i & 3) == 0) {
819 cpu_fprintf(f, "%%f%02d:", i * 2);
820 }
821 cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
822 if ((i & 3) == 3) {
823 cpu_fprintf(f, "\n");
824 }
825 }
826 #ifdef TARGET_SPARC64
827 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
828 (unsigned)cpu_get_ccr(env));
829 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
830 cpu_fprintf(f, " xcc: ");
831 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
832 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
833 env->psrpil);
834 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
835 "cleanwin: %d cwp: %d\n",
836 env->cansave, env->canrestore, env->otherwin, env->wstate,
837 env->cleanwin, env->nwindows - 1 - env->cwp);
838 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
839 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
840 #else
841 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
842 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
843 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
844 env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
845 env->wim);
846 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
847 env->fsr, env->y);
848 #endif
849 }