vnc: only use a single zlib stream
[qemu.git] / target-sparc / helper.c
blob96a22f3475d6c890bacc81820096e6f30b773529
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 #ifdef DEBUG_MMU
34 #define DPRINTF_MMU(fmt, ...) \
35 do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
36 #else
37 #define DPRINTF_MMU(fmt, ...) do {} while (0)
38 #endif
40 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
42 /* Sparc MMU emulation */
44 /* thread support */
46 static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
48 void cpu_lock(void)
50 spin_lock(&global_cpu_lock);
53 void cpu_unlock(void)
55 spin_unlock(&global_cpu_lock);
58 #if defined(CONFIG_USER_ONLY)
60 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
61 int mmu_idx, int is_softmmu)
63 if (rw & 2)
64 env1->exception_index = TT_TFAULT;
65 else
66 env1->exception_index = TT_DFAULT;
67 return 1;
70 #else
72 #ifndef TARGET_SPARC64
74 * Sparc V8 Reference MMU (SRMMU)
76 static const int access_table[8][8] = {
77 { 0, 0, 0, 0, 8, 0, 12, 12 },
78 { 0, 0, 0, 0, 8, 0, 0, 0 },
79 { 8, 8, 0, 0, 0, 8, 12, 12 },
80 { 8, 8, 0, 0, 0, 8, 0, 0 },
81 { 8, 0, 8, 0, 8, 8, 12, 12 },
82 { 8, 0, 8, 0, 8, 0, 8, 0 },
83 { 8, 8, 8, 0, 8, 8, 12, 12 },
84 { 8, 8, 8, 0, 8, 8, 8, 0 }
87 static const int perm_table[2][8] = {
89 PAGE_READ,
90 PAGE_READ | PAGE_WRITE,
91 PAGE_READ | PAGE_EXEC,
92 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
93 PAGE_EXEC,
94 PAGE_READ | PAGE_WRITE,
95 PAGE_READ | PAGE_EXEC,
96 PAGE_READ | PAGE_WRITE | PAGE_EXEC
99 PAGE_READ,
100 PAGE_READ | PAGE_WRITE,
101 PAGE_READ | PAGE_EXEC,
102 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
103 PAGE_EXEC,
104 PAGE_READ,
110 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
111 int *prot, int *access_index,
112 target_ulong address, int rw, int mmu_idx,
113 target_ulong *page_size)
115 int access_perms = 0;
116 target_phys_addr_t pde_ptr;
117 uint32_t pde;
118 int error_code = 0, is_dirty, is_user;
119 unsigned long page_offset;
121 is_user = mmu_idx == MMU_USER_IDX;
123 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
124 *page_size = TARGET_PAGE_SIZE;
125 // Boot mode: instruction fetches are taken from PROM
126 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
127 *physical = env->prom_addr | (address & 0x7ffffULL);
128 *prot = PAGE_READ | PAGE_EXEC;
129 return 0;
131 *physical = address;
132 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
133 return 0;
136 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
137 *physical = 0xffffffffffff0000ULL;
139 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
140 /* Context base + context number */
141 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
142 pde = ldl_phys(pde_ptr);
144 /* Ctx pde */
145 switch (pde & PTE_ENTRYTYPE_MASK) {
146 default:
147 case 0: /* Invalid */
148 return 1 << 2;
149 case 2: /* L0 PTE, maybe should not happen? */
150 case 3: /* Reserved */
151 return 4 << 2;
152 case 1: /* L0 PDE */
153 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
154 pde = ldl_phys(pde_ptr);
156 switch (pde & PTE_ENTRYTYPE_MASK) {
157 default:
158 case 0: /* Invalid */
159 return (1 << 8) | (1 << 2);
160 case 3: /* Reserved */
161 return (1 << 8) | (4 << 2);
162 case 1: /* L1 PDE */
163 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
164 pde = ldl_phys(pde_ptr);
166 switch (pde & PTE_ENTRYTYPE_MASK) {
167 default:
168 case 0: /* Invalid */
169 return (2 << 8) | (1 << 2);
170 case 3: /* Reserved */
171 return (2 << 8) | (4 << 2);
172 case 1: /* L2 PDE */
173 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
174 pde = ldl_phys(pde_ptr);
176 switch (pde & PTE_ENTRYTYPE_MASK) {
177 default:
178 case 0: /* Invalid */
179 return (3 << 8) | (1 << 2);
180 case 1: /* PDE, should not happen */
181 case 3: /* Reserved */
182 return (3 << 8) | (4 << 2);
183 case 2: /* L3 PTE */
184 page_offset = (address & TARGET_PAGE_MASK) &
185 (TARGET_PAGE_SIZE - 1);
187 *page_size = TARGET_PAGE_SIZE;
188 break;
189 case 2: /* L2 PTE */
190 page_offset = address & 0x3ffff;
191 *page_size = 0x40000;
193 break;
194 case 2: /* L1 PTE */
195 page_offset = address & 0xffffff;
196 *page_size = 0x1000000;
200 /* check access */
201 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
202 error_code = access_table[*access_index][access_perms];
203 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
204 return error_code;
206 /* update page modified and dirty bits */
207 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
208 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
209 pde |= PG_ACCESSED_MASK;
210 if (is_dirty)
211 pde |= PG_MODIFIED_MASK;
212 stl_phys_notdirty(pde_ptr, pde);
215 /* the page can be put in the TLB */
216 *prot = perm_table[is_user][access_perms];
217 if (!(pde & PG_MODIFIED_MASK)) {
218 /* only set write access if already dirty... otherwise wait
219 for dirty access */
220 *prot &= ~PAGE_WRITE;
223 /* Even if large ptes, we map only one 4KB page in the cache to
224 avoid filling it too fast */
225 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
226 return error_code;
229 /* Perform address translation */
230 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
231 int mmu_idx, int is_softmmu)
233 target_phys_addr_t paddr;
234 target_ulong vaddr;
235 target_ulong page_size;
236 int error_code = 0, prot, access_index;
238 error_code = get_physical_address(env, &paddr, &prot, &access_index,
239 address, rw, mmu_idx, &page_size);
240 if (error_code == 0) {
241 vaddr = address & TARGET_PAGE_MASK;
242 paddr &= TARGET_PAGE_MASK;
243 #ifdef DEBUG_MMU
244 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
245 TARGET_FMT_lx "\n", address, paddr, vaddr);
246 #endif
247 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
248 return 0;
251 if (env->mmuregs[3]) /* Fault status register */
252 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
253 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
254 env->mmuregs[4] = address; /* Fault address register */
256 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
257 // No fault mode: if a mapping is available, just override
258 // permissions. If no mapping is available, redirect accesses to
259 // neverland. Fake/overridden mappings will be flushed when
260 // switching to normal mode.
261 vaddr = address & TARGET_PAGE_MASK;
262 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
263 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
264 return 0;
265 } else {
266 if (rw & 2)
267 env->exception_index = TT_TFAULT;
268 else
269 env->exception_index = TT_DFAULT;
270 return 1;
274 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
276 target_phys_addr_t pde_ptr;
277 uint32_t pde;
279 /* Context base + context number */
280 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
281 (env->mmuregs[2] << 2);
282 pde = ldl_phys(pde_ptr);
284 switch (pde & PTE_ENTRYTYPE_MASK) {
285 default:
286 case 0: /* Invalid */
287 case 2: /* PTE, maybe should not happen? */
288 case 3: /* Reserved */
289 return 0;
290 case 1: /* L1 PDE */
291 if (mmulev == 3)
292 return pde;
293 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
294 pde = ldl_phys(pde_ptr);
296 switch (pde & PTE_ENTRYTYPE_MASK) {
297 default:
298 case 0: /* Invalid */
299 case 3: /* Reserved */
300 return 0;
301 case 2: /* L1 PTE */
302 return pde;
303 case 1: /* L2 PDE */
304 if (mmulev == 2)
305 return pde;
306 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
307 pde = ldl_phys(pde_ptr);
309 switch (pde & PTE_ENTRYTYPE_MASK) {
310 default:
311 case 0: /* Invalid */
312 case 3: /* Reserved */
313 return 0;
314 case 2: /* L2 PTE */
315 return pde;
316 case 1: /* L3 PDE */
317 if (mmulev == 1)
318 return pde;
319 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
320 pde = ldl_phys(pde_ptr);
322 switch (pde & PTE_ENTRYTYPE_MASK) {
323 default:
324 case 0: /* Invalid */
325 case 1: /* PDE, should not happen */
326 case 3: /* Reserved */
327 return 0;
328 case 2: /* L3 PTE */
329 return pde;
334 return 0;
337 #ifdef DEBUG_MMU
338 void dump_mmu(CPUState *env)
340 target_ulong va, va1, va2;
341 unsigned int n, m, o;
342 target_phys_addr_t pde_ptr, pa;
343 uint32_t pde;
345 printf("MMU dump:\n");
346 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
347 pde = ldl_phys(pde_ptr);
348 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
349 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
350 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
351 pde = mmu_probe(env, va, 2);
352 if (pde) {
353 pa = cpu_get_phys_page_debug(env, va);
354 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
355 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
356 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
357 pde = mmu_probe(env, va1, 1);
358 if (pde) {
359 pa = cpu_get_phys_page_debug(env, va1);
360 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
361 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
362 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
363 pde = mmu_probe(env, va2, 0);
364 if (pde) {
365 pa = cpu_get_phys_page_debug(env, va2);
366 printf(" VA: " TARGET_FMT_lx ", PA: "
367 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
368 va2, pa, pde);
375 printf("MMU dump ends\n");
377 #endif /* DEBUG_MMU */
379 #else /* !TARGET_SPARC64 */
381 // 41 bit physical address space
382 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
384 return x & 0x1ffffffffffULL;
388 * UltraSparc IIi I/DMMUs
391 // Returns true if TTE tag is valid and matches virtual address value in context
392 // requires virtual address mask value calculated from TTE entry size
393 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
394 uint64_t address, uint64_t context,
395 target_phys_addr_t *physical)
397 uint64_t mask;
399 switch ((tlb->tte >> 61) & 3) {
400 default:
401 case 0x0: // 8k
402 mask = 0xffffffffffffe000ULL;
403 break;
404 case 0x1: // 64k
405 mask = 0xffffffffffff0000ULL;
406 break;
407 case 0x2: // 512k
408 mask = 0xfffffffffff80000ULL;
409 break;
410 case 0x3: // 4M
411 mask = 0xffffffffffc00000ULL;
412 break;
415 // valid, context match, virtual address match?
416 if (TTE_IS_VALID(tlb->tte) &&
417 (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
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 mmu_idx)
432 unsigned int i;
433 uint64_t context;
435 int is_user = (mmu_idx == MMU_USER_IDX ||
436 mmu_idx == MMU_USER_SECONDARY_IDX);
438 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
439 *physical = ultrasparc_truncate_physical(address);
440 *prot = PAGE_READ | PAGE_WRITE;
441 return 0;
444 switch(mmu_idx) {
445 case MMU_USER_IDX:
446 case MMU_KERNEL_IDX:
447 context = env->dmmu.mmu_primary_context & 0x1fff;
448 break;
449 case MMU_USER_SECONDARY_IDX:
450 case MMU_KERNEL_SECONDARY_IDX:
451 context = env->dmmu.mmu_secondary_context & 0x1fff;
452 break;
453 case MMU_NUCLEUS_IDX:
454 default:
455 context = 0;
456 break;
459 for (i = 0; i < 64; i++) {
460 // ctx match, vaddr match, valid?
461 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
463 uint8_t fault_type = 0;
465 // access ok?
466 if ((env->dtlb[i].tte & 0x4) && is_user) {
467 fault_type |= 1; /* privilege violation */
468 env->exception_index = TT_DFAULT;
470 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
471 " mmu_idx=%d tl=%d\n",
472 address, context, mmu_idx, env->tl);
473 } else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) {
474 env->exception_index = TT_DPROT;
476 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
477 " mmu_idx=%d tl=%d\n",
478 address, context, mmu_idx, env->tl);
479 } else {
480 *prot = PAGE_READ;
481 if (env->dtlb[i].tte & 0x2)
482 *prot |= PAGE_WRITE;
484 TTE_SET_USED(env->dtlb[i].tte);
486 return 0;
489 if (env->dmmu.sfsr & 1) /* Fault status register */
490 env->dmmu.sfsr = 2; /* overflow (not read before
491 another fault) */
493 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
495 env->dmmu.sfsr |= (fault_type << 7);
497 env->dmmu.sfar = address; /* Fault address register */
498 return 1;
502 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
503 address, context);
505 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
506 env->exception_index = TT_DMISS;
507 return 1;
510 static int get_physical_address_code(CPUState *env,
511 target_phys_addr_t *physical, int *prot,
512 target_ulong address, int mmu_idx)
514 unsigned int i;
515 uint64_t context;
517 int is_user = (mmu_idx == MMU_USER_IDX ||
518 mmu_idx == MMU_USER_SECONDARY_IDX);
520 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
521 /* IMMU disabled */
522 *physical = ultrasparc_truncate_physical(address);
523 *prot = PAGE_EXEC;
524 return 0;
527 if (env->tl == 0) {
528 /* PRIMARY context */
529 context = env->dmmu.mmu_primary_context & 0x1fff;
530 } else {
531 /* NUCLEUS context */
532 context = 0;
535 for (i = 0; i < 64; i++) {
536 // ctx match, vaddr match, valid?
537 if (ultrasparc_tag_match(&env->itlb[i],
538 address, context, physical)) {
539 // access ok?
540 if ((env->itlb[i].tte & 0x4) && is_user) {
541 if (env->immu.sfsr) /* Fault status register */
542 env->immu.sfsr = 2; /* overflow (not read before
543 another fault) */
544 env->immu.sfsr |= (is_user << 3) | 1;
545 env->exception_index = TT_TFAULT;
547 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
548 address, context);
550 return 1;
552 *prot = PAGE_EXEC;
553 TTE_SET_USED(env->itlb[i].tte);
554 return 0;
558 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
559 address, context);
561 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
562 env->immu.tag_access = (address & ~0x1fffULL) | context;
563 env->exception_index = TT_TMISS;
564 return 1;
567 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
568 int *prot, int *access_index,
569 target_ulong address, int rw, int mmu_idx,
570 target_ulong *page_size)
572 /* ??? We treat everything as a small page, then explicitly flush
573 everything when an entry is evicted. */
574 *page_size = TARGET_PAGE_SIZE;
576 #if defined (DEBUG_MMU)
577 /* safety net to catch wrong softmmu index use from dynamic code */
578 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
579 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
580 " primary context=%" PRIx64
581 " secondary context=%" PRIx64
582 " address=%" PRIx64
583 "\n",
584 (rw == 2 ? "CODE" : "DATA"),
585 env->tl, mmu_idx,
586 env->dmmu.mmu_primary_context,
587 env->dmmu.mmu_secondary_context,
588 address);
590 #endif
592 if (rw == 2)
593 return get_physical_address_code(env, physical, prot, address,
594 mmu_idx);
595 else
596 return get_physical_address_data(env, physical, prot, address, rw,
597 mmu_idx);
600 /* Perform address translation */
601 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
602 int mmu_idx, int is_softmmu)
604 target_ulong virt_addr, vaddr;
605 target_phys_addr_t paddr;
606 target_ulong page_size;
607 int error_code = 0, prot, access_index;
609 error_code = get_physical_address(env, &paddr, &prot, &access_index,
610 address, rw, mmu_idx, &page_size);
611 if (error_code == 0) {
612 virt_addr = address & TARGET_PAGE_MASK;
613 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
614 (TARGET_PAGE_SIZE - 1));
616 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
617 " vaddr %" PRIx64
618 " mmu_idx=%d"
619 " tl=%d"
620 " primary context=%" PRIx64
621 " secondary context=%" PRIx64
622 "\n",
623 address, paddr, vaddr, mmu_idx, env->tl,
624 env->dmmu.mmu_primary_context,
625 env->dmmu.mmu_secondary_context);
627 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
628 return 0;
630 // XXX
631 return 1;
634 #ifdef DEBUG_MMU
635 void dump_mmu(CPUState *env)
637 unsigned int i;
638 const char *mask;
640 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
641 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
642 if ((env->lsu & DMMU_E) == 0) {
643 printf("DMMU disabled\n");
644 } else {
645 printf("DMMU dump:\n");
646 for (i = 0; i < 64; i++) {
647 switch ((env->dtlb[i].tte >> 61) & 3) {
648 default:
649 case 0x0:
650 mask = " 8k";
651 break;
652 case 0x1:
653 mask = " 64k";
654 break;
655 case 0x2:
656 mask = "512k";
657 break;
658 case 0x3:
659 mask = " 4M";
660 break;
662 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
663 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
664 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
666 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
667 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
668 mask,
669 env->dtlb[i].tte & 0x4? "priv": "user",
670 env->dtlb[i].tte & 0x2? "RW": "RO",
671 env->dtlb[i].tte & 0x40? "locked": "unlocked",
672 env->dtlb[i].tag & (uint64_t)0x1fffULL,
673 TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local");
677 if ((env->lsu & IMMU_E) == 0) {
678 printf("IMMU disabled\n");
679 } else {
680 printf("IMMU dump:\n");
681 for (i = 0; i < 64; i++) {
682 switch ((env->itlb[i].tte >> 61) & 3) {
683 default:
684 case 0x0:
685 mask = " 8k";
686 break;
687 case 0x1:
688 mask = " 64k";
689 break;
690 case 0x2:
691 mask = "512k";
692 break;
693 case 0x3:
694 mask = " 4M";
695 break;
697 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
698 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
699 ", %s, %s, %s, ctx %" PRId64 " %s\n",
701 env->itlb[i].tag & (uint64_t)~0x1fffULL,
702 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
703 mask,
704 env->itlb[i].tte & 0x4? "priv": "user",
705 env->itlb[i].tte & 0x40? "locked": "unlocked",
706 env->itlb[i].tag & (uint64_t)0x1fffULL,
707 TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local");
712 #endif /* DEBUG_MMU */
714 #endif /* TARGET_SPARC64 */
715 #endif /* !CONFIG_USER_ONLY */
718 #if !defined(CONFIG_USER_ONLY)
719 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
720 int mmu_idx)
722 target_phys_addr_t phys_addr;
723 target_ulong page_size;
724 int prot, access_index;
726 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
727 mmu_idx, &page_size) != 0)
728 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
729 0, mmu_idx, &page_size) != 0)
730 return -1;
731 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
732 return -1;
733 return phys_addr;
736 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
738 return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
740 #endif
742 void cpu_reset(CPUSPARCState *env)
744 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
745 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
746 log_cpu_state(env, 0);
749 tlb_flush(env, 1);
750 env->cwp = 0;
751 #ifndef TARGET_SPARC64
752 env->wim = 1;
753 #endif
754 env->regwptr = env->regbase + (env->cwp * 16);
755 CC_OP = CC_OP_FLAGS;
756 #if defined(CONFIG_USER_ONLY)
757 #ifdef TARGET_SPARC64
758 env->cleanwin = env->nwindows - 2;
759 env->cansave = env->nwindows - 2;
760 env->pstate = PS_RMO | PS_PEF | PS_IE;
761 env->asi = 0x82; // Primary no-fault
762 #endif
763 #else
764 #if !defined(TARGET_SPARC64)
765 env->psret = 0;
766 env->psrs = 1;
767 env->psrps = 1;
768 #endif
769 #ifdef TARGET_SPARC64
770 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
771 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
772 env->tl = env->maxtl;
773 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
774 env->lsu = 0;
775 #else
776 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
777 env->mmuregs[0] |= env->def->mmu_bm;
778 #endif
779 env->pc = 0;
780 env->npc = env->pc + 4;
781 #endif
784 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
786 sparc_def_t def1, *def = &def1;
788 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
789 return -1;
791 env->def = qemu_mallocz(sizeof(*def));
792 memcpy(env->def, def, sizeof(*def));
793 #if defined(CONFIG_USER_ONLY)
794 if ((env->def->features & CPU_FEATURE_FLOAT))
795 env->def->features |= CPU_FEATURE_FLOAT128;
796 #endif
797 env->cpu_model_str = cpu_model;
798 env->version = def->iu_version;
799 env->fsr = def->fpu_version;
800 env->nwindows = def->nwindows;
801 #if !defined(TARGET_SPARC64)
802 env->mmuregs[0] |= def->mmu_version;
803 cpu_sparc_set_id(env, 0);
804 env->mxccregs[7] |= def->mxcc_version;
805 #else
806 env->mmu_version = def->mmu_version;
807 env->maxtl = def->maxtl;
808 env->version |= def->maxtl << 8;
809 env->version |= def->nwindows - 1;
810 #endif
811 return 0;
814 static void cpu_sparc_close(CPUSPARCState *env)
816 free(env->def);
817 free(env);
820 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
822 CPUSPARCState *env;
824 env = qemu_mallocz(sizeof(CPUSPARCState));
825 cpu_exec_init(env);
827 gen_intermediate_code_init(env);
829 if (cpu_sparc_register(env, cpu_model) < 0) {
830 cpu_sparc_close(env);
831 return NULL;
833 qemu_init_vcpu(env);
835 return env;
838 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
840 #if !defined(TARGET_SPARC64)
841 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
842 #endif
845 static const sparc_def_t sparc_defs[] = {
846 #ifdef TARGET_SPARC64
848 .name = "Fujitsu Sparc64",
849 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
850 .fpu_version = 0x00000000,
851 .mmu_version = mmu_us_12,
852 .nwindows = 4,
853 .maxtl = 4,
854 .features = CPU_DEFAULT_FEATURES,
857 .name = "Fujitsu Sparc64 III",
858 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
859 .fpu_version = 0x00000000,
860 .mmu_version = mmu_us_12,
861 .nwindows = 5,
862 .maxtl = 4,
863 .features = CPU_DEFAULT_FEATURES,
866 .name = "Fujitsu Sparc64 IV",
867 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
868 .fpu_version = 0x00000000,
869 .mmu_version = mmu_us_12,
870 .nwindows = 8,
871 .maxtl = 5,
872 .features = CPU_DEFAULT_FEATURES,
875 .name = "Fujitsu Sparc64 V",
876 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
877 .fpu_version = 0x00000000,
878 .mmu_version = mmu_us_12,
879 .nwindows = 8,
880 .maxtl = 5,
881 .features = CPU_DEFAULT_FEATURES,
884 .name = "TI UltraSparc I",
885 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
886 .fpu_version = 0x00000000,
887 .mmu_version = mmu_us_12,
888 .nwindows = 8,
889 .maxtl = 5,
890 .features = CPU_DEFAULT_FEATURES,
893 .name = "TI UltraSparc II",
894 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
895 .fpu_version = 0x00000000,
896 .mmu_version = mmu_us_12,
897 .nwindows = 8,
898 .maxtl = 5,
899 .features = CPU_DEFAULT_FEATURES,
902 .name = "TI UltraSparc IIi",
903 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
904 .fpu_version = 0x00000000,
905 .mmu_version = mmu_us_12,
906 .nwindows = 8,
907 .maxtl = 5,
908 .features = CPU_DEFAULT_FEATURES,
911 .name = "TI UltraSparc IIe",
912 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
913 .fpu_version = 0x00000000,
914 .mmu_version = mmu_us_12,
915 .nwindows = 8,
916 .maxtl = 5,
917 .features = CPU_DEFAULT_FEATURES,
920 .name = "Sun UltraSparc III",
921 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
922 .fpu_version = 0x00000000,
923 .mmu_version = mmu_us_12,
924 .nwindows = 8,
925 .maxtl = 5,
926 .features = CPU_DEFAULT_FEATURES,
929 .name = "Sun UltraSparc III Cu",
930 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
931 .fpu_version = 0x00000000,
932 .mmu_version = mmu_us_3,
933 .nwindows = 8,
934 .maxtl = 5,
935 .features = CPU_DEFAULT_FEATURES,
938 .name = "Sun UltraSparc IIIi",
939 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
940 .fpu_version = 0x00000000,
941 .mmu_version = mmu_us_12,
942 .nwindows = 8,
943 .maxtl = 5,
944 .features = CPU_DEFAULT_FEATURES,
947 .name = "Sun UltraSparc IV",
948 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
949 .fpu_version = 0x00000000,
950 .mmu_version = mmu_us_4,
951 .nwindows = 8,
952 .maxtl = 5,
953 .features = CPU_DEFAULT_FEATURES,
956 .name = "Sun UltraSparc IV+",
957 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
958 .fpu_version = 0x00000000,
959 .mmu_version = mmu_us_12,
960 .nwindows = 8,
961 .maxtl = 5,
962 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
965 .name = "Sun UltraSparc IIIi+",
966 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
967 .fpu_version = 0x00000000,
968 .mmu_version = mmu_us_3,
969 .nwindows = 8,
970 .maxtl = 5,
971 .features = CPU_DEFAULT_FEATURES,
974 .name = "Sun UltraSparc T1",
975 // defined in sparc_ifu_fdp.v and ctu.h
976 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
977 .fpu_version = 0x00000000,
978 .mmu_version = mmu_sun4v,
979 .nwindows = 8,
980 .maxtl = 6,
981 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
982 | CPU_FEATURE_GL,
985 .name = "Sun UltraSparc T2",
986 // defined in tlu_asi_ctl.v and n2_revid_cust.v
987 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
988 .fpu_version = 0x00000000,
989 .mmu_version = mmu_sun4v,
990 .nwindows = 8,
991 .maxtl = 6,
992 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
993 | CPU_FEATURE_GL,
996 .name = "NEC UltraSparc I",
997 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
998 .fpu_version = 0x00000000,
999 .mmu_version = mmu_us_12,
1000 .nwindows = 8,
1001 .maxtl = 5,
1002 .features = CPU_DEFAULT_FEATURES,
1004 #else
1006 .name = "Fujitsu MB86900",
1007 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1008 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1009 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1010 .mmu_bm = 0x00004000,
1011 .mmu_ctpr_mask = 0x007ffff0,
1012 .mmu_cxr_mask = 0x0000003f,
1013 .mmu_sfsr_mask = 0xffffffff,
1014 .mmu_trcr_mask = 0xffffffff,
1015 .nwindows = 7,
1016 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1019 .name = "Fujitsu MB86904",
1020 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1021 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1022 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1023 .mmu_bm = 0x00004000,
1024 .mmu_ctpr_mask = 0x00ffffc0,
1025 .mmu_cxr_mask = 0x000000ff,
1026 .mmu_sfsr_mask = 0x00016fff,
1027 .mmu_trcr_mask = 0x00ffffff,
1028 .nwindows = 8,
1029 .features = CPU_DEFAULT_FEATURES,
1032 .name = "Fujitsu MB86907",
1033 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1034 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1035 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1036 .mmu_bm = 0x00004000,
1037 .mmu_ctpr_mask = 0xffffffc0,
1038 .mmu_cxr_mask = 0x000000ff,
1039 .mmu_sfsr_mask = 0x00016fff,
1040 .mmu_trcr_mask = 0xffffffff,
1041 .nwindows = 8,
1042 .features = CPU_DEFAULT_FEATURES,
1045 .name = "LSI L64811",
1046 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1047 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1048 .mmu_version = 0x10 << 24,
1049 .mmu_bm = 0x00004000,
1050 .mmu_ctpr_mask = 0x007ffff0,
1051 .mmu_cxr_mask = 0x0000003f,
1052 .mmu_sfsr_mask = 0xffffffff,
1053 .mmu_trcr_mask = 0xffffffff,
1054 .nwindows = 8,
1055 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1056 CPU_FEATURE_FSMULD,
1059 .name = "Cypress CY7C601",
1060 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1061 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1062 .mmu_version = 0x10 << 24,
1063 .mmu_bm = 0x00004000,
1064 .mmu_ctpr_mask = 0x007ffff0,
1065 .mmu_cxr_mask = 0x0000003f,
1066 .mmu_sfsr_mask = 0xffffffff,
1067 .mmu_trcr_mask = 0xffffffff,
1068 .nwindows = 8,
1069 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1070 CPU_FEATURE_FSMULD,
1073 .name = "Cypress CY7C611",
1074 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1075 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1076 .mmu_version = 0x10 << 24,
1077 .mmu_bm = 0x00004000,
1078 .mmu_ctpr_mask = 0x007ffff0,
1079 .mmu_cxr_mask = 0x0000003f,
1080 .mmu_sfsr_mask = 0xffffffff,
1081 .mmu_trcr_mask = 0xffffffff,
1082 .nwindows = 8,
1083 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1084 CPU_FEATURE_FSMULD,
1087 .name = "TI MicroSparc I",
1088 .iu_version = 0x41000000,
1089 .fpu_version = 4 << 17,
1090 .mmu_version = 0x41000000,
1091 .mmu_bm = 0x00004000,
1092 .mmu_ctpr_mask = 0x007ffff0,
1093 .mmu_cxr_mask = 0x0000003f,
1094 .mmu_sfsr_mask = 0x00016fff,
1095 .mmu_trcr_mask = 0x0000003f,
1096 .nwindows = 7,
1097 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1098 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1099 CPU_FEATURE_FMUL,
1102 .name = "TI MicroSparc II",
1103 .iu_version = 0x42000000,
1104 .fpu_version = 4 << 17,
1105 .mmu_version = 0x02000000,
1106 .mmu_bm = 0x00004000,
1107 .mmu_ctpr_mask = 0x00ffffc0,
1108 .mmu_cxr_mask = 0x000000ff,
1109 .mmu_sfsr_mask = 0x00016fff,
1110 .mmu_trcr_mask = 0x00ffffff,
1111 .nwindows = 8,
1112 .features = CPU_DEFAULT_FEATURES,
1115 .name = "TI MicroSparc IIep",
1116 .iu_version = 0x42000000,
1117 .fpu_version = 4 << 17,
1118 .mmu_version = 0x04000000,
1119 .mmu_bm = 0x00004000,
1120 .mmu_ctpr_mask = 0x00ffffc0,
1121 .mmu_cxr_mask = 0x000000ff,
1122 .mmu_sfsr_mask = 0x00016bff,
1123 .mmu_trcr_mask = 0x00ffffff,
1124 .nwindows = 8,
1125 .features = CPU_DEFAULT_FEATURES,
1128 .name = "TI SuperSparc 40", // STP1020NPGA
1129 .iu_version = 0x41000000, // SuperSPARC 2.x
1130 .fpu_version = 0 << 17,
1131 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1132 .mmu_bm = 0x00002000,
1133 .mmu_ctpr_mask = 0xffffffc0,
1134 .mmu_cxr_mask = 0x0000ffff,
1135 .mmu_sfsr_mask = 0xffffffff,
1136 .mmu_trcr_mask = 0xffffffff,
1137 .nwindows = 8,
1138 .features = CPU_DEFAULT_FEATURES,
1141 .name = "TI SuperSparc 50", // STP1020PGA
1142 .iu_version = 0x40000000, // SuperSPARC 3.x
1143 .fpu_version = 0 << 17,
1144 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1145 .mmu_bm = 0x00002000,
1146 .mmu_ctpr_mask = 0xffffffc0,
1147 .mmu_cxr_mask = 0x0000ffff,
1148 .mmu_sfsr_mask = 0xffffffff,
1149 .mmu_trcr_mask = 0xffffffff,
1150 .nwindows = 8,
1151 .features = CPU_DEFAULT_FEATURES,
1154 .name = "TI SuperSparc 51",
1155 .iu_version = 0x40000000, // SuperSPARC 3.x
1156 .fpu_version = 0 << 17,
1157 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1158 .mmu_bm = 0x00002000,
1159 .mmu_ctpr_mask = 0xffffffc0,
1160 .mmu_cxr_mask = 0x0000ffff,
1161 .mmu_sfsr_mask = 0xffffffff,
1162 .mmu_trcr_mask = 0xffffffff,
1163 .mxcc_version = 0x00000104,
1164 .nwindows = 8,
1165 .features = CPU_DEFAULT_FEATURES,
1168 .name = "TI SuperSparc 60", // STP1020APGA
1169 .iu_version = 0x40000000, // SuperSPARC 3.x
1170 .fpu_version = 0 << 17,
1171 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1172 .mmu_bm = 0x00002000,
1173 .mmu_ctpr_mask = 0xffffffc0,
1174 .mmu_cxr_mask = 0x0000ffff,
1175 .mmu_sfsr_mask = 0xffffffff,
1176 .mmu_trcr_mask = 0xffffffff,
1177 .nwindows = 8,
1178 .features = CPU_DEFAULT_FEATURES,
1181 .name = "TI SuperSparc 61",
1182 .iu_version = 0x44000000, // SuperSPARC 3.x
1183 .fpu_version = 0 << 17,
1184 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1185 .mmu_bm = 0x00002000,
1186 .mmu_ctpr_mask = 0xffffffc0,
1187 .mmu_cxr_mask = 0x0000ffff,
1188 .mmu_sfsr_mask = 0xffffffff,
1189 .mmu_trcr_mask = 0xffffffff,
1190 .mxcc_version = 0x00000104,
1191 .nwindows = 8,
1192 .features = CPU_DEFAULT_FEATURES,
1195 .name = "TI SuperSparc II",
1196 .iu_version = 0x40000000, // SuperSPARC II 1.x
1197 .fpu_version = 0 << 17,
1198 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1199 .mmu_bm = 0x00002000,
1200 .mmu_ctpr_mask = 0xffffffc0,
1201 .mmu_cxr_mask = 0x0000ffff,
1202 .mmu_sfsr_mask = 0xffffffff,
1203 .mmu_trcr_mask = 0xffffffff,
1204 .mxcc_version = 0x00000104,
1205 .nwindows = 8,
1206 .features = CPU_DEFAULT_FEATURES,
1209 .name = "Ross RT625",
1210 .iu_version = 0x1e000000,
1211 .fpu_version = 1 << 17,
1212 .mmu_version = 0x1e000000,
1213 .mmu_bm = 0x00004000,
1214 .mmu_ctpr_mask = 0x007ffff0,
1215 .mmu_cxr_mask = 0x0000003f,
1216 .mmu_sfsr_mask = 0xffffffff,
1217 .mmu_trcr_mask = 0xffffffff,
1218 .nwindows = 8,
1219 .features = CPU_DEFAULT_FEATURES,
1222 .name = "Ross RT620",
1223 .iu_version = 0x1f000000,
1224 .fpu_version = 1 << 17,
1225 .mmu_version = 0x1f000000,
1226 .mmu_bm = 0x00004000,
1227 .mmu_ctpr_mask = 0x007ffff0,
1228 .mmu_cxr_mask = 0x0000003f,
1229 .mmu_sfsr_mask = 0xffffffff,
1230 .mmu_trcr_mask = 0xffffffff,
1231 .nwindows = 8,
1232 .features = CPU_DEFAULT_FEATURES,
1235 .name = "BIT B5010",
1236 .iu_version = 0x20000000,
1237 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1238 .mmu_version = 0x20000000,
1239 .mmu_bm = 0x00004000,
1240 .mmu_ctpr_mask = 0x007ffff0,
1241 .mmu_cxr_mask = 0x0000003f,
1242 .mmu_sfsr_mask = 0xffffffff,
1243 .mmu_trcr_mask = 0xffffffff,
1244 .nwindows = 8,
1245 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1246 CPU_FEATURE_FSMULD,
1249 .name = "Matsushita MN10501",
1250 .iu_version = 0x50000000,
1251 .fpu_version = 0 << 17,
1252 .mmu_version = 0x50000000,
1253 .mmu_bm = 0x00004000,
1254 .mmu_ctpr_mask = 0x007ffff0,
1255 .mmu_cxr_mask = 0x0000003f,
1256 .mmu_sfsr_mask = 0xffffffff,
1257 .mmu_trcr_mask = 0xffffffff,
1258 .nwindows = 8,
1259 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1260 CPU_FEATURE_FSMULD,
1263 .name = "Weitek W8601",
1264 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1265 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1266 .mmu_version = 0x10 << 24,
1267 .mmu_bm = 0x00004000,
1268 .mmu_ctpr_mask = 0x007ffff0,
1269 .mmu_cxr_mask = 0x0000003f,
1270 .mmu_sfsr_mask = 0xffffffff,
1271 .mmu_trcr_mask = 0xffffffff,
1272 .nwindows = 8,
1273 .features = CPU_DEFAULT_FEATURES,
1276 .name = "LEON2",
1277 .iu_version = 0xf2000000,
1278 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1279 .mmu_version = 0xf2000000,
1280 .mmu_bm = 0x00004000,
1281 .mmu_ctpr_mask = 0x007ffff0,
1282 .mmu_cxr_mask = 0x0000003f,
1283 .mmu_sfsr_mask = 0xffffffff,
1284 .mmu_trcr_mask = 0xffffffff,
1285 .nwindows = 8,
1286 .features = CPU_DEFAULT_FEATURES,
1289 .name = "LEON3",
1290 .iu_version = 0xf3000000,
1291 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1292 .mmu_version = 0xf3000000,
1293 .mmu_bm = 0x00004000,
1294 .mmu_ctpr_mask = 0x007ffff0,
1295 .mmu_cxr_mask = 0x0000003f,
1296 .mmu_sfsr_mask = 0xffffffff,
1297 .mmu_trcr_mask = 0xffffffff,
1298 .nwindows = 8,
1299 .features = CPU_DEFAULT_FEATURES,
1301 #endif
1304 static const char * const feature_name[] = {
1305 "float",
1306 "float128",
1307 "swap",
1308 "mul",
1309 "div",
1310 "flush",
1311 "fsqrt",
1312 "fmul",
1313 "vis1",
1314 "vis2",
1315 "fsmuld",
1316 "hypv",
1317 "cmt",
1318 "gl",
1321 static void print_features(FILE *f,
1322 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1323 uint32_t features, const char *prefix)
1325 unsigned int i;
1327 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1328 if (feature_name[i] && (features & (1 << i))) {
1329 if (prefix)
1330 (*cpu_fprintf)(f, "%s", prefix);
1331 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1335 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1337 unsigned int i;
1339 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1340 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1341 *features |= 1 << i;
1342 return;
1344 fprintf(stderr, "CPU feature %s not found\n", flagname);
1347 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1349 unsigned int i;
1350 const sparc_def_t *def = NULL;
1351 char *s = strdup(cpu_model);
1352 char *featurestr, *name = strtok(s, ",");
1353 uint32_t plus_features = 0;
1354 uint32_t minus_features = 0;
1355 uint64_t iu_version;
1356 uint32_t fpu_version, mmu_version, nwindows;
1358 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1359 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1360 def = &sparc_defs[i];
1363 if (!def)
1364 goto error;
1365 memcpy(cpu_def, def, sizeof(*def));
1367 featurestr = strtok(NULL, ",");
1368 while (featurestr) {
1369 char *val;
1371 if (featurestr[0] == '+') {
1372 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1373 } else if (featurestr[0] == '-') {
1374 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1375 } else if ((val = strchr(featurestr, '='))) {
1376 *val = 0; val++;
1377 if (!strcmp(featurestr, "iu_version")) {
1378 char *err;
1380 iu_version = strtoll(val, &err, 0);
1381 if (!*val || *err) {
1382 fprintf(stderr, "bad numerical value %s\n", val);
1383 goto error;
1385 cpu_def->iu_version = iu_version;
1386 #ifdef DEBUG_FEATURES
1387 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1388 #endif
1389 } else if (!strcmp(featurestr, "fpu_version")) {
1390 char *err;
1392 fpu_version = strtol(val, &err, 0);
1393 if (!*val || *err) {
1394 fprintf(stderr, "bad numerical value %s\n", val);
1395 goto error;
1397 cpu_def->fpu_version = fpu_version;
1398 #ifdef DEBUG_FEATURES
1399 fprintf(stderr, "fpu_version %x\n", fpu_version);
1400 #endif
1401 } else if (!strcmp(featurestr, "mmu_version")) {
1402 char *err;
1404 mmu_version = strtol(val, &err, 0);
1405 if (!*val || *err) {
1406 fprintf(stderr, "bad numerical value %s\n", val);
1407 goto error;
1409 cpu_def->mmu_version = mmu_version;
1410 #ifdef DEBUG_FEATURES
1411 fprintf(stderr, "mmu_version %x\n", mmu_version);
1412 #endif
1413 } else if (!strcmp(featurestr, "nwindows")) {
1414 char *err;
1416 nwindows = strtol(val, &err, 0);
1417 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1418 nwindows < MIN_NWINDOWS) {
1419 fprintf(stderr, "bad numerical value %s\n", val);
1420 goto error;
1422 cpu_def->nwindows = nwindows;
1423 #ifdef DEBUG_FEATURES
1424 fprintf(stderr, "nwindows %d\n", nwindows);
1425 #endif
1426 } else {
1427 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1428 goto error;
1430 } else {
1431 fprintf(stderr, "feature string `%s' not in format "
1432 "(+feature|-feature|feature=xyz)\n", featurestr);
1433 goto error;
1435 featurestr = strtok(NULL, ",");
1437 cpu_def->features |= plus_features;
1438 cpu_def->features &= ~minus_features;
1439 #ifdef DEBUG_FEATURES
1440 print_features(stderr, fprintf, cpu_def->features, NULL);
1441 #endif
1442 free(s);
1443 return 0;
1445 error:
1446 free(s);
1447 return -1;
1450 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1452 unsigned int i;
1454 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1455 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1456 sparc_defs[i].name,
1457 sparc_defs[i].iu_version,
1458 sparc_defs[i].fpu_version,
1459 sparc_defs[i].mmu_version,
1460 sparc_defs[i].nwindows);
1461 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1462 ~sparc_defs[i].features, "-");
1463 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1464 sparc_defs[i].features, "+");
1465 (*cpu_fprintf)(f, "\n");
1467 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1468 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1469 (*cpu_fprintf)(f, "\n");
1470 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1471 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1472 (*cpu_fprintf)(f, "\n");
1473 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1474 "fpu_version mmu_version nwindows\n");
1477 static void cpu_print_cc(FILE *f,
1478 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1479 uint32_t cc)
1481 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1482 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1483 cc & PSR_CARRY? 'C' : '-');
1486 #ifdef TARGET_SPARC64
1487 #define REGS_PER_LINE 4
1488 #else
1489 #define REGS_PER_LINE 8
1490 #endif
1492 void cpu_dump_state(CPUState *env, FILE *f,
1493 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1494 int flags)
1496 int i, x;
1498 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1499 env->npc);
1500 cpu_fprintf(f, "General Registers:\n");
1502 for (i = 0; i < 8; i++) {
1503 if (i % REGS_PER_LINE == 0) {
1504 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1506 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1507 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1508 cpu_fprintf(f, "\n");
1511 cpu_fprintf(f, "\nCurrent Register Window:\n");
1512 for (x = 0; x < 3; x++) {
1513 for (i = 0; i < 8; i++) {
1514 if (i % REGS_PER_LINE == 0) {
1515 cpu_fprintf(f, "%%%c%d-%d: ",
1516 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1517 i, i + REGS_PER_LINE - 1);
1519 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1520 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1521 cpu_fprintf(f, "\n");
1525 cpu_fprintf(f, "\nFloating Point Registers:\n");
1526 for (i = 0; i < TARGET_FPREGS; i++) {
1527 if ((i & 3) == 0)
1528 cpu_fprintf(f, "%%f%02d:", i);
1529 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1530 if ((i & 3) == 3)
1531 cpu_fprintf(f, "\n");
1533 #ifdef TARGET_SPARC64
1534 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1535 (unsigned)cpu_get_ccr(env));
1536 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1537 cpu_fprintf(f, " xcc: ");
1538 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1539 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1540 env->psrpil);
1541 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1542 "cleanwin: %d cwp: %d\n",
1543 env->cansave, env->canrestore, env->otherwin, env->wstate,
1544 env->cleanwin, env->nwindows - 1 - env->cwp);
1545 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1546 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1547 #else
1548 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1549 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1550 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1551 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1552 env->wim);
1553 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1554 env->fsr, env->y);
1555 #endif