Merge remote branch 'qmp/for-anthony' into staging
[qemu.git] / target-sparc / helper.c
blobaa1fd632cc586bf35296a49d8c2274569b73a44f
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 */
499 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
501 return 1;
505 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
506 address, context);
508 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
509 env->exception_index = TT_DMISS;
510 return 1;
513 static int get_physical_address_code(CPUState *env,
514 target_phys_addr_t *physical, int *prot,
515 target_ulong address, int mmu_idx)
517 unsigned int i;
518 uint64_t context;
520 int is_user = (mmu_idx == MMU_USER_IDX ||
521 mmu_idx == MMU_USER_SECONDARY_IDX);
523 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
524 /* IMMU disabled */
525 *physical = ultrasparc_truncate_physical(address);
526 *prot = PAGE_EXEC;
527 return 0;
530 if (env->tl == 0) {
531 /* PRIMARY context */
532 context = env->dmmu.mmu_primary_context & 0x1fff;
533 } else {
534 /* NUCLEUS context */
535 context = 0;
538 for (i = 0; i < 64; i++) {
539 // ctx match, vaddr match, valid?
540 if (ultrasparc_tag_match(&env->itlb[i],
541 address, context, physical)) {
542 // access ok?
543 if ((env->itlb[i].tte & 0x4) && is_user) {
544 if (env->immu.sfsr) /* Fault status register */
545 env->immu.sfsr = 2; /* overflow (not read before
546 another fault) */
547 env->immu.sfsr |= (is_user << 3) | 1;
548 env->exception_index = TT_TFAULT;
550 env->immu.tag_access = (address & ~0x1fffULL) | context;
552 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
553 address, context);
555 return 1;
557 *prot = PAGE_EXEC;
558 TTE_SET_USED(env->itlb[i].tte);
559 return 0;
563 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
564 address, context);
566 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
567 env->immu.tag_access = (address & ~0x1fffULL) | context;
568 env->exception_index = TT_TMISS;
569 return 1;
572 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
573 int *prot, int *access_index,
574 target_ulong address, int rw, int mmu_idx,
575 target_ulong *page_size)
577 /* ??? We treat everything as a small page, then explicitly flush
578 everything when an entry is evicted. */
579 *page_size = TARGET_PAGE_SIZE;
581 #if defined (DEBUG_MMU)
582 /* safety net to catch wrong softmmu index use from dynamic code */
583 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
584 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
585 " primary context=%" PRIx64
586 " secondary context=%" PRIx64
587 " address=%" PRIx64
588 "\n",
589 (rw == 2 ? "CODE" : "DATA"),
590 env->tl, mmu_idx,
591 env->dmmu.mmu_primary_context,
592 env->dmmu.mmu_secondary_context,
593 address);
595 #endif
597 if (rw == 2)
598 return get_physical_address_code(env, physical, prot, address,
599 mmu_idx);
600 else
601 return get_physical_address_data(env, physical, prot, address, rw,
602 mmu_idx);
605 /* Perform address translation */
606 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
607 int mmu_idx, int is_softmmu)
609 target_ulong virt_addr, vaddr;
610 target_phys_addr_t paddr;
611 target_ulong page_size;
612 int error_code = 0, prot, access_index;
614 error_code = get_physical_address(env, &paddr, &prot, &access_index,
615 address, rw, mmu_idx, &page_size);
616 if (error_code == 0) {
617 virt_addr = address & TARGET_PAGE_MASK;
618 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
619 (TARGET_PAGE_SIZE - 1));
621 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
622 " vaddr %" PRIx64
623 " mmu_idx=%d"
624 " tl=%d"
625 " primary context=%" PRIx64
626 " secondary context=%" PRIx64
627 "\n",
628 address, paddr, vaddr, mmu_idx, env->tl,
629 env->dmmu.mmu_primary_context,
630 env->dmmu.mmu_secondary_context);
632 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
633 return 0;
635 // XXX
636 return 1;
639 #ifdef DEBUG_MMU
640 void dump_mmu(CPUState *env)
642 unsigned int i;
643 const char *mask;
645 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
646 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
647 if ((env->lsu & DMMU_E) == 0) {
648 printf("DMMU disabled\n");
649 } else {
650 printf("DMMU dump:\n");
651 for (i = 0; i < 64; i++) {
652 switch ((env->dtlb[i].tte >> 61) & 3) {
653 default:
654 case 0x0:
655 mask = " 8k";
656 break;
657 case 0x1:
658 mask = " 64k";
659 break;
660 case 0x2:
661 mask = "512k";
662 break;
663 case 0x3:
664 mask = " 4M";
665 break;
667 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
668 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
669 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
671 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
672 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
673 mask,
674 env->dtlb[i].tte & 0x4? "priv": "user",
675 env->dtlb[i].tte & 0x2? "RW": "RO",
676 env->dtlb[i].tte & 0x40? "locked": "unlocked",
677 env->dtlb[i].tag & (uint64_t)0x1fffULL,
678 TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local");
682 if ((env->lsu & IMMU_E) == 0) {
683 printf("IMMU disabled\n");
684 } else {
685 printf("IMMU dump:\n");
686 for (i = 0; i < 64; i++) {
687 switch ((env->itlb[i].tte >> 61) & 3) {
688 default:
689 case 0x0:
690 mask = " 8k";
691 break;
692 case 0x1:
693 mask = " 64k";
694 break;
695 case 0x2:
696 mask = "512k";
697 break;
698 case 0x3:
699 mask = " 4M";
700 break;
702 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
703 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
704 ", %s, %s, %s, ctx %" PRId64 " %s\n",
706 env->itlb[i].tag & (uint64_t)~0x1fffULL,
707 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
708 mask,
709 env->itlb[i].tte & 0x4? "priv": "user",
710 env->itlb[i].tte & 0x40? "locked": "unlocked",
711 env->itlb[i].tag & (uint64_t)0x1fffULL,
712 TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local");
717 #endif /* DEBUG_MMU */
719 #endif /* TARGET_SPARC64 */
720 #endif /* !CONFIG_USER_ONLY */
723 #if !defined(CONFIG_USER_ONLY)
724 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
725 int mmu_idx)
727 target_phys_addr_t phys_addr;
728 target_ulong page_size;
729 int prot, access_index;
731 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
732 mmu_idx, &page_size) != 0)
733 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
734 0, mmu_idx, &page_size) != 0)
735 return -1;
736 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
737 return -1;
738 return phys_addr;
741 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
743 return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
745 #endif
747 void cpu_reset(CPUSPARCState *env)
749 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
750 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
751 log_cpu_state(env, 0);
754 tlb_flush(env, 1);
755 env->cwp = 0;
756 #ifndef TARGET_SPARC64
757 env->wim = 1;
758 #endif
759 env->regwptr = env->regbase + (env->cwp * 16);
760 CC_OP = CC_OP_FLAGS;
761 #if defined(CONFIG_USER_ONLY)
762 #ifdef TARGET_SPARC64
763 env->cleanwin = env->nwindows - 2;
764 env->cansave = env->nwindows - 2;
765 env->pstate = PS_RMO | PS_PEF | PS_IE;
766 env->asi = 0x82; // Primary no-fault
767 #endif
768 #else
769 #if !defined(TARGET_SPARC64)
770 env->psret = 0;
771 env->psrs = 1;
772 env->psrps = 1;
773 #endif
774 #ifdef TARGET_SPARC64
775 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
776 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
777 env->tl = env->maxtl;
778 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
779 env->lsu = 0;
780 #else
781 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
782 env->mmuregs[0] |= env->def->mmu_bm;
783 #endif
784 env->pc = 0;
785 env->npc = env->pc + 4;
786 #endif
789 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
791 sparc_def_t def1, *def = &def1;
793 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
794 return -1;
796 env->def = qemu_mallocz(sizeof(*def));
797 memcpy(env->def, def, sizeof(*def));
798 #if defined(CONFIG_USER_ONLY)
799 if ((env->def->features & CPU_FEATURE_FLOAT))
800 env->def->features |= CPU_FEATURE_FLOAT128;
801 #endif
802 env->cpu_model_str = cpu_model;
803 env->version = def->iu_version;
804 env->fsr = def->fpu_version;
805 env->nwindows = def->nwindows;
806 #if !defined(TARGET_SPARC64)
807 env->mmuregs[0] |= def->mmu_version;
808 cpu_sparc_set_id(env, 0);
809 env->mxccregs[7] |= def->mxcc_version;
810 #else
811 env->mmu_version = def->mmu_version;
812 env->maxtl = def->maxtl;
813 env->version |= def->maxtl << 8;
814 env->version |= def->nwindows - 1;
815 #endif
816 return 0;
819 static void cpu_sparc_close(CPUSPARCState *env)
821 free(env->def);
822 free(env);
825 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
827 CPUSPARCState *env;
829 env = qemu_mallocz(sizeof(CPUSPARCState));
830 cpu_exec_init(env);
832 gen_intermediate_code_init(env);
834 if (cpu_sparc_register(env, cpu_model) < 0) {
835 cpu_sparc_close(env);
836 return NULL;
838 qemu_init_vcpu(env);
840 return env;
843 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
845 #if !defined(TARGET_SPARC64)
846 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
847 #endif
850 static const sparc_def_t sparc_defs[] = {
851 #ifdef TARGET_SPARC64
853 .name = "Fujitsu Sparc64",
854 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
855 .fpu_version = 0x00000000,
856 .mmu_version = mmu_us_12,
857 .nwindows = 4,
858 .maxtl = 4,
859 .features = CPU_DEFAULT_FEATURES,
862 .name = "Fujitsu Sparc64 III",
863 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
864 .fpu_version = 0x00000000,
865 .mmu_version = mmu_us_12,
866 .nwindows = 5,
867 .maxtl = 4,
868 .features = CPU_DEFAULT_FEATURES,
871 .name = "Fujitsu Sparc64 IV",
872 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
873 .fpu_version = 0x00000000,
874 .mmu_version = mmu_us_12,
875 .nwindows = 8,
876 .maxtl = 5,
877 .features = CPU_DEFAULT_FEATURES,
880 .name = "Fujitsu Sparc64 V",
881 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
882 .fpu_version = 0x00000000,
883 .mmu_version = mmu_us_12,
884 .nwindows = 8,
885 .maxtl = 5,
886 .features = CPU_DEFAULT_FEATURES,
889 .name = "TI UltraSparc I",
890 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
891 .fpu_version = 0x00000000,
892 .mmu_version = mmu_us_12,
893 .nwindows = 8,
894 .maxtl = 5,
895 .features = CPU_DEFAULT_FEATURES,
898 .name = "TI UltraSparc II",
899 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
900 .fpu_version = 0x00000000,
901 .mmu_version = mmu_us_12,
902 .nwindows = 8,
903 .maxtl = 5,
904 .features = CPU_DEFAULT_FEATURES,
907 .name = "TI UltraSparc IIi",
908 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
909 .fpu_version = 0x00000000,
910 .mmu_version = mmu_us_12,
911 .nwindows = 8,
912 .maxtl = 5,
913 .features = CPU_DEFAULT_FEATURES,
916 .name = "TI UltraSparc IIe",
917 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
918 .fpu_version = 0x00000000,
919 .mmu_version = mmu_us_12,
920 .nwindows = 8,
921 .maxtl = 5,
922 .features = CPU_DEFAULT_FEATURES,
925 .name = "Sun UltraSparc III",
926 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
927 .fpu_version = 0x00000000,
928 .mmu_version = mmu_us_12,
929 .nwindows = 8,
930 .maxtl = 5,
931 .features = CPU_DEFAULT_FEATURES,
934 .name = "Sun UltraSparc III Cu",
935 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
936 .fpu_version = 0x00000000,
937 .mmu_version = mmu_us_3,
938 .nwindows = 8,
939 .maxtl = 5,
940 .features = CPU_DEFAULT_FEATURES,
943 .name = "Sun UltraSparc IIIi",
944 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
945 .fpu_version = 0x00000000,
946 .mmu_version = mmu_us_12,
947 .nwindows = 8,
948 .maxtl = 5,
949 .features = CPU_DEFAULT_FEATURES,
952 .name = "Sun UltraSparc IV",
953 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
954 .fpu_version = 0x00000000,
955 .mmu_version = mmu_us_4,
956 .nwindows = 8,
957 .maxtl = 5,
958 .features = CPU_DEFAULT_FEATURES,
961 .name = "Sun UltraSparc IV+",
962 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
963 .fpu_version = 0x00000000,
964 .mmu_version = mmu_us_12,
965 .nwindows = 8,
966 .maxtl = 5,
967 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
970 .name = "Sun UltraSparc IIIi+",
971 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
972 .fpu_version = 0x00000000,
973 .mmu_version = mmu_us_3,
974 .nwindows = 8,
975 .maxtl = 5,
976 .features = CPU_DEFAULT_FEATURES,
979 .name = "Sun UltraSparc T1",
980 // defined in sparc_ifu_fdp.v and ctu.h
981 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
982 .fpu_version = 0x00000000,
983 .mmu_version = mmu_sun4v,
984 .nwindows = 8,
985 .maxtl = 6,
986 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
987 | CPU_FEATURE_GL,
990 .name = "Sun UltraSparc T2",
991 // defined in tlu_asi_ctl.v and n2_revid_cust.v
992 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
993 .fpu_version = 0x00000000,
994 .mmu_version = mmu_sun4v,
995 .nwindows = 8,
996 .maxtl = 6,
997 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
998 | CPU_FEATURE_GL,
1001 .name = "NEC UltraSparc I",
1002 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1003 .fpu_version = 0x00000000,
1004 .mmu_version = mmu_us_12,
1005 .nwindows = 8,
1006 .maxtl = 5,
1007 .features = CPU_DEFAULT_FEATURES,
1009 #else
1011 .name = "Fujitsu MB86900",
1012 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1013 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1014 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1015 .mmu_bm = 0x00004000,
1016 .mmu_ctpr_mask = 0x007ffff0,
1017 .mmu_cxr_mask = 0x0000003f,
1018 .mmu_sfsr_mask = 0xffffffff,
1019 .mmu_trcr_mask = 0xffffffff,
1020 .nwindows = 7,
1021 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1024 .name = "Fujitsu MB86904",
1025 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1026 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1027 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1028 .mmu_bm = 0x00004000,
1029 .mmu_ctpr_mask = 0x00ffffc0,
1030 .mmu_cxr_mask = 0x000000ff,
1031 .mmu_sfsr_mask = 0x00016fff,
1032 .mmu_trcr_mask = 0x00ffffff,
1033 .nwindows = 8,
1034 .features = CPU_DEFAULT_FEATURES,
1037 .name = "Fujitsu MB86907",
1038 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1039 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1040 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1041 .mmu_bm = 0x00004000,
1042 .mmu_ctpr_mask = 0xffffffc0,
1043 .mmu_cxr_mask = 0x000000ff,
1044 .mmu_sfsr_mask = 0x00016fff,
1045 .mmu_trcr_mask = 0xffffffff,
1046 .nwindows = 8,
1047 .features = CPU_DEFAULT_FEATURES,
1050 .name = "LSI L64811",
1051 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1052 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1053 .mmu_version = 0x10 << 24,
1054 .mmu_bm = 0x00004000,
1055 .mmu_ctpr_mask = 0x007ffff0,
1056 .mmu_cxr_mask = 0x0000003f,
1057 .mmu_sfsr_mask = 0xffffffff,
1058 .mmu_trcr_mask = 0xffffffff,
1059 .nwindows = 8,
1060 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1061 CPU_FEATURE_FSMULD,
1064 .name = "Cypress CY7C601",
1065 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1066 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1067 .mmu_version = 0x10 << 24,
1068 .mmu_bm = 0x00004000,
1069 .mmu_ctpr_mask = 0x007ffff0,
1070 .mmu_cxr_mask = 0x0000003f,
1071 .mmu_sfsr_mask = 0xffffffff,
1072 .mmu_trcr_mask = 0xffffffff,
1073 .nwindows = 8,
1074 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1075 CPU_FEATURE_FSMULD,
1078 .name = "Cypress CY7C611",
1079 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1080 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1081 .mmu_version = 0x10 << 24,
1082 .mmu_bm = 0x00004000,
1083 .mmu_ctpr_mask = 0x007ffff0,
1084 .mmu_cxr_mask = 0x0000003f,
1085 .mmu_sfsr_mask = 0xffffffff,
1086 .mmu_trcr_mask = 0xffffffff,
1087 .nwindows = 8,
1088 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1089 CPU_FEATURE_FSMULD,
1092 .name = "TI MicroSparc I",
1093 .iu_version = 0x41000000,
1094 .fpu_version = 4 << 17,
1095 .mmu_version = 0x41000000,
1096 .mmu_bm = 0x00004000,
1097 .mmu_ctpr_mask = 0x007ffff0,
1098 .mmu_cxr_mask = 0x0000003f,
1099 .mmu_sfsr_mask = 0x00016fff,
1100 .mmu_trcr_mask = 0x0000003f,
1101 .nwindows = 7,
1102 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1103 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1104 CPU_FEATURE_FMUL,
1107 .name = "TI MicroSparc II",
1108 .iu_version = 0x42000000,
1109 .fpu_version = 4 << 17,
1110 .mmu_version = 0x02000000,
1111 .mmu_bm = 0x00004000,
1112 .mmu_ctpr_mask = 0x00ffffc0,
1113 .mmu_cxr_mask = 0x000000ff,
1114 .mmu_sfsr_mask = 0x00016fff,
1115 .mmu_trcr_mask = 0x00ffffff,
1116 .nwindows = 8,
1117 .features = CPU_DEFAULT_FEATURES,
1120 .name = "TI MicroSparc IIep",
1121 .iu_version = 0x42000000,
1122 .fpu_version = 4 << 17,
1123 .mmu_version = 0x04000000,
1124 .mmu_bm = 0x00004000,
1125 .mmu_ctpr_mask = 0x00ffffc0,
1126 .mmu_cxr_mask = 0x000000ff,
1127 .mmu_sfsr_mask = 0x00016bff,
1128 .mmu_trcr_mask = 0x00ffffff,
1129 .nwindows = 8,
1130 .features = CPU_DEFAULT_FEATURES,
1133 .name = "TI SuperSparc 40", // STP1020NPGA
1134 .iu_version = 0x41000000, // SuperSPARC 2.x
1135 .fpu_version = 0 << 17,
1136 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1137 .mmu_bm = 0x00002000,
1138 .mmu_ctpr_mask = 0xffffffc0,
1139 .mmu_cxr_mask = 0x0000ffff,
1140 .mmu_sfsr_mask = 0xffffffff,
1141 .mmu_trcr_mask = 0xffffffff,
1142 .nwindows = 8,
1143 .features = CPU_DEFAULT_FEATURES,
1146 .name = "TI SuperSparc 50", // STP1020PGA
1147 .iu_version = 0x40000000, // SuperSPARC 3.x
1148 .fpu_version = 0 << 17,
1149 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1150 .mmu_bm = 0x00002000,
1151 .mmu_ctpr_mask = 0xffffffc0,
1152 .mmu_cxr_mask = 0x0000ffff,
1153 .mmu_sfsr_mask = 0xffffffff,
1154 .mmu_trcr_mask = 0xffffffff,
1155 .nwindows = 8,
1156 .features = CPU_DEFAULT_FEATURES,
1159 .name = "TI SuperSparc 51",
1160 .iu_version = 0x40000000, // SuperSPARC 3.x
1161 .fpu_version = 0 << 17,
1162 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1163 .mmu_bm = 0x00002000,
1164 .mmu_ctpr_mask = 0xffffffc0,
1165 .mmu_cxr_mask = 0x0000ffff,
1166 .mmu_sfsr_mask = 0xffffffff,
1167 .mmu_trcr_mask = 0xffffffff,
1168 .mxcc_version = 0x00000104,
1169 .nwindows = 8,
1170 .features = CPU_DEFAULT_FEATURES,
1173 .name = "TI SuperSparc 60", // STP1020APGA
1174 .iu_version = 0x40000000, // SuperSPARC 3.x
1175 .fpu_version = 0 << 17,
1176 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1177 .mmu_bm = 0x00002000,
1178 .mmu_ctpr_mask = 0xffffffc0,
1179 .mmu_cxr_mask = 0x0000ffff,
1180 .mmu_sfsr_mask = 0xffffffff,
1181 .mmu_trcr_mask = 0xffffffff,
1182 .nwindows = 8,
1183 .features = CPU_DEFAULT_FEATURES,
1186 .name = "TI SuperSparc 61",
1187 .iu_version = 0x44000000, // SuperSPARC 3.x
1188 .fpu_version = 0 << 17,
1189 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1190 .mmu_bm = 0x00002000,
1191 .mmu_ctpr_mask = 0xffffffc0,
1192 .mmu_cxr_mask = 0x0000ffff,
1193 .mmu_sfsr_mask = 0xffffffff,
1194 .mmu_trcr_mask = 0xffffffff,
1195 .mxcc_version = 0x00000104,
1196 .nwindows = 8,
1197 .features = CPU_DEFAULT_FEATURES,
1200 .name = "TI SuperSparc II",
1201 .iu_version = 0x40000000, // SuperSPARC II 1.x
1202 .fpu_version = 0 << 17,
1203 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1204 .mmu_bm = 0x00002000,
1205 .mmu_ctpr_mask = 0xffffffc0,
1206 .mmu_cxr_mask = 0x0000ffff,
1207 .mmu_sfsr_mask = 0xffffffff,
1208 .mmu_trcr_mask = 0xffffffff,
1209 .mxcc_version = 0x00000104,
1210 .nwindows = 8,
1211 .features = CPU_DEFAULT_FEATURES,
1214 .name = "Ross RT625",
1215 .iu_version = 0x1e000000,
1216 .fpu_version = 1 << 17,
1217 .mmu_version = 0x1e000000,
1218 .mmu_bm = 0x00004000,
1219 .mmu_ctpr_mask = 0x007ffff0,
1220 .mmu_cxr_mask = 0x0000003f,
1221 .mmu_sfsr_mask = 0xffffffff,
1222 .mmu_trcr_mask = 0xffffffff,
1223 .nwindows = 8,
1224 .features = CPU_DEFAULT_FEATURES,
1227 .name = "Ross RT620",
1228 .iu_version = 0x1f000000,
1229 .fpu_version = 1 << 17,
1230 .mmu_version = 0x1f000000,
1231 .mmu_bm = 0x00004000,
1232 .mmu_ctpr_mask = 0x007ffff0,
1233 .mmu_cxr_mask = 0x0000003f,
1234 .mmu_sfsr_mask = 0xffffffff,
1235 .mmu_trcr_mask = 0xffffffff,
1236 .nwindows = 8,
1237 .features = CPU_DEFAULT_FEATURES,
1240 .name = "BIT B5010",
1241 .iu_version = 0x20000000,
1242 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1243 .mmu_version = 0x20000000,
1244 .mmu_bm = 0x00004000,
1245 .mmu_ctpr_mask = 0x007ffff0,
1246 .mmu_cxr_mask = 0x0000003f,
1247 .mmu_sfsr_mask = 0xffffffff,
1248 .mmu_trcr_mask = 0xffffffff,
1249 .nwindows = 8,
1250 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1251 CPU_FEATURE_FSMULD,
1254 .name = "Matsushita MN10501",
1255 .iu_version = 0x50000000,
1256 .fpu_version = 0 << 17,
1257 .mmu_version = 0x50000000,
1258 .mmu_bm = 0x00004000,
1259 .mmu_ctpr_mask = 0x007ffff0,
1260 .mmu_cxr_mask = 0x0000003f,
1261 .mmu_sfsr_mask = 0xffffffff,
1262 .mmu_trcr_mask = 0xffffffff,
1263 .nwindows = 8,
1264 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1265 CPU_FEATURE_FSMULD,
1268 .name = "Weitek W8601",
1269 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1270 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1271 .mmu_version = 0x10 << 24,
1272 .mmu_bm = 0x00004000,
1273 .mmu_ctpr_mask = 0x007ffff0,
1274 .mmu_cxr_mask = 0x0000003f,
1275 .mmu_sfsr_mask = 0xffffffff,
1276 .mmu_trcr_mask = 0xffffffff,
1277 .nwindows = 8,
1278 .features = CPU_DEFAULT_FEATURES,
1281 .name = "LEON2",
1282 .iu_version = 0xf2000000,
1283 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1284 .mmu_version = 0xf2000000,
1285 .mmu_bm = 0x00004000,
1286 .mmu_ctpr_mask = 0x007ffff0,
1287 .mmu_cxr_mask = 0x0000003f,
1288 .mmu_sfsr_mask = 0xffffffff,
1289 .mmu_trcr_mask = 0xffffffff,
1290 .nwindows = 8,
1291 .features = CPU_DEFAULT_FEATURES,
1294 .name = "LEON3",
1295 .iu_version = 0xf3000000,
1296 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1297 .mmu_version = 0xf3000000,
1298 .mmu_bm = 0x00004000,
1299 .mmu_ctpr_mask = 0x007ffff0,
1300 .mmu_cxr_mask = 0x0000003f,
1301 .mmu_sfsr_mask = 0xffffffff,
1302 .mmu_trcr_mask = 0xffffffff,
1303 .nwindows = 8,
1304 .features = CPU_DEFAULT_FEATURES,
1306 #endif
1309 static const char * const feature_name[] = {
1310 "float",
1311 "float128",
1312 "swap",
1313 "mul",
1314 "div",
1315 "flush",
1316 "fsqrt",
1317 "fmul",
1318 "vis1",
1319 "vis2",
1320 "fsmuld",
1321 "hypv",
1322 "cmt",
1323 "gl",
1326 static void print_features(FILE *f,
1327 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1328 uint32_t features, const char *prefix)
1330 unsigned int i;
1332 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1333 if (feature_name[i] && (features & (1 << i))) {
1334 if (prefix)
1335 (*cpu_fprintf)(f, "%s", prefix);
1336 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1340 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1342 unsigned int i;
1344 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1345 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1346 *features |= 1 << i;
1347 return;
1349 fprintf(stderr, "CPU feature %s not found\n", flagname);
1352 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1354 unsigned int i;
1355 const sparc_def_t *def = NULL;
1356 char *s = strdup(cpu_model);
1357 char *featurestr, *name = strtok(s, ",");
1358 uint32_t plus_features = 0;
1359 uint32_t minus_features = 0;
1360 uint64_t iu_version;
1361 uint32_t fpu_version, mmu_version, nwindows;
1363 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1364 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1365 def = &sparc_defs[i];
1368 if (!def)
1369 goto error;
1370 memcpy(cpu_def, def, sizeof(*def));
1372 featurestr = strtok(NULL, ",");
1373 while (featurestr) {
1374 char *val;
1376 if (featurestr[0] == '+') {
1377 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1378 } else if (featurestr[0] == '-') {
1379 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1380 } else if ((val = strchr(featurestr, '='))) {
1381 *val = 0; val++;
1382 if (!strcmp(featurestr, "iu_version")) {
1383 char *err;
1385 iu_version = strtoll(val, &err, 0);
1386 if (!*val || *err) {
1387 fprintf(stderr, "bad numerical value %s\n", val);
1388 goto error;
1390 cpu_def->iu_version = iu_version;
1391 #ifdef DEBUG_FEATURES
1392 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1393 #endif
1394 } else if (!strcmp(featurestr, "fpu_version")) {
1395 char *err;
1397 fpu_version = strtol(val, &err, 0);
1398 if (!*val || *err) {
1399 fprintf(stderr, "bad numerical value %s\n", val);
1400 goto error;
1402 cpu_def->fpu_version = fpu_version;
1403 #ifdef DEBUG_FEATURES
1404 fprintf(stderr, "fpu_version %x\n", fpu_version);
1405 #endif
1406 } else if (!strcmp(featurestr, "mmu_version")) {
1407 char *err;
1409 mmu_version = strtol(val, &err, 0);
1410 if (!*val || *err) {
1411 fprintf(stderr, "bad numerical value %s\n", val);
1412 goto error;
1414 cpu_def->mmu_version = mmu_version;
1415 #ifdef DEBUG_FEATURES
1416 fprintf(stderr, "mmu_version %x\n", mmu_version);
1417 #endif
1418 } else if (!strcmp(featurestr, "nwindows")) {
1419 char *err;
1421 nwindows = strtol(val, &err, 0);
1422 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1423 nwindows < MIN_NWINDOWS) {
1424 fprintf(stderr, "bad numerical value %s\n", val);
1425 goto error;
1427 cpu_def->nwindows = nwindows;
1428 #ifdef DEBUG_FEATURES
1429 fprintf(stderr, "nwindows %d\n", nwindows);
1430 #endif
1431 } else {
1432 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1433 goto error;
1435 } else {
1436 fprintf(stderr, "feature string `%s' not in format "
1437 "(+feature|-feature|feature=xyz)\n", featurestr);
1438 goto error;
1440 featurestr = strtok(NULL, ",");
1442 cpu_def->features |= plus_features;
1443 cpu_def->features &= ~minus_features;
1444 #ifdef DEBUG_FEATURES
1445 print_features(stderr, fprintf, cpu_def->features, NULL);
1446 #endif
1447 free(s);
1448 return 0;
1450 error:
1451 free(s);
1452 return -1;
1455 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1457 unsigned int i;
1459 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1460 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1461 sparc_defs[i].name,
1462 sparc_defs[i].iu_version,
1463 sparc_defs[i].fpu_version,
1464 sparc_defs[i].mmu_version,
1465 sparc_defs[i].nwindows);
1466 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1467 ~sparc_defs[i].features, "-");
1468 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1469 sparc_defs[i].features, "+");
1470 (*cpu_fprintf)(f, "\n");
1472 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1473 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1474 (*cpu_fprintf)(f, "\n");
1475 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1476 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1477 (*cpu_fprintf)(f, "\n");
1478 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1479 "fpu_version mmu_version nwindows\n");
1482 static void cpu_print_cc(FILE *f,
1483 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1484 uint32_t cc)
1486 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1487 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1488 cc & PSR_CARRY? 'C' : '-');
1491 #ifdef TARGET_SPARC64
1492 #define REGS_PER_LINE 4
1493 #else
1494 #define REGS_PER_LINE 8
1495 #endif
1497 void cpu_dump_state(CPUState *env, FILE *f,
1498 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1499 int flags)
1501 int i, x;
1503 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1504 env->npc);
1505 cpu_fprintf(f, "General Registers:\n");
1507 for (i = 0; i < 8; i++) {
1508 if (i % REGS_PER_LINE == 0) {
1509 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1511 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1512 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1513 cpu_fprintf(f, "\n");
1516 cpu_fprintf(f, "\nCurrent Register Window:\n");
1517 for (x = 0; x < 3; x++) {
1518 for (i = 0; i < 8; i++) {
1519 if (i % REGS_PER_LINE == 0) {
1520 cpu_fprintf(f, "%%%c%d-%d: ",
1521 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1522 i, i + REGS_PER_LINE - 1);
1524 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1525 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1526 cpu_fprintf(f, "\n");
1530 cpu_fprintf(f, "\nFloating Point Registers:\n");
1531 for (i = 0; i < TARGET_FPREGS; i++) {
1532 if ((i & 3) == 0)
1533 cpu_fprintf(f, "%%f%02d:", i);
1534 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1535 if ((i & 3) == 3)
1536 cpu_fprintf(f, "\n");
1538 #ifdef TARGET_SPARC64
1539 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1540 (unsigned)cpu_get_ccr(env));
1541 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1542 cpu_fprintf(f, " xcc: ");
1543 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1544 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1545 env->psrpil);
1546 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1547 "cleanwin: %d cwp: %d\n",
1548 env->cansave, env->canrestore, env->otherwin, env->wstate,
1549 env->cleanwin, env->nwindows - 1 - env->cwp);
1550 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1551 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1552 #else
1553 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1554 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1555 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1556 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1557 env->wim);
1558 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1559 env->fsr, env->y);
1560 #endif