sparc64: fix dump_mmu to look for global bit in tte value instead of tag
[qemu/aliguori-queue.git] / target-sparc / helper.c
blob1045c317913e68cc22aa036e4358c13892a6595e
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;
575 if (rw == 2)
576 return get_physical_address_code(env, physical, prot, address,
577 mmu_idx);
578 else
579 return get_physical_address_data(env, physical, prot, address, rw,
580 mmu_idx);
583 /* Perform address translation */
584 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
585 int mmu_idx, int is_softmmu)
587 target_ulong virt_addr, vaddr;
588 target_phys_addr_t paddr;
589 target_ulong page_size;
590 int error_code = 0, prot, access_index;
592 error_code = get_physical_address(env, &paddr, &prot, &access_index,
593 address, rw, mmu_idx, &page_size);
594 if (error_code == 0) {
595 virt_addr = address & TARGET_PAGE_MASK;
596 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
597 (TARGET_PAGE_SIZE - 1));
599 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
600 " vaddr %" PRIx64
601 " mmu_idx=%d"
602 " tl=%d"
603 " primary context=%" PRIx64
604 " secondary context=%" PRIx64
605 "\n",
606 address, paddr, vaddr, mmu_idx, env->tl,
607 env->dmmu.mmu_primary_context,
608 env->dmmu.mmu_secondary_context);
610 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
611 return 0;
613 // XXX
614 return 1;
617 #ifdef DEBUG_MMU
618 void dump_mmu(CPUState *env)
620 unsigned int i;
621 const char *mask;
623 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
624 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
625 if ((env->lsu & DMMU_E) == 0) {
626 printf("DMMU disabled\n");
627 } else {
628 printf("DMMU dump:\n");
629 for (i = 0; i < 64; i++) {
630 switch ((env->dtlb[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->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
646 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
647 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
649 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
650 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
651 mask,
652 env->dtlb[i].tte & 0x4? "priv": "user",
653 env->dtlb[i].tte & 0x2? "RW": "RO",
654 env->dtlb[i].tte & 0x40? "locked": "unlocked",
655 env->dtlb[i].tag & (uint64_t)0x1fffULL,
656 TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local");
660 if ((env->lsu & IMMU_E) == 0) {
661 printf("IMMU disabled\n");
662 } else {
663 printf("IMMU dump:\n");
664 for (i = 0; i < 64; i++) {
665 switch ((env->itlb[i].tte >> 61) & 3) {
666 default:
667 case 0x0:
668 mask = " 8k";
669 break;
670 case 0x1:
671 mask = " 64k";
672 break;
673 case 0x2:
674 mask = "512k";
675 break;
676 case 0x3:
677 mask = " 4M";
678 break;
680 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
681 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
682 ", %s, %s, %s, ctx %" PRId64 " %s\n",
684 env->itlb[i].tag & (uint64_t)~0x1fffULL,
685 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
686 mask,
687 env->itlb[i].tte & 0x4? "priv": "user",
688 env->itlb[i].tte & 0x40? "locked": "unlocked",
689 env->itlb[i].tag & (uint64_t)0x1fffULL,
690 TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local");
695 #endif /* DEBUG_MMU */
697 #endif /* TARGET_SPARC64 */
698 #endif /* !CONFIG_USER_ONLY */
701 #if !defined(CONFIG_USER_ONLY)
702 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
703 int mmu_idx)
705 target_phys_addr_t phys_addr;
706 target_ulong page_size;
707 int prot, access_index;
709 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
710 mmu_idx, &page_size) != 0)
711 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
712 0, mmu_idx, &page_size) != 0)
713 return -1;
714 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
715 return -1;
716 return phys_addr;
719 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
721 return cpu_get_phys_page_nofault(env, addr, MMU_KERNEL_IDX);
723 #endif
725 void cpu_reset(CPUSPARCState *env)
727 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
728 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
729 log_cpu_state(env, 0);
732 tlb_flush(env, 1);
733 env->cwp = 0;
734 #ifndef TARGET_SPARC64
735 env->wim = 1;
736 #endif
737 env->regwptr = env->regbase + (env->cwp * 16);
738 CC_OP = CC_OP_FLAGS;
739 #if defined(CONFIG_USER_ONLY)
740 #ifdef TARGET_SPARC64
741 env->cleanwin = env->nwindows - 2;
742 env->cansave = env->nwindows - 2;
743 env->pstate = PS_RMO | PS_PEF | PS_IE;
744 env->asi = 0x82; // Primary no-fault
745 #endif
746 #else
747 #if !defined(TARGET_SPARC64)
748 env->psret = 0;
749 env->psrs = 1;
750 env->psrps = 1;
751 #endif
752 #ifdef TARGET_SPARC64
753 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
754 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
755 env->tl = env->maxtl;
756 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
757 env->lsu = 0;
758 #else
759 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
760 env->mmuregs[0] |= env->def->mmu_bm;
761 #endif
762 env->pc = 0;
763 env->npc = env->pc + 4;
764 #endif
767 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
769 sparc_def_t def1, *def = &def1;
771 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
772 return -1;
774 env->def = qemu_mallocz(sizeof(*def));
775 memcpy(env->def, def, sizeof(*def));
776 #if defined(CONFIG_USER_ONLY)
777 if ((env->def->features & CPU_FEATURE_FLOAT))
778 env->def->features |= CPU_FEATURE_FLOAT128;
779 #endif
780 env->cpu_model_str = cpu_model;
781 env->version = def->iu_version;
782 env->fsr = def->fpu_version;
783 env->nwindows = def->nwindows;
784 #if !defined(TARGET_SPARC64)
785 env->mmuregs[0] |= def->mmu_version;
786 cpu_sparc_set_id(env, 0);
787 env->mxccregs[7] |= def->mxcc_version;
788 #else
789 env->mmu_version = def->mmu_version;
790 env->maxtl = def->maxtl;
791 env->version |= def->maxtl << 8;
792 env->version |= def->nwindows - 1;
793 #endif
794 return 0;
797 static void cpu_sparc_close(CPUSPARCState *env)
799 free(env->def);
800 free(env);
803 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
805 CPUSPARCState *env;
807 env = qemu_mallocz(sizeof(CPUSPARCState));
808 cpu_exec_init(env);
810 gen_intermediate_code_init(env);
812 if (cpu_sparc_register(env, cpu_model) < 0) {
813 cpu_sparc_close(env);
814 return NULL;
816 qemu_init_vcpu(env);
818 return env;
821 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
823 #if !defined(TARGET_SPARC64)
824 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
825 #endif
828 static const sparc_def_t sparc_defs[] = {
829 #ifdef TARGET_SPARC64
831 .name = "Fujitsu Sparc64",
832 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
833 .fpu_version = 0x00000000,
834 .mmu_version = mmu_us_12,
835 .nwindows = 4,
836 .maxtl = 4,
837 .features = CPU_DEFAULT_FEATURES,
840 .name = "Fujitsu Sparc64 III",
841 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
842 .fpu_version = 0x00000000,
843 .mmu_version = mmu_us_12,
844 .nwindows = 5,
845 .maxtl = 4,
846 .features = CPU_DEFAULT_FEATURES,
849 .name = "Fujitsu Sparc64 IV",
850 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
851 .fpu_version = 0x00000000,
852 .mmu_version = mmu_us_12,
853 .nwindows = 8,
854 .maxtl = 5,
855 .features = CPU_DEFAULT_FEATURES,
858 .name = "Fujitsu Sparc64 V",
859 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
860 .fpu_version = 0x00000000,
861 .mmu_version = mmu_us_12,
862 .nwindows = 8,
863 .maxtl = 5,
864 .features = CPU_DEFAULT_FEATURES,
867 .name = "TI UltraSparc I",
868 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
869 .fpu_version = 0x00000000,
870 .mmu_version = mmu_us_12,
871 .nwindows = 8,
872 .maxtl = 5,
873 .features = CPU_DEFAULT_FEATURES,
876 .name = "TI UltraSparc II",
877 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
878 .fpu_version = 0x00000000,
879 .mmu_version = mmu_us_12,
880 .nwindows = 8,
881 .maxtl = 5,
882 .features = CPU_DEFAULT_FEATURES,
885 .name = "TI UltraSparc IIi",
886 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
887 .fpu_version = 0x00000000,
888 .mmu_version = mmu_us_12,
889 .nwindows = 8,
890 .maxtl = 5,
891 .features = CPU_DEFAULT_FEATURES,
894 .name = "TI UltraSparc IIe",
895 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
896 .fpu_version = 0x00000000,
897 .mmu_version = mmu_us_12,
898 .nwindows = 8,
899 .maxtl = 5,
900 .features = CPU_DEFAULT_FEATURES,
903 .name = "Sun UltraSparc III",
904 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
905 .fpu_version = 0x00000000,
906 .mmu_version = mmu_us_12,
907 .nwindows = 8,
908 .maxtl = 5,
909 .features = CPU_DEFAULT_FEATURES,
912 .name = "Sun UltraSparc III Cu",
913 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
914 .fpu_version = 0x00000000,
915 .mmu_version = mmu_us_3,
916 .nwindows = 8,
917 .maxtl = 5,
918 .features = CPU_DEFAULT_FEATURES,
921 .name = "Sun UltraSparc IIIi",
922 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
923 .fpu_version = 0x00000000,
924 .mmu_version = mmu_us_12,
925 .nwindows = 8,
926 .maxtl = 5,
927 .features = CPU_DEFAULT_FEATURES,
930 .name = "Sun UltraSparc IV",
931 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
932 .fpu_version = 0x00000000,
933 .mmu_version = mmu_us_4,
934 .nwindows = 8,
935 .maxtl = 5,
936 .features = CPU_DEFAULT_FEATURES,
939 .name = "Sun UltraSparc IV+",
940 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
941 .fpu_version = 0x00000000,
942 .mmu_version = mmu_us_12,
943 .nwindows = 8,
944 .maxtl = 5,
945 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
948 .name = "Sun UltraSparc IIIi+",
949 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
950 .fpu_version = 0x00000000,
951 .mmu_version = mmu_us_3,
952 .nwindows = 8,
953 .maxtl = 5,
954 .features = CPU_DEFAULT_FEATURES,
957 .name = "Sun UltraSparc T1",
958 // defined in sparc_ifu_fdp.v and ctu.h
959 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
960 .fpu_version = 0x00000000,
961 .mmu_version = mmu_sun4v,
962 .nwindows = 8,
963 .maxtl = 6,
964 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
965 | CPU_FEATURE_GL,
968 .name = "Sun UltraSparc T2",
969 // defined in tlu_asi_ctl.v and n2_revid_cust.v
970 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
971 .fpu_version = 0x00000000,
972 .mmu_version = mmu_sun4v,
973 .nwindows = 8,
974 .maxtl = 6,
975 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
976 | CPU_FEATURE_GL,
979 .name = "NEC UltraSparc I",
980 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
981 .fpu_version = 0x00000000,
982 .mmu_version = mmu_us_12,
983 .nwindows = 8,
984 .maxtl = 5,
985 .features = CPU_DEFAULT_FEATURES,
987 #else
989 .name = "Fujitsu MB86900",
990 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
991 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
992 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
993 .mmu_bm = 0x00004000,
994 .mmu_ctpr_mask = 0x007ffff0,
995 .mmu_cxr_mask = 0x0000003f,
996 .mmu_sfsr_mask = 0xffffffff,
997 .mmu_trcr_mask = 0xffffffff,
998 .nwindows = 7,
999 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1002 .name = "Fujitsu MB86904",
1003 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1004 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1005 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1006 .mmu_bm = 0x00004000,
1007 .mmu_ctpr_mask = 0x00ffffc0,
1008 .mmu_cxr_mask = 0x000000ff,
1009 .mmu_sfsr_mask = 0x00016fff,
1010 .mmu_trcr_mask = 0x00ffffff,
1011 .nwindows = 8,
1012 .features = CPU_DEFAULT_FEATURES,
1015 .name = "Fujitsu MB86907",
1016 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1017 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1018 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1019 .mmu_bm = 0x00004000,
1020 .mmu_ctpr_mask = 0xffffffc0,
1021 .mmu_cxr_mask = 0x000000ff,
1022 .mmu_sfsr_mask = 0x00016fff,
1023 .mmu_trcr_mask = 0xffffffff,
1024 .nwindows = 8,
1025 .features = CPU_DEFAULT_FEATURES,
1028 .name = "LSI L64811",
1029 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1030 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1031 .mmu_version = 0x10 << 24,
1032 .mmu_bm = 0x00004000,
1033 .mmu_ctpr_mask = 0x007ffff0,
1034 .mmu_cxr_mask = 0x0000003f,
1035 .mmu_sfsr_mask = 0xffffffff,
1036 .mmu_trcr_mask = 0xffffffff,
1037 .nwindows = 8,
1038 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1039 CPU_FEATURE_FSMULD,
1042 .name = "Cypress CY7C601",
1043 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1044 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1045 .mmu_version = 0x10 << 24,
1046 .mmu_bm = 0x00004000,
1047 .mmu_ctpr_mask = 0x007ffff0,
1048 .mmu_cxr_mask = 0x0000003f,
1049 .mmu_sfsr_mask = 0xffffffff,
1050 .mmu_trcr_mask = 0xffffffff,
1051 .nwindows = 8,
1052 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1053 CPU_FEATURE_FSMULD,
1056 .name = "Cypress CY7C611",
1057 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1058 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1059 .mmu_version = 0x10 << 24,
1060 .mmu_bm = 0x00004000,
1061 .mmu_ctpr_mask = 0x007ffff0,
1062 .mmu_cxr_mask = 0x0000003f,
1063 .mmu_sfsr_mask = 0xffffffff,
1064 .mmu_trcr_mask = 0xffffffff,
1065 .nwindows = 8,
1066 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1067 CPU_FEATURE_FSMULD,
1070 .name = "TI MicroSparc I",
1071 .iu_version = 0x41000000,
1072 .fpu_version = 4 << 17,
1073 .mmu_version = 0x41000000,
1074 .mmu_bm = 0x00004000,
1075 .mmu_ctpr_mask = 0x007ffff0,
1076 .mmu_cxr_mask = 0x0000003f,
1077 .mmu_sfsr_mask = 0x00016fff,
1078 .mmu_trcr_mask = 0x0000003f,
1079 .nwindows = 7,
1080 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1081 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1082 CPU_FEATURE_FMUL,
1085 .name = "TI MicroSparc II",
1086 .iu_version = 0x42000000,
1087 .fpu_version = 4 << 17,
1088 .mmu_version = 0x02000000,
1089 .mmu_bm = 0x00004000,
1090 .mmu_ctpr_mask = 0x00ffffc0,
1091 .mmu_cxr_mask = 0x000000ff,
1092 .mmu_sfsr_mask = 0x00016fff,
1093 .mmu_trcr_mask = 0x00ffffff,
1094 .nwindows = 8,
1095 .features = CPU_DEFAULT_FEATURES,
1098 .name = "TI MicroSparc IIep",
1099 .iu_version = 0x42000000,
1100 .fpu_version = 4 << 17,
1101 .mmu_version = 0x04000000,
1102 .mmu_bm = 0x00004000,
1103 .mmu_ctpr_mask = 0x00ffffc0,
1104 .mmu_cxr_mask = 0x000000ff,
1105 .mmu_sfsr_mask = 0x00016bff,
1106 .mmu_trcr_mask = 0x00ffffff,
1107 .nwindows = 8,
1108 .features = CPU_DEFAULT_FEATURES,
1111 .name = "TI SuperSparc 40", // STP1020NPGA
1112 .iu_version = 0x41000000, // SuperSPARC 2.x
1113 .fpu_version = 0 << 17,
1114 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1115 .mmu_bm = 0x00002000,
1116 .mmu_ctpr_mask = 0xffffffc0,
1117 .mmu_cxr_mask = 0x0000ffff,
1118 .mmu_sfsr_mask = 0xffffffff,
1119 .mmu_trcr_mask = 0xffffffff,
1120 .nwindows = 8,
1121 .features = CPU_DEFAULT_FEATURES,
1124 .name = "TI SuperSparc 50", // STP1020PGA
1125 .iu_version = 0x40000000, // SuperSPARC 3.x
1126 .fpu_version = 0 << 17,
1127 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1128 .mmu_bm = 0x00002000,
1129 .mmu_ctpr_mask = 0xffffffc0,
1130 .mmu_cxr_mask = 0x0000ffff,
1131 .mmu_sfsr_mask = 0xffffffff,
1132 .mmu_trcr_mask = 0xffffffff,
1133 .nwindows = 8,
1134 .features = CPU_DEFAULT_FEATURES,
1137 .name = "TI SuperSparc 51",
1138 .iu_version = 0x40000000, // SuperSPARC 3.x
1139 .fpu_version = 0 << 17,
1140 .mmu_version = 0x01000000, // SuperSPARC 3.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 = "TI SuperSparc 60", // STP1020APGA
1152 .iu_version = 0x40000000, // SuperSPARC 3.x
1153 .fpu_version = 0 << 17,
1154 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1155 .mmu_bm = 0x00002000,
1156 .mmu_ctpr_mask = 0xffffffc0,
1157 .mmu_cxr_mask = 0x0000ffff,
1158 .mmu_sfsr_mask = 0xffffffff,
1159 .mmu_trcr_mask = 0xffffffff,
1160 .nwindows = 8,
1161 .features = CPU_DEFAULT_FEATURES,
1164 .name = "TI SuperSparc 61",
1165 .iu_version = 0x44000000, // SuperSPARC 3.x
1166 .fpu_version = 0 << 17,
1167 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1168 .mmu_bm = 0x00002000,
1169 .mmu_ctpr_mask = 0xffffffc0,
1170 .mmu_cxr_mask = 0x0000ffff,
1171 .mmu_sfsr_mask = 0xffffffff,
1172 .mmu_trcr_mask = 0xffffffff,
1173 .mxcc_version = 0x00000104,
1174 .nwindows = 8,
1175 .features = CPU_DEFAULT_FEATURES,
1178 .name = "TI SuperSparc II",
1179 .iu_version = 0x40000000, // SuperSPARC II 1.x
1180 .fpu_version = 0 << 17,
1181 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1182 .mmu_bm = 0x00002000,
1183 .mmu_ctpr_mask = 0xffffffc0,
1184 .mmu_cxr_mask = 0x0000ffff,
1185 .mmu_sfsr_mask = 0xffffffff,
1186 .mmu_trcr_mask = 0xffffffff,
1187 .mxcc_version = 0x00000104,
1188 .nwindows = 8,
1189 .features = CPU_DEFAULT_FEATURES,
1192 .name = "Ross RT625",
1193 .iu_version = 0x1e000000,
1194 .fpu_version = 1 << 17,
1195 .mmu_version = 0x1e000000,
1196 .mmu_bm = 0x00004000,
1197 .mmu_ctpr_mask = 0x007ffff0,
1198 .mmu_cxr_mask = 0x0000003f,
1199 .mmu_sfsr_mask = 0xffffffff,
1200 .mmu_trcr_mask = 0xffffffff,
1201 .nwindows = 8,
1202 .features = CPU_DEFAULT_FEATURES,
1205 .name = "Ross RT620",
1206 .iu_version = 0x1f000000,
1207 .fpu_version = 1 << 17,
1208 .mmu_version = 0x1f000000,
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 = "BIT B5010",
1219 .iu_version = 0x20000000,
1220 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1221 .mmu_version = 0x20000000,
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_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1229 CPU_FEATURE_FSMULD,
1232 .name = "Matsushita MN10501",
1233 .iu_version = 0x50000000,
1234 .fpu_version = 0 << 17,
1235 .mmu_version = 0x50000000,
1236 .mmu_bm = 0x00004000,
1237 .mmu_ctpr_mask = 0x007ffff0,
1238 .mmu_cxr_mask = 0x0000003f,
1239 .mmu_sfsr_mask = 0xffffffff,
1240 .mmu_trcr_mask = 0xffffffff,
1241 .nwindows = 8,
1242 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1243 CPU_FEATURE_FSMULD,
1246 .name = "Weitek W8601",
1247 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1248 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1249 .mmu_version = 0x10 << 24,
1250 .mmu_bm = 0x00004000,
1251 .mmu_ctpr_mask = 0x007ffff0,
1252 .mmu_cxr_mask = 0x0000003f,
1253 .mmu_sfsr_mask = 0xffffffff,
1254 .mmu_trcr_mask = 0xffffffff,
1255 .nwindows = 8,
1256 .features = CPU_DEFAULT_FEATURES,
1259 .name = "LEON2",
1260 .iu_version = 0xf2000000,
1261 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1262 .mmu_version = 0xf2000000,
1263 .mmu_bm = 0x00004000,
1264 .mmu_ctpr_mask = 0x007ffff0,
1265 .mmu_cxr_mask = 0x0000003f,
1266 .mmu_sfsr_mask = 0xffffffff,
1267 .mmu_trcr_mask = 0xffffffff,
1268 .nwindows = 8,
1269 .features = CPU_DEFAULT_FEATURES,
1272 .name = "LEON3",
1273 .iu_version = 0xf3000000,
1274 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1275 .mmu_version = 0xf3000000,
1276 .mmu_bm = 0x00004000,
1277 .mmu_ctpr_mask = 0x007ffff0,
1278 .mmu_cxr_mask = 0x0000003f,
1279 .mmu_sfsr_mask = 0xffffffff,
1280 .mmu_trcr_mask = 0xffffffff,
1281 .nwindows = 8,
1282 .features = CPU_DEFAULT_FEATURES,
1284 #endif
1287 static const char * const feature_name[] = {
1288 "float",
1289 "float128",
1290 "swap",
1291 "mul",
1292 "div",
1293 "flush",
1294 "fsqrt",
1295 "fmul",
1296 "vis1",
1297 "vis2",
1298 "fsmuld",
1299 "hypv",
1300 "cmt",
1301 "gl",
1304 static void print_features(FILE *f,
1305 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1306 uint32_t features, const char *prefix)
1308 unsigned int i;
1310 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1311 if (feature_name[i] && (features & (1 << i))) {
1312 if (prefix)
1313 (*cpu_fprintf)(f, "%s", prefix);
1314 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1318 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1320 unsigned int i;
1322 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1323 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1324 *features |= 1 << i;
1325 return;
1327 fprintf(stderr, "CPU feature %s not found\n", flagname);
1330 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1332 unsigned int i;
1333 const sparc_def_t *def = NULL;
1334 char *s = strdup(cpu_model);
1335 char *featurestr, *name = strtok(s, ",");
1336 uint32_t plus_features = 0;
1337 uint32_t minus_features = 0;
1338 uint64_t iu_version;
1339 uint32_t fpu_version, mmu_version, nwindows;
1341 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1342 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1343 def = &sparc_defs[i];
1346 if (!def)
1347 goto error;
1348 memcpy(cpu_def, def, sizeof(*def));
1350 featurestr = strtok(NULL, ",");
1351 while (featurestr) {
1352 char *val;
1354 if (featurestr[0] == '+') {
1355 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1356 } else if (featurestr[0] == '-') {
1357 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1358 } else if ((val = strchr(featurestr, '='))) {
1359 *val = 0; val++;
1360 if (!strcmp(featurestr, "iu_version")) {
1361 char *err;
1363 iu_version = strtoll(val, &err, 0);
1364 if (!*val || *err) {
1365 fprintf(stderr, "bad numerical value %s\n", val);
1366 goto error;
1368 cpu_def->iu_version = iu_version;
1369 #ifdef DEBUG_FEATURES
1370 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1371 #endif
1372 } else if (!strcmp(featurestr, "fpu_version")) {
1373 char *err;
1375 fpu_version = strtol(val, &err, 0);
1376 if (!*val || *err) {
1377 fprintf(stderr, "bad numerical value %s\n", val);
1378 goto error;
1380 cpu_def->fpu_version = fpu_version;
1381 #ifdef DEBUG_FEATURES
1382 fprintf(stderr, "fpu_version %x\n", fpu_version);
1383 #endif
1384 } else if (!strcmp(featurestr, "mmu_version")) {
1385 char *err;
1387 mmu_version = strtol(val, &err, 0);
1388 if (!*val || *err) {
1389 fprintf(stderr, "bad numerical value %s\n", val);
1390 goto error;
1392 cpu_def->mmu_version = mmu_version;
1393 #ifdef DEBUG_FEATURES
1394 fprintf(stderr, "mmu_version %x\n", mmu_version);
1395 #endif
1396 } else if (!strcmp(featurestr, "nwindows")) {
1397 char *err;
1399 nwindows = strtol(val, &err, 0);
1400 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1401 nwindows < MIN_NWINDOWS) {
1402 fprintf(stderr, "bad numerical value %s\n", val);
1403 goto error;
1405 cpu_def->nwindows = nwindows;
1406 #ifdef DEBUG_FEATURES
1407 fprintf(stderr, "nwindows %d\n", nwindows);
1408 #endif
1409 } else {
1410 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1411 goto error;
1413 } else {
1414 fprintf(stderr, "feature string `%s' not in format "
1415 "(+feature|-feature|feature=xyz)\n", featurestr);
1416 goto error;
1418 featurestr = strtok(NULL, ",");
1420 cpu_def->features |= plus_features;
1421 cpu_def->features &= ~minus_features;
1422 #ifdef DEBUG_FEATURES
1423 print_features(stderr, fprintf, cpu_def->features, NULL);
1424 #endif
1425 free(s);
1426 return 0;
1428 error:
1429 free(s);
1430 return -1;
1433 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1435 unsigned int i;
1437 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1438 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1439 sparc_defs[i].name,
1440 sparc_defs[i].iu_version,
1441 sparc_defs[i].fpu_version,
1442 sparc_defs[i].mmu_version,
1443 sparc_defs[i].nwindows);
1444 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1445 ~sparc_defs[i].features, "-");
1446 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1447 sparc_defs[i].features, "+");
1448 (*cpu_fprintf)(f, "\n");
1450 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1451 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1452 (*cpu_fprintf)(f, "\n");
1453 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1454 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1455 (*cpu_fprintf)(f, "\n");
1456 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1457 "fpu_version mmu_version nwindows\n");
1460 static void cpu_print_cc(FILE *f,
1461 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1462 uint32_t cc)
1464 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1465 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1466 cc & PSR_CARRY? 'C' : '-');
1469 #ifdef TARGET_SPARC64
1470 #define REGS_PER_LINE 4
1471 #else
1472 #define REGS_PER_LINE 8
1473 #endif
1475 void cpu_dump_state(CPUState *env, FILE *f,
1476 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1477 int flags)
1479 int i, x;
1481 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1482 env->npc);
1483 cpu_fprintf(f, "General Registers:\n");
1485 for (i = 0; i < 8; i++) {
1486 if (i % REGS_PER_LINE == 0) {
1487 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1489 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1490 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1491 cpu_fprintf(f, "\n");
1494 cpu_fprintf(f, "\nCurrent Register Window:\n");
1495 for (x = 0; x < 3; x++) {
1496 for (i = 0; i < 8; i++) {
1497 if (i % REGS_PER_LINE == 0) {
1498 cpu_fprintf(f, "%%%c%d-%d: ",
1499 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1500 i, i + REGS_PER_LINE - 1);
1502 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1503 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1504 cpu_fprintf(f, "\n");
1508 cpu_fprintf(f, "\nFloating Point Registers:\n");
1509 for (i = 0; i < TARGET_FPREGS; i++) {
1510 if ((i & 3) == 0)
1511 cpu_fprintf(f, "%%f%02d:", i);
1512 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1513 if ((i & 3) == 3)
1514 cpu_fprintf(f, "\n");
1516 #ifdef TARGET_SPARC64
1517 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1518 (unsigned)cpu_get_ccr(env));
1519 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1520 cpu_fprintf(f, " xcc: ");
1521 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1522 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1523 env->psrpil);
1524 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1525 "cleanwin: %d cwp: %d\n",
1526 env->cansave, env->canrestore, env->otherwin, env->wstate,
1527 env->cleanwin, env->nwindows - 1 - env->cwp);
1528 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1529 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1530 #else
1531 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1532 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1533 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1534 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1535 env->wim);
1536 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1537 env->fsr, env->y);
1538 #endif