Introduce a default qmp session
[qemu/aliguori-queue.git] / target-sparc / helper.c
blob1f0f7d49d4ab63b55761103e1510967f1430af56
1 /*
2 * sparc 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/>.
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <signal.h>
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "qemu-common.h"
30 //#define DEBUG_MMU
31 //#define DEBUG_FEATURES
33 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
35 /* Sparc MMU emulation */
37 /* thread support */
39 static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
41 void cpu_lock(void)
43 spin_lock(&global_cpu_lock);
46 void cpu_unlock(void)
48 spin_unlock(&global_cpu_lock);
51 #if defined(CONFIG_USER_ONLY)
53 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
54 int mmu_idx, int is_softmmu)
56 if (rw & 2)
57 env1->exception_index = TT_TFAULT;
58 else
59 env1->exception_index = TT_DFAULT;
60 return 1;
63 #else
65 #ifndef TARGET_SPARC64
67 * Sparc V8 Reference MMU (SRMMU)
69 static const int access_table[8][8] = {
70 { 0, 0, 0, 0, 8, 0, 12, 12 },
71 { 0, 0, 0, 0, 8, 0, 0, 0 },
72 { 8, 8, 0, 0, 0, 8, 12, 12 },
73 { 8, 8, 0, 0, 0, 8, 0, 0 },
74 { 8, 0, 8, 0, 8, 8, 12, 12 },
75 { 8, 0, 8, 0, 8, 0, 8, 0 },
76 { 8, 8, 8, 0, 8, 8, 12, 12 },
77 { 8, 8, 8, 0, 8, 8, 8, 0 }
80 static const int perm_table[2][8] = {
82 PAGE_READ,
83 PAGE_READ | PAGE_WRITE,
84 PAGE_READ | PAGE_EXEC,
85 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
86 PAGE_EXEC,
87 PAGE_READ | PAGE_WRITE,
88 PAGE_READ | PAGE_EXEC,
89 PAGE_READ | PAGE_WRITE | PAGE_EXEC
92 PAGE_READ,
93 PAGE_READ | PAGE_WRITE,
94 PAGE_READ | PAGE_EXEC,
95 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
96 PAGE_EXEC,
97 PAGE_READ,
103 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
104 int *prot, int *access_index,
105 target_ulong address, int rw, int mmu_idx,
106 target_ulong *page_size)
108 int access_perms = 0;
109 target_phys_addr_t pde_ptr;
110 uint32_t pde;
111 int error_code = 0, is_dirty, is_user;
112 unsigned long page_offset;
114 is_user = mmu_idx == MMU_USER_IDX;
116 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
117 *page_size = TARGET_PAGE_SIZE;
118 // Boot mode: instruction fetches are taken from PROM
119 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
120 *physical = env->prom_addr | (address & 0x7ffffULL);
121 *prot = PAGE_READ | PAGE_EXEC;
122 return 0;
124 *physical = address;
125 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
126 return 0;
129 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
130 *physical = 0xffffffffffff0000ULL;
132 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
133 /* Context base + context number */
134 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
135 pde = ldl_phys(pde_ptr);
137 /* Ctx pde */
138 switch (pde & PTE_ENTRYTYPE_MASK) {
139 default:
140 case 0: /* Invalid */
141 return 1 << 2;
142 case 2: /* L0 PTE, maybe should not happen? */
143 case 3: /* Reserved */
144 return 4 << 2;
145 case 1: /* L0 PDE */
146 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
147 pde = ldl_phys(pde_ptr);
149 switch (pde & PTE_ENTRYTYPE_MASK) {
150 default:
151 case 0: /* Invalid */
152 return (1 << 8) | (1 << 2);
153 case 3: /* Reserved */
154 return (1 << 8) | (4 << 2);
155 case 1: /* L1 PDE */
156 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
157 pde = ldl_phys(pde_ptr);
159 switch (pde & PTE_ENTRYTYPE_MASK) {
160 default:
161 case 0: /* Invalid */
162 return (2 << 8) | (1 << 2);
163 case 3: /* Reserved */
164 return (2 << 8) | (4 << 2);
165 case 1: /* L2 PDE */
166 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
167 pde = ldl_phys(pde_ptr);
169 switch (pde & PTE_ENTRYTYPE_MASK) {
170 default:
171 case 0: /* Invalid */
172 return (3 << 8) | (1 << 2);
173 case 1: /* PDE, should not happen */
174 case 3: /* Reserved */
175 return (3 << 8) | (4 << 2);
176 case 2: /* L3 PTE */
177 page_offset = (address & TARGET_PAGE_MASK) &
178 (TARGET_PAGE_SIZE - 1);
180 *page_size = TARGET_PAGE_SIZE;
181 break;
182 case 2: /* L2 PTE */
183 page_offset = address & 0x3ffff;
184 *page_size = 0x40000;
186 break;
187 case 2: /* L1 PTE */
188 page_offset = address & 0xffffff;
189 *page_size = 0x1000000;
193 /* check access */
194 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
195 error_code = access_table[*access_index][access_perms];
196 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
197 return error_code;
199 /* update page modified and dirty bits */
200 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
201 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
202 pde |= PG_ACCESSED_MASK;
203 if (is_dirty)
204 pde |= PG_MODIFIED_MASK;
205 stl_phys_notdirty(pde_ptr, pde);
208 /* the page can be put in the TLB */
209 *prot = perm_table[is_user][access_perms];
210 if (!(pde & PG_MODIFIED_MASK)) {
211 /* only set write access if already dirty... otherwise wait
212 for dirty access */
213 *prot &= ~PAGE_WRITE;
216 /* Even if large ptes, we map only one 4KB page in the cache to
217 avoid filling it too fast */
218 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
219 return error_code;
222 /* Perform address translation */
223 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
224 int mmu_idx, int is_softmmu)
226 target_phys_addr_t paddr;
227 target_ulong vaddr;
228 target_ulong page_size;
229 int error_code = 0, prot, access_index;
231 error_code = get_physical_address(env, &paddr, &prot, &access_index,
232 address, rw, mmu_idx, &page_size);
233 if (error_code == 0) {
234 vaddr = address & TARGET_PAGE_MASK;
235 paddr &= TARGET_PAGE_MASK;
236 #ifdef DEBUG_MMU
237 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
238 TARGET_FMT_lx "\n", address, paddr, vaddr);
239 #endif
240 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
241 return 0;
244 if (env->mmuregs[3]) /* Fault status register */
245 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
246 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
247 env->mmuregs[4] = address; /* Fault address register */
249 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
250 // No fault mode: if a mapping is available, just override
251 // permissions. If no mapping is available, redirect accesses to
252 // neverland. Fake/overridden mappings will be flushed when
253 // switching to normal mode.
254 vaddr = address & TARGET_PAGE_MASK;
255 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
256 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
257 return 0;
258 } else {
259 if (rw & 2)
260 env->exception_index = TT_TFAULT;
261 else
262 env->exception_index = TT_DFAULT;
263 return 1;
267 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
269 target_phys_addr_t pde_ptr;
270 uint32_t pde;
272 /* Context base + context number */
273 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
274 (env->mmuregs[2] << 2);
275 pde = ldl_phys(pde_ptr);
277 switch (pde & PTE_ENTRYTYPE_MASK) {
278 default:
279 case 0: /* Invalid */
280 case 2: /* PTE, maybe should not happen? */
281 case 3: /* Reserved */
282 return 0;
283 case 1: /* L1 PDE */
284 if (mmulev == 3)
285 return pde;
286 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
287 pde = ldl_phys(pde_ptr);
289 switch (pde & PTE_ENTRYTYPE_MASK) {
290 default:
291 case 0: /* Invalid */
292 case 3: /* Reserved */
293 return 0;
294 case 2: /* L1 PTE */
295 return pde;
296 case 1: /* L2 PDE */
297 if (mmulev == 2)
298 return pde;
299 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
300 pde = ldl_phys(pde_ptr);
302 switch (pde & PTE_ENTRYTYPE_MASK) {
303 default:
304 case 0: /* Invalid */
305 case 3: /* Reserved */
306 return 0;
307 case 2: /* L2 PTE */
308 return pde;
309 case 1: /* L3 PDE */
310 if (mmulev == 1)
311 return pde;
312 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
313 pde = ldl_phys(pde_ptr);
315 switch (pde & PTE_ENTRYTYPE_MASK) {
316 default:
317 case 0: /* Invalid */
318 case 1: /* PDE, should not happen */
319 case 3: /* Reserved */
320 return 0;
321 case 2: /* L3 PTE */
322 return pde;
327 return 0;
330 #ifdef DEBUG_MMU
331 void dump_mmu(CPUState *env)
333 target_ulong va, va1, va2;
334 unsigned int n, m, o;
335 target_phys_addr_t pde_ptr, pa;
336 uint32_t pde;
338 printf("MMU dump:\n");
339 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
340 pde = ldl_phys(pde_ptr);
341 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
342 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
343 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
344 pde = mmu_probe(env, va, 2);
345 if (pde) {
346 pa = cpu_get_phys_page_debug(env, va);
347 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
348 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
349 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
350 pde = mmu_probe(env, va1, 1);
351 if (pde) {
352 pa = cpu_get_phys_page_debug(env, va1);
353 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
354 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
355 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
356 pde = mmu_probe(env, va2, 0);
357 if (pde) {
358 pa = cpu_get_phys_page_debug(env, va2);
359 printf(" VA: " TARGET_FMT_lx ", PA: "
360 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
361 va2, pa, pde);
368 printf("MMU dump ends\n");
370 #endif /* DEBUG_MMU */
372 #else /* !TARGET_SPARC64 */
374 // 41 bit physical address space
375 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
377 return x & 0x1ffffffffffULL;
381 * UltraSparc IIi I/DMMUs
384 static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
386 return (x & mask) == (y & mask);
389 // Returns true if TTE tag is valid and matches virtual address value in context
390 // requires virtual address mask value calculated from TTE entry size
391 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
392 uint64_t address, uint64_t context,
393 target_phys_addr_t *physical,
394 int is_nucleus)
396 uint64_t mask;
398 switch ((tlb->tte >> 61) & 3) {
399 default:
400 case 0x0: // 8k
401 mask = 0xffffffffffffe000ULL;
402 break;
403 case 0x1: // 64k
404 mask = 0xffffffffffff0000ULL;
405 break;
406 case 0x2: // 512k
407 mask = 0xfffffffffff80000ULL;
408 break;
409 case 0x3: // 4M
410 mask = 0xffffffffffc00000ULL;
411 break;
414 // valid, context match, virtual address match?
415 if (TTE_IS_VALID(tlb->tte) &&
416 ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
417 || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag, 0x1fff))
418 && compare_masked(address, tlb->tag, mask))
420 // decode physical address
421 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
422 return 1;
425 return 0;
428 static int get_physical_address_data(CPUState *env,
429 target_phys_addr_t *physical, int *prot,
430 target_ulong address, int rw, int is_user)
432 unsigned int i;
433 uint64_t context;
434 int is_nucleus;
436 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
437 *physical = ultrasparc_truncate_physical(address);
438 *prot = PAGE_READ | PAGE_WRITE;
439 return 0;
442 context = env->dmmu.mmu_primary_context & 0x1fff;
443 is_nucleus = env->tl > 0;
445 for (i = 0; i < 64; i++) {
446 // ctx match, vaddr match, valid?
447 if (ultrasparc_tag_match(&env->dtlb[i],
448 address, context, physical,
449 is_nucleus)) {
450 // access ok?
451 if (((env->dtlb[i].tte & 0x4) && is_user) ||
452 (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
453 uint8_t fault_type = 0;
455 if ((env->dtlb[i].tte & 0x4) && is_user) {
456 fault_type |= 1; /* privilege violation */
459 if (env->dmmu.sfsr & 1) /* Fault status register */
460 env->dmmu.sfsr = 2; /* overflow (not read before
461 another fault) */
463 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
465 env->dmmu.sfsr |= (fault_type << 7);
467 env->dmmu.sfar = address; /* Fault address register */
468 env->exception_index = TT_DFAULT;
469 #ifdef DEBUG_MMU
470 printf("DFAULT at 0x%" PRIx64 "\n", address);
471 #endif
472 return 1;
474 *prot = PAGE_READ;
475 if (env->dtlb[i].tte & 0x2)
476 *prot |= PAGE_WRITE;
477 TTE_SET_USED(env->dtlb[i].tte);
478 return 0;
481 #ifdef DEBUG_MMU
482 printf("DMISS at 0x%" PRIx64 "\n", address);
483 #endif
484 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
485 env->exception_index = TT_DMISS;
486 return 1;
489 static int get_physical_address_code(CPUState *env,
490 target_phys_addr_t *physical, int *prot,
491 target_ulong address, int is_user)
493 unsigned int i;
494 uint64_t context;
495 int is_nucleus;
497 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
498 /* IMMU disabled */
499 *physical = ultrasparc_truncate_physical(address);
500 *prot = PAGE_EXEC;
501 return 0;
504 context = env->dmmu.mmu_primary_context & 0x1fff;
505 is_nucleus = env->tl > 0;
507 for (i = 0; i < 64; i++) {
508 // ctx match, vaddr match, valid?
509 if (ultrasparc_tag_match(&env->itlb[i],
510 address, context, physical,
511 is_nucleus)) {
512 // access ok?
513 if ((env->itlb[i].tte & 0x4) && is_user) {
514 if (env->immu.sfsr) /* Fault status register */
515 env->immu.sfsr = 2; /* overflow (not read before
516 another fault) */
517 env->immu.sfsr |= (is_user << 3) | 1;
518 env->exception_index = TT_TFAULT;
519 #ifdef DEBUG_MMU
520 printf("TFAULT at 0x%" PRIx64 "\n", address);
521 #endif
522 return 1;
524 *prot = PAGE_EXEC;
525 TTE_SET_USED(env->itlb[i].tte);
526 return 0;
529 #ifdef DEBUG_MMU
530 printf("TMISS at 0x%" PRIx64 "\n", address);
531 #endif
532 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
533 env->immu.tag_access = (address & ~0x1fffULL) | context;
534 env->exception_index = TT_TMISS;
535 return 1;
538 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
539 int *prot, int *access_index,
540 target_ulong address, int rw, int mmu_idx,
541 target_ulong *page_size)
543 int is_user = mmu_idx == MMU_USER_IDX;
545 /* ??? We treat everything as a small page, then explicitly flush
546 everything when an entry is evicted. */
547 *page_size = TARGET_PAGE_SIZE;
548 if (rw == 2)
549 return get_physical_address_code(env, physical, prot, address,
550 is_user);
551 else
552 return get_physical_address_data(env, physical, prot, address, rw,
553 is_user);
556 /* Perform address translation */
557 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
558 int mmu_idx, int is_softmmu)
560 target_ulong virt_addr, vaddr;
561 target_phys_addr_t paddr;
562 target_ulong page_size;
563 int error_code = 0, prot, access_index;
565 error_code = get_physical_address(env, &paddr, &prot, &access_index,
566 address, rw, mmu_idx, &page_size);
567 if (error_code == 0) {
568 virt_addr = address & TARGET_PAGE_MASK;
569 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
570 (TARGET_PAGE_SIZE - 1));
571 #ifdef DEBUG_MMU
572 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
573 "\n", address, paddr, vaddr);
574 #endif
575 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
576 return 0;
578 // XXX
579 return 1;
582 #ifdef DEBUG_MMU
583 void dump_mmu(CPUState *env)
585 unsigned int i;
586 const char *mask;
588 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
589 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
590 if ((env->lsu & DMMU_E) == 0) {
591 printf("DMMU disabled\n");
592 } else {
593 printf("DMMU dump:\n");
594 for (i = 0; i < 64; i++) {
595 switch ((env->dtlb[i].tte >> 61) & 3) {
596 default:
597 case 0x0:
598 mask = " 8k";
599 break;
600 case 0x1:
601 mask = " 64k";
602 break;
603 case 0x2:
604 mask = "512k";
605 break;
606 case 0x3:
607 mask = " 4M";
608 break;
610 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
611 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
612 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
614 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
615 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
616 mask,
617 env->dtlb[i].tte & 0x4? "priv": "user",
618 env->dtlb[i].tte & 0x2? "RW": "RO",
619 env->dtlb[i].tte & 0x40? "locked": "unlocked",
620 env->dtlb[i].tag & (uint64_t)0x1fffULL,
621 TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
625 if ((env->lsu & IMMU_E) == 0) {
626 printf("IMMU disabled\n");
627 } else {
628 printf("IMMU dump:\n");
629 for (i = 0; i < 64; i++) {
630 switch ((env->itlb[i].tte >> 61) & 3) {
631 default:
632 case 0x0:
633 mask = " 8k";
634 break;
635 case 0x1:
636 mask = " 64k";
637 break;
638 case 0x2:
639 mask = "512k";
640 break;
641 case 0x3:
642 mask = " 4M";
643 break;
645 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
646 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
647 ", %s, %s, %s, ctx %" PRId64 " %s\n",
649 env->itlb[i].tag & (uint64_t)~0x1fffULL,
650 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
651 mask,
652 env->itlb[i].tte & 0x4? "priv": "user",
653 env->itlb[i].tte & 0x40? "locked": "unlocked",
654 env->itlb[i].tag & (uint64_t)0x1fffULL,
655 TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
660 #endif /* DEBUG_MMU */
662 #endif /* TARGET_SPARC64 */
663 #endif /* !CONFIG_USER_ONLY */
666 #if !defined(CONFIG_USER_ONLY)
667 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
669 target_phys_addr_t phys_addr;
670 target_ulong page_size;
671 int prot, access_index;
673 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
674 MMU_KERNEL_IDX, &page_size) != 0)
675 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
676 0, MMU_KERNEL_IDX, &page_size) != 0)
677 return -1;
678 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
679 return -1;
680 return phys_addr;
682 #endif
684 void cpu_reset(CPUSPARCState *env)
686 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
687 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
688 log_cpu_state(env, 0);
691 tlb_flush(env, 1);
692 env->cwp = 0;
693 #ifndef TARGET_SPARC64
694 env->wim = 1;
695 #endif
696 env->regwptr = env->regbase + (env->cwp * 16);
697 CC_OP = CC_OP_FLAGS;
698 #if defined(CONFIG_USER_ONLY)
699 #ifdef TARGET_SPARC64
700 env->cleanwin = env->nwindows - 2;
701 env->cansave = env->nwindows - 2;
702 env->pstate = PS_RMO | PS_PEF | PS_IE;
703 env->asi = 0x82; // Primary no-fault
704 #endif
705 #else
706 #if !defined(TARGET_SPARC64)
707 env->psret = 0;
708 #endif
709 env->psrs = 1;
710 env->psrps = 1;
711 #ifdef TARGET_SPARC64
712 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
713 env->hpstate = HS_PRIV;
714 env->tl = env->maxtl;
715 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
716 env->lsu = 0;
717 #else
718 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
719 env->mmuregs[0] |= env->def->mmu_bm;
720 #endif
721 env->pc = 0;
722 env->npc = env->pc + 4;
723 #endif
726 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
728 sparc_def_t def1, *def = &def1;
730 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
731 return -1;
733 env->def = qemu_mallocz(sizeof(*def));
734 memcpy(env->def, def, sizeof(*def));
735 #if defined(CONFIG_USER_ONLY)
736 if ((env->def->features & CPU_FEATURE_FLOAT))
737 env->def->features |= CPU_FEATURE_FLOAT128;
738 #endif
739 env->cpu_model_str = cpu_model;
740 env->version = def->iu_version;
741 env->fsr = def->fpu_version;
742 env->nwindows = def->nwindows;
743 #if !defined(TARGET_SPARC64)
744 env->mmuregs[0] |= def->mmu_version;
745 cpu_sparc_set_id(env, 0);
746 env->mxccregs[7] |= def->mxcc_version;
747 #else
748 env->mmu_version = def->mmu_version;
749 env->maxtl = def->maxtl;
750 env->version |= def->maxtl << 8;
751 env->version |= def->nwindows - 1;
752 #endif
753 return 0;
756 static void cpu_sparc_close(CPUSPARCState *env)
758 free(env->def);
759 free(env);
762 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
764 CPUSPARCState *env;
766 env = qemu_mallocz(sizeof(CPUSPARCState));
767 cpu_exec_init(env);
769 gen_intermediate_code_init(env);
771 if (cpu_sparc_register(env, cpu_model) < 0) {
772 cpu_sparc_close(env);
773 return NULL;
775 qemu_init_vcpu(env);
777 return env;
780 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
782 #if !defined(TARGET_SPARC64)
783 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
784 #endif
787 static const sparc_def_t sparc_defs[] = {
788 #ifdef TARGET_SPARC64
790 .name = "Fujitsu Sparc64",
791 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
792 .fpu_version = 0x00000000,
793 .mmu_version = mmu_us_12,
794 .nwindows = 4,
795 .maxtl = 4,
796 .features = CPU_DEFAULT_FEATURES,
799 .name = "Fujitsu Sparc64 III",
800 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
801 .fpu_version = 0x00000000,
802 .mmu_version = mmu_us_12,
803 .nwindows = 5,
804 .maxtl = 4,
805 .features = CPU_DEFAULT_FEATURES,
808 .name = "Fujitsu Sparc64 IV",
809 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
810 .fpu_version = 0x00000000,
811 .mmu_version = mmu_us_12,
812 .nwindows = 8,
813 .maxtl = 5,
814 .features = CPU_DEFAULT_FEATURES,
817 .name = "Fujitsu Sparc64 V",
818 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
819 .fpu_version = 0x00000000,
820 .mmu_version = mmu_us_12,
821 .nwindows = 8,
822 .maxtl = 5,
823 .features = CPU_DEFAULT_FEATURES,
826 .name = "TI UltraSparc I",
827 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
828 .fpu_version = 0x00000000,
829 .mmu_version = mmu_us_12,
830 .nwindows = 8,
831 .maxtl = 5,
832 .features = CPU_DEFAULT_FEATURES,
835 .name = "TI UltraSparc II",
836 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
837 .fpu_version = 0x00000000,
838 .mmu_version = mmu_us_12,
839 .nwindows = 8,
840 .maxtl = 5,
841 .features = CPU_DEFAULT_FEATURES,
844 .name = "TI UltraSparc IIi",
845 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
846 .fpu_version = 0x00000000,
847 .mmu_version = mmu_us_12,
848 .nwindows = 8,
849 .maxtl = 5,
850 .features = CPU_DEFAULT_FEATURES,
853 .name = "TI UltraSparc IIe",
854 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
855 .fpu_version = 0x00000000,
856 .mmu_version = mmu_us_12,
857 .nwindows = 8,
858 .maxtl = 5,
859 .features = CPU_DEFAULT_FEATURES,
862 .name = "Sun UltraSparc III",
863 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
864 .fpu_version = 0x00000000,
865 .mmu_version = mmu_us_12,
866 .nwindows = 8,
867 .maxtl = 5,
868 .features = CPU_DEFAULT_FEATURES,
871 .name = "Sun UltraSparc III Cu",
872 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
873 .fpu_version = 0x00000000,
874 .mmu_version = mmu_us_3,
875 .nwindows = 8,
876 .maxtl = 5,
877 .features = CPU_DEFAULT_FEATURES,
880 .name = "Sun UltraSparc IIIi",
881 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
882 .fpu_version = 0x00000000,
883 .mmu_version = mmu_us_12,
884 .nwindows = 8,
885 .maxtl = 5,
886 .features = CPU_DEFAULT_FEATURES,
889 .name = "Sun UltraSparc IV",
890 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
891 .fpu_version = 0x00000000,
892 .mmu_version = mmu_us_4,
893 .nwindows = 8,
894 .maxtl = 5,
895 .features = CPU_DEFAULT_FEATURES,
898 .name = "Sun UltraSparc IV+",
899 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
900 .fpu_version = 0x00000000,
901 .mmu_version = mmu_us_12,
902 .nwindows = 8,
903 .maxtl = 5,
904 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
907 .name = "Sun UltraSparc IIIi+",
908 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
909 .fpu_version = 0x00000000,
910 .mmu_version = mmu_us_3,
911 .nwindows = 8,
912 .maxtl = 5,
913 .features = CPU_DEFAULT_FEATURES,
916 .name = "Sun UltraSparc T1",
917 // defined in sparc_ifu_fdp.v and ctu.h
918 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
919 .fpu_version = 0x00000000,
920 .mmu_version = mmu_sun4v,
921 .nwindows = 8,
922 .maxtl = 6,
923 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
924 | CPU_FEATURE_GL,
927 .name = "Sun UltraSparc T2",
928 // defined in tlu_asi_ctl.v and n2_revid_cust.v
929 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
930 .fpu_version = 0x00000000,
931 .mmu_version = mmu_sun4v,
932 .nwindows = 8,
933 .maxtl = 6,
934 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
935 | CPU_FEATURE_GL,
938 .name = "NEC UltraSparc I",
939 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
940 .fpu_version = 0x00000000,
941 .mmu_version = mmu_us_12,
942 .nwindows = 8,
943 .maxtl = 5,
944 .features = CPU_DEFAULT_FEATURES,
946 #else
948 .name = "Fujitsu MB86900",
949 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
950 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
951 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
952 .mmu_bm = 0x00004000,
953 .mmu_ctpr_mask = 0x007ffff0,
954 .mmu_cxr_mask = 0x0000003f,
955 .mmu_sfsr_mask = 0xffffffff,
956 .mmu_trcr_mask = 0xffffffff,
957 .nwindows = 7,
958 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
961 .name = "Fujitsu MB86904",
962 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
963 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
964 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
965 .mmu_bm = 0x00004000,
966 .mmu_ctpr_mask = 0x00ffffc0,
967 .mmu_cxr_mask = 0x000000ff,
968 .mmu_sfsr_mask = 0x00016fff,
969 .mmu_trcr_mask = 0x00ffffff,
970 .nwindows = 8,
971 .features = CPU_DEFAULT_FEATURES,
974 .name = "Fujitsu MB86907",
975 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
976 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
977 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
978 .mmu_bm = 0x00004000,
979 .mmu_ctpr_mask = 0xffffffc0,
980 .mmu_cxr_mask = 0x000000ff,
981 .mmu_sfsr_mask = 0x00016fff,
982 .mmu_trcr_mask = 0xffffffff,
983 .nwindows = 8,
984 .features = CPU_DEFAULT_FEATURES,
987 .name = "LSI L64811",
988 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
989 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
990 .mmu_version = 0x10 << 24,
991 .mmu_bm = 0x00004000,
992 .mmu_ctpr_mask = 0x007ffff0,
993 .mmu_cxr_mask = 0x0000003f,
994 .mmu_sfsr_mask = 0xffffffff,
995 .mmu_trcr_mask = 0xffffffff,
996 .nwindows = 8,
997 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
998 CPU_FEATURE_FSMULD,
1001 .name = "Cypress CY7C601",
1002 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1003 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1004 .mmu_version = 0x10 << 24,
1005 .mmu_bm = 0x00004000,
1006 .mmu_ctpr_mask = 0x007ffff0,
1007 .mmu_cxr_mask = 0x0000003f,
1008 .mmu_sfsr_mask = 0xffffffff,
1009 .mmu_trcr_mask = 0xffffffff,
1010 .nwindows = 8,
1011 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1012 CPU_FEATURE_FSMULD,
1015 .name = "Cypress CY7C611",
1016 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1017 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1018 .mmu_version = 0x10 << 24,
1019 .mmu_bm = 0x00004000,
1020 .mmu_ctpr_mask = 0x007ffff0,
1021 .mmu_cxr_mask = 0x0000003f,
1022 .mmu_sfsr_mask = 0xffffffff,
1023 .mmu_trcr_mask = 0xffffffff,
1024 .nwindows = 8,
1025 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1026 CPU_FEATURE_FSMULD,
1029 .name = "TI MicroSparc I",
1030 .iu_version = 0x41000000,
1031 .fpu_version = 4 << 17,
1032 .mmu_version = 0x41000000,
1033 .mmu_bm = 0x00004000,
1034 .mmu_ctpr_mask = 0x007ffff0,
1035 .mmu_cxr_mask = 0x0000003f,
1036 .mmu_sfsr_mask = 0x00016fff,
1037 .mmu_trcr_mask = 0x0000003f,
1038 .nwindows = 7,
1039 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1040 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1041 CPU_FEATURE_FMUL,
1044 .name = "TI MicroSparc II",
1045 .iu_version = 0x42000000,
1046 .fpu_version = 4 << 17,
1047 .mmu_version = 0x02000000,
1048 .mmu_bm = 0x00004000,
1049 .mmu_ctpr_mask = 0x00ffffc0,
1050 .mmu_cxr_mask = 0x000000ff,
1051 .mmu_sfsr_mask = 0x00016fff,
1052 .mmu_trcr_mask = 0x00ffffff,
1053 .nwindows = 8,
1054 .features = CPU_DEFAULT_FEATURES,
1057 .name = "TI MicroSparc IIep",
1058 .iu_version = 0x42000000,
1059 .fpu_version = 4 << 17,
1060 .mmu_version = 0x04000000,
1061 .mmu_bm = 0x00004000,
1062 .mmu_ctpr_mask = 0x00ffffc0,
1063 .mmu_cxr_mask = 0x000000ff,
1064 .mmu_sfsr_mask = 0x00016bff,
1065 .mmu_trcr_mask = 0x00ffffff,
1066 .nwindows = 8,
1067 .features = CPU_DEFAULT_FEATURES,
1070 .name = "TI SuperSparc 40", // STP1020NPGA
1071 .iu_version = 0x41000000, // SuperSPARC 2.x
1072 .fpu_version = 0 << 17,
1073 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1074 .mmu_bm = 0x00002000,
1075 .mmu_ctpr_mask = 0xffffffc0,
1076 .mmu_cxr_mask = 0x0000ffff,
1077 .mmu_sfsr_mask = 0xffffffff,
1078 .mmu_trcr_mask = 0xffffffff,
1079 .nwindows = 8,
1080 .features = CPU_DEFAULT_FEATURES,
1083 .name = "TI SuperSparc 50", // STP1020PGA
1084 .iu_version = 0x40000000, // SuperSPARC 3.x
1085 .fpu_version = 0 << 17,
1086 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1087 .mmu_bm = 0x00002000,
1088 .mmu_ctpr_mask = 0xffffffc0,
1089 .mmu_cxr_mask = 0x0000ffff,
1090 .mmu_sfsr_mask = 0xffffffff,
1091 .mmu_trcr_mask = 0xffffffff,
1092 .nwindows = 8,
1093 .features = CPU_DEFAULT_FEATURES,
1096 .name = "TI SuperSparc 51",
1097 .iu_version = 0x40000000, // SuperSPARC 3.x
1098 .fpu_version = 0 << 17,
1099 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1100 .mmu_bm = 0x00002000,
1101 .mmu_ctpr_mask = 0xffffffc0,
1102 .mmu_cxr_mask = 0x0000ffff,
1103 .mmu_sfsr_mask = 0xffffffff,
1104 .mmu_trcr_mask = 0xffffffff,
1105 .mxcc_version = 0x00000104,
1106 .nwindows = 8,
1107 .features = CPU_DEFAULT_FEATURES,
1110 .name = "TI SuperSparc 60", // STP1020APGA
1111 .iu_version = 0x40000000, // SuperSPARC 3.x
1112 .fpu_version = 0 << 17,
1113 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1114 .mmu_bm = 0x00002000,
1115 .mmu_ctpr_mask = 0xffffffc0,
1116 .mmu_cxr_mask = 0x0000ffff,
1117 .mmu_sfsr_mask = 0xffffffff,
1118 .mmu_trcr_mask = 0xffffffff,
1119 .nwindows = 8,
1120 .features = CPU_DEFAULT_FEATURES,
1123 .name = "TI SuperSparc 61",
1124 .iu_version = 0x44000000, // SuperSPARC 3.x
1125 .fpu_version = 0 << 17,
1126 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1127 .mmu_bm = 0x00002000,
1128 .mmu_ctpr_mask = 0xffffffc0,
1129 .mmu_cxr_mask = 0x0000ffff,
1130 .mmu_sfsr_mask = 0xffffffff,
1131 .mmu_trcr_mask = 0xffffffff,
1132 .mxcc_version = 0x00000104,
1133 .nwindows = 8,
1134 .features = CPU_DEFAULT_FEATURES,
1137 .name = "TI SuperSparc II",
1138 .iu_version = 0x40000000, // SuperSPARC II 1.x
1139 .fpu_version = 0 << 17,
1140 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1141 .mmu_bm = 0x00002000,
1142 .mmu_ctpr_mask = 0xffffffc0,
1143 .mmu_cxr_mask = 0x0000ffff,
1144 .mmu_sfsr_mask = 0xffffffff,
1145 .mmu_trcr_mask = 0xffffffff,
1146 .mxcc_version = 0x00000104,
1147 .nwindows = 8,
1148 .features = CPU_DEFAULT_FEATURES,
1151 .name = "Ross RT625",
1152 .iu_version = 0x1e000000,
1153 .fpu_version = 1 << 17,
1154 .mmu_version = 0x1e000000,
1155 .mmu_bm = 0x00004000,
1156 .mmu_ctpr_mask = 0x007ffff0,
1157 .mmu_cxr_mask = 0x0000003f,
1158 .mmu_sfsr_mask = 0xffffffff,
1159 .mmu_trcr_mask = 0xffffffff,
1160 .nwindows = 8,
1161 .features = CPU_DEFAULT_FEATURES,
1164 .name = "Ross RT620",
1165 .iu_version = 0x1f000000,
1166 .fpu_version = 1 << 17,
1167 .mmu_version = 0x1f000000,
1168 .mmu_bm = 0x00004000,
1169 .mmu_ctpr_mask = 0x007ffff0,
1170 .mmu_cxr_mask = 0x0000003f,
1171 .mmu_sfsr_mask = 0xffffffff,
1172 .mmu_trcr_mask = 0xffffffff,
1173 .nwindows = 8,
1174 .features = CPU_DEFAULT_FEATURES,
1177 .name = "BIT B5010",
1178 .iu_version = 0x20000000,
1179 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1180 .mmu_version = 0x20000000,
1181 .mmu_bm = 0x00004000,
1182 .mmu_ctpr_mask = 0x007ffff0,
1183 .mmu_cxr_mask = 0x0000003f,
1184 .mmu_sfsr_mask = 0xffffffff,
1185 .mmu_trcr_mask = 0xffffffff,
1186 .nwindows = 8,
1187 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1188 CPU_FEATURE_FSMULD,
1191 .name = "Matsushita MN10501",
1192 .iu_version = 0x50000000,
1193 .fpu_version = 0 << 17,
1194 .mmu_version = 0x50000000,
1195 .mmu_bm = 0x00004000,
1196 .mmu_ctpr_mask = 0x007ffff0,
1197 .mmu_cxr_mask = 0x0000003f,
1198 .mmu_sfsr_mask = 0xffffffff,
1199 .mmu_trcr_mask = 0xffffffff,
1200 .nwindows = 8,
1201 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1202 CPU_FEATURE_FSMULD,
1205 .name = "Weitek W8601",
1206 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1207 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1208 .mmu_version = 0x10 << 24,
1209 .mmu_bm = 0x00004000,
1210 .mmu_ctpr_mask = 0x007ffff0,
1211 .mmu_cxr_mask = 0x0000003f,
1212 .mmu_sfsr_mask = 0xffffffff,
1213 .mmu_trcr_mask = 0xffffffff,
1214 .nwindows = 8,
1215 .features = CPU_DEFAULT_FEATURES,
1218 .name = "LEON2",
1219 .iu_version = 0xf2000000,
1220 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1221 .mmu_version = 0xf2000000,
1222 .mmu_bm = 0x00004000,
1223 .mmu_ctpr_mask = 0x007ffff0,
1224 .mmu_cxr_mask = 0x0000003f,
1225 .mmu_sfsr_mask = 0xffffffff,
1226 .mmu_trcr_mask = 0xffffffff,
1227 .nwindows = 8,
1228 .features = CPU_DEFAULT_FEATURES,
1231 .name = "LEON3",
1232 .iu_version = 0xf3000000,
1233 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1234 .mmu_version = 0xf3000000,
1235 .mmu_bm = 0x00004000,
1236 .mmu_ctpr_mask = 0x007ffff0,
1237 .mmu_cxr_mask = 0x0000003f,
1238 .mmu_sfsr_mask = 0xffffffff,
1239 .mmu_trcr_mask = 0xffffffff,
1240 .nwindows = 8,
1241 .features = CPU_DEFAULT_FEATURES,
1243 #endif
1246 static const char * const feature_name[] = {
1247 "float",
1248 "float128",
1249 "swap",
1250 "mul",
1251 "div",
1252 "flush",
1253 "fsqrt",
1254 "fmul",
1255 "vis1",
1256 "vis2",
1257 "fsmuld",
1258 "hypv",
1259 "cmt",
1260 "gl",
1263 static void print_features(FILE *f,
1264 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1265 uint32_t features, const char *prefix)
1267 unsigned int i;
1269 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1270 if (feature_name[i] && (features & (1 << i))) {
1271 if (prefix)
1272 (*cpu_fprintf)(f, "%s", prefix);
1273 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1277 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1279 unsigned int i;
1281 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1282 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1283 *features |= 1 << i;
1284 return;
1286 fprintf(stderr, "CPU feature %s not found\n", flagname);
1289 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1291 unsigned int i;
1292 const sparc_def_t *def = NULL;
1293 char *s = strdup(cpu_model);
1294 char *featurestr, *name = strtok(s, ",");
1295 uint32_t plus_features = 0;
1296 uint32_t minus_features = 0;
1297 long long iu_version;
1298 uint32_t fpu_version, mmu_version, nwindows;
1300 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1301 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1302 def = &sparc_defs[i];
1305 if (!def)
1306 goto error;
1307 memcpy(cpu_def, def, sizeof(*def));
1309 featurestr = strtok(NULL, ",");
1310 while (featurestr) {
1311 char *val;
1313 if (featurestr[0] == '+') {
1314 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1315 } else if (featurestr[0] == '-') {
1316 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1317 } else if ((val = strchr(featurestr, '='))) {
1318 *val = 0; val++;
1319 if (!strcmp(featurestr, "iu_version")) {
1320 char *err;
1322 iu_version = strtoll(val, &err, 0);
1323 if (!*val || *err) {
1324 fprintf(stderr, "bad numerical value %s\n", val);
1325 goto error;
1327 cpu_def->iu_version = iu_version;
1328 #ifdef DEBUG_FEATURES
1329 fprintf(stderr, "iu_version %llx\n", iu_version);
1330 #endif
1331 } else if (!strcmp(featurestr, "fpu_version")) {
1332 char *err;
1334 fpu_version = strtol(val, &err, 0);
1335 if (!*val || *err) {
1336 fprintf(stderr, "bad numerical value %s\n", val);
1337 goto error;
1339 cpu_def->fpu_version = fpu_version;
1340 #ifdef DEBUG_FEATURES
1341 fprintf(stderr, "fpu_version %x\n", fpu_version);
1342 #endif
1343 } else if (!strcmp(featurestr, "mmu_version")) {
1344 char *err;
1346 mmu_version = strtol(val, &err, 0);
1347 if (!*val || *err) {
1348 fprintf(stderr, "bad numerical value %s\n", val);
1349 goto error;
1351 cpu_def->mmu_version = mmu_version;
1352 #ifdef DEBUG_FEATURES
1353 fprintf(stderr, "mmu_version %x\n", mmu_version);
1354 #endif
1355 } else if (!strcmp(featurestr, "nwindows")) {
1356 char *err;
1358 nwindows = strtol(val, &err, 0);
1359 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1360 nwindows < MIN_NWINDOWS) {
1361 fprintf(stderr, "bad numerical value %s\n", val);
1362 goto error;
1364 cpu_def->nwindows = nwindows;
1365 #ifdef DEBUG_FEATURES
1366 fprintf(stderr, "nwindows %d\n", nwindows);
1367 #endif
1368 } else {
1369 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1370 goto error;
1372 } else {
1373 fprintf(stderr, "feature string `%s' not in format "
1374 "(+feature|-feature|feature=xyz)\n", featurestr);
1375 goto error;
1377 featurestr = strtok(NULL, ",");
1379 cpu_def->features |= plus_features;
1380 cpu_def->features &= ~minus_features;
1381 #ifdef DEBUG_FEATURES
1382 print_features(stderr, fprintf, cpu_def->features, NULL);
1383 #endif
1384 free(s);
1385 return 0;
1387 error:
1388 free(s);
1389 return -1;
1392 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1394 unsigned int i;
1396 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1397 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1398 sparc_defs[i].name,
1399 sparc_defs[i].iu_version,
1400 sparc_defs[i].fpu_version,
1401 sparc_defs[i].mmu_version,
1402 sparc_defs[i].nwindows);
1403 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1404 ~sparc_defs[i].features, "-");
1405 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1406 sparc_defs[i].features, "+");
1407 (*cpu_fprintf)(f, "\n");
1409 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1410 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1411 (*cpu_fprintf)(f, "\n");
1412 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1413 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1414 (*cpu_fprintf)(f, "\n");
1415 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1416 "fpu_version mmu_version nwindows\n");
1419 static void cpu_print_cc(FILE *f,
1420 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1421 uint32_t cc)
1423 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1424 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1425 cc & PSR_CARRY? 'C' : '-');
1428 #ifdef TARGET_SPARC64
1429 #define REGS_PER_LINE 4
1430 #else
1431 #define REGS_PER_LINE 8
1432 #endif
1434 void cpu_dump_state(CPUState *env, FILE *f,
1435 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1436 int flags)
1438 int i, x;
1440 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1441 env->npc);
1442 cpu_fprintf(f, "General Registers:\n");
1444 for (i = 0; i < 8; i++) {
1445 if (i % REGS_PER_LINE == 0) {
1446 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1448 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1449 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1450 cpu_fprintf(f, "\n");
1453 cpu_fprintf(f, "\nCurrent Register Window:\n");
1454 for (x = 0; x < 3; x++) {
1455 for (i = 0; i < 8; i++) {
1456 if (i % REGS_PER_LINE == 0) {
1457 cpu_fprintf(f, "%%%c%d-%d: ",
1458 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1459 i, i + REGS_PER_LINE - 1);
1461 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1462 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1463 cpu_fprintf(f, "\n");
1467 cpu_fprintf(f, "\nFloating Point Registers:\n");
1468 for (i = 0; i < TARGET_FPREGS; i++) {
1469 if ((i & 3) == 0)
1470 cpu_fprintf(f, "%%f%02d:", i);
1471 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1472 if ((i & 3) == 3)
1473 cpu_fprintf(f, "\n");
1475 #ifdef TARGET_SPARC64
1476 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1477 GET_CCR(env));
1478 cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << PSR_CARRY_SHIFT);
1479 cpu_fprintf(f, " xcc: ");
1480 cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << (PSR_CARRY_SHIFT - 4));
1481 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1482 env->psrpil);
1483 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1484 "cleanwin: %d cwp: %d\n",
1485 env->cansave, env->canrestore, env->otherwin, env->wstate,
1486 env->cleanwin, env->nwindows - 1 - env->cwp);
1487 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1488 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1489 #else
1490 cpu_fprintf(f, "psr: %08x (icc: ", GET_PSR(env));
1491 cpu_print_cc(f, cpu_fprintf, GET_PSR(env));
1492 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1493 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1494 env->wim);
1495 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1496 env->fsr, env->y);
1497 #endif