SPARC64: split cpu_get_phys_page_debug() from cpu_get_phys_page_nofault()
[qemu.git] / target-sparc / helper.c
blobcb8d706f78abcbebc65fc21c9067819b2644798a
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>
25 #include "cpu.h"
26 #include "qemu-common.h"
28 //#define DEBUG_MMU
29 //#define DEBUG_FEATURES
31 #ifdef DEBUG_MMU
32 #define DPRINTF_MMU(fmt, ...) \
33 do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
34 #else
35 #define DPRINTF_MMU(fmt, ...) do {} while (0)
36 #endif
38 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
40 /* Sparc MMU emulation */
42 #if defined(CONFIG_USER_ONLY)
44 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
45 int mmu_idx, int is_softmmu)
47 if (rw & 2)
48 env1->exception_index = TT_TFAULT;
49 else
50 env1->exception_index = TT_DFAULT;
51 return 1;
54 #else
56 #ifndef TARGET_SPARC64
58 * Sparc V8 Reference MMU (SRMMU)
60 static const int access_table[8][8] = {
61 { 0, 0, 0, 0, 8, 0, 12, 12 },
62 { 0, 0, 0, 0, 8, 0, 0, 0 },
63 { 8, 8, 0, 0, 0, 8, 12, 12 },
64 { 8, 8, 0, 0, 0, 8, 0, 0 },
65 { 8, 0, 8, 0, 8, 8, 12, 12 },
66 { 8, 0, 8, 0, 8, 0, 8, 0 },
67 { 8, 8, 8, 0, 8, 8, 12, 12 },
68 { 8, 8, 8, 0, 8, 8, 8, 0 }
71 static const int perm_table[2][8] = {
73 PAGE_READ,
74 PAGE_READ | PAGE_WRITE,
75 PAGE_READ | PAGE_EXEC,
76 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
77 PAGE_EXEC,
78 PAGE_READ | PAGE_WRITE,
79 PAGE_READ | PAGE_EXEC,
80 PAGE_READ | PAGE_WRITE | PAGE_EXEC
83 PAGE_READ,
84 PAGE_READ | PAGE_WRITE,
85 PAGE_READ | PAGE_EXEC,
86 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
87 PAGE_EXEC,
88 PAGE_READ,
94 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
95 int *prot, int *access_index,
96 target_ulong address, int rw, int mmu_idx,
97 target_ulong *page_size)
99 int access_perms = 0;
100 target_phys_addr_t pde_ptr;
101 uint32_t pde;
102 int error_code = 0, is_dirty, is_user;
103 unsigned long page_offset;
105 is_user = mmu_idx == MMU_USER_IDX;
107 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
108 *page_size = TARGET_PAGE_SIZE;
109 // Boot mode: instruction fetches are taken from PROM
110 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
111 *physical = env->prom_addr | (address & 0x7ffffULL);
112 *prot = PAGE_READ | PAGE_EXEC;
113 return 0;
115 *physical = address;
116 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
117 return 0;
120 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
121 *physical = 0xffffffffffff0000ULL;
123 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
124 /* Context base + context number */
125 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
126 pde = ldl_phys(pde_ptr);
128 /* Ctx pde */
129 switch (pde & PTE_ENTRYTYPE_MASK) {
130 default:
131 case 0: /* Invalid */
132 return 1 << 2;
133 case 2: /* L0 PTE, maybe should not happen? */
134 case 3: /* Reserved */
135 return 4 << 2;
136 case 1: /* L0 PDE */
137 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
138 pde = ldl_phys(pde_ptr);
140 switch (pde & PTE_ENTRYTYPE_MASK) {
141 default:
142 case 0: /* Invalid */
143 return (1 << 8) | (1 << 2);
144 case 3: /* Reserved */
145 return (1 << 8) | (4 << 2);
146 case 1: /* L1 PDE */
147 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
148 pde = ldl_phys(pde_ptr);
150 switch (pde & PTE_ENTRYTYPE_MASK) {
151 default:
152 case 0: /* Invalid */
153 return (2 << 8) | (1 << 2);
154 case 3: /* Reserved */
155 return (2 << 8) | (4 << 2);
156 case 1: /* L2 PDE */
157 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
158 pde = ldl_phys(pde_ptr);
160 switch (pde & PTE_ENTRYTYPE_MASK) {
161 default:
162 case 0: /* Invalid */
163 return (3 << 8) | (1 << 2);
164 case 1: /* PDE, should not happen */
165 case 3: /* Reserved */
166 return (3 << 8) | (4 << 2);
167 case 2: /* L3 PTE */
168 page_offset = (address & TARGET_PAGE_MASK) &
169 (TARGET_PAGE_SIZE - 1);
171 *page_size = TARGET_PAGE_SIZE;
172 break;
173 case 2: /* L2 PTE */
174 page_offset = address & 0x3ffff;
175 *page_size = 0x40000;
177 break;
178 case 2: /* L1 PTE */
179 page_offset = address & 0xffffff;
180 *page_size = 0x1000000;
184 /* check access */
185 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
186 error_code = access_table[*access_index][access_perms];
187 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
188 return error_code;
190 /* update page modified and dirty bits */
191 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
192 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
193 pde |= PG_ACCESSED_MASK;
194 if (is_dirty)
195 pde |= PG_MODIFIED_MASK;
196 stl_phys_notdirty(pde_ptr, pde);
199 /* the page can be put in the TLB */
200 *prot = perm_table[is_user][access_perms];
201 if (!(pde & PG_MODIFIED_MASK)) {
202 /* only set write access if already dirty... otherwise wait
203 for dirty access */
204 *prot &= ~PAGE_WRITE;
207 /* Even if large ptes, we map only one 4KB page in the cache to
208 avoid filling it too fast */
209 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
210 return error_code;
213 /* Perform address translation */
214 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
215 int mmu_idx, int is_softmmu)
217 target_phys_addr_t paddr;
218 target_ulong vaddr;
219 target_ulong page_size;
220 int error_code = 0, prot, access_index;
222 error_code = get_physical_address(env, &paddr, &prot, &access_index,
223 address, rw, mmu_idx, &page_size);
224 if (error_code == 0) {
225 vaddr = address & TARGET_PAGE_MASK;
226 paddr &= TARGET_PAGE_MASK;
227 #ifdef DEBUG_MMU
228 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
229 TARGET_FMT_lx "\n", address, paddr, vaddr);
230 #endif
231 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
232 return 0;
235 if (env->mmuregs[3]) /* Fault status register */
236 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
237 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
238 env->mmuregs[4] = address; /* Fault address register */
240 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
241 // No fault mode: if a mapping is available, just override
242 // permissions. If no mapping is available, redirect accesses to
243 // neverland. Fake/overridden mappings will be flushed when
244 // switching to normal mode.
245 vaddr = address & TARGET_PAGE_MASK;
246 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
247 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
248 return 0;
249 } else {
250 if (rw & 2)
251 env->exception_index = TT_TFAULT;
252 else
253 env->exception_index = TT_DFAULT;
254 return 1;
258 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
260 target_phys_addr_t pde_ptr;
261 uint32_t pde;
263 /* Context base + context number */
264 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
265 (env->mmuregs[2] << 2);
266 pde = ldl_phys(pde_ptr);
268 switch (pde & PTE_ENTRYTYPE_MASK) {
269 default:
270 case 0: /* Invalid */
271 case 2: /* PTE, maybe should not happen? */
272 case 3: /* Reserved */
273 return 0;
274 case 1: /* L1 PDE */
275 if (mmulev == 3)
276 return pde;
277 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
278 pde = ldl_phys(pde_ptr);
280 switch (pde & PTE_ENTRYTYPE_MASK) {
281 default:
282 case 0: /* Invalid */
283 case 3: /* Reserved */
284 return 0;
285 case 2: /* L1 PTE */
286 return pde;
287 case 1: /* L2 PDE */
288 if (mmulev == 2)
289 return pde;
290 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
291 pde = ldl_phys(pde_ptr);
293 switch (pde & PTE_ENTRYTYPE_MASK) {
294 default:
295 case 0: /* Invalid */
296 case 3: /* Reserved */
297 return 0;
298 case 2: /* L2 PTE */
299 return pde;
300 case 1: /* L3 PDE */
301 if (mmulev == 1)
302 return pde;
303 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
304 pde = ldl_phys(pde_ptr);
306 switch (pde & PTE_ENTRYTYPE_MASK) {
307 default:
308 case 0: /* Invalid */
309 case 1: /* PDE, should not happen */
310 case 3: /* Reserved */
311 return 0;
312 case 2: /* L3 PTE */
313 return pde;
318 return 0;
321 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
323 target_ulong va, va1, va2;
324 unsigned int n, m, o;
325 target_phys_addr_t pde_ptr, pa;
326 uint32_t pde;
328 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
329 pde = ldl_phys(pde_ptr);
330 (*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
331 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
332 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
333 pde = mmu_probe(env, va, 2);
334 if (pde) {
335 pa = cpu_get_phys_page_debug(env, va);
336 (*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
337 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
338 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
339 pde = mmu_probe(env, va1, 1);
340 if (pde) {
341 pa = cpu_get_phys_page_debug(env, va1);
342 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
343 TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
344 va1, pa, pde);
345 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
346 pde = mmu_probe(env, va2, 0);
347 if (pde) {
348 pa = cpu_get_phys_page_debug(env, va2);
349 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
350 TARGET_FMT_plx " PTE: "
351 TARGET_FMT_lx "\n",
352 va2, pa, pde);
361 #else /* !TARGET_SPARC64 */
363 // 41 bit physical address space
364 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
366 return x & 0x1ffffffffffULL;
370 * UltraSparc IIi I/DMMUs
373 // Returns true if TTE tag is valid and matches virtual address value in context
374 // requires virtual address mask value calculated from TTE entry size
375 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
376 uint64_t address, uint64_t context,
377 target_phys_addr_t *physical)
379 uint64_t mask;
381 switch (TTE_PGSIZE(tlb->tte)) {
382 default:
383 case 0x0: // 8k
384 mask = 0xffffffffffffe000ULL;
385 break;
386 case 0x1: // 64k
387 mask = 0xffffffffffff0000ULL;
388 break;
389 case 0x2: // 512k
390 mask = 0xfffffffffff80000ULL;
391 break;
392 case 0x3: // 4M
393 mask = 0xffffffffffc00000ULL;
394 break;
397 // valid, context match, virtual address match?
398 if (TTE_IS_VALID(tlb->tte) &&
399 (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
400 && compare_masked(address, tlb->tag, mask))
402 // decode physical address
403 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
404 return 1;
407 return 0;
410 static int get_physical_address_data(CPUState *env,
411 target_phys_addr_t *physical, int *prot,
412 target_ulong address, int rw, int mmu_idx)
414 unsigned int i;
415 uint64_t context;
416 uint64_t sfsr = 0;
418 int is_user = (mmu_idx == MMU_USER_IDX ||
419 mmu_idx == MMU_USER_SECONDARY_IDX);
421 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
422 *physical = ultrasparc_truncate_physical(address);
423 *prot = PAGE_READ | PAGE_WRITE;
424 return 0;
427 switch(mmu_idx) {
428 case MMU_USER_IDX:
429 case MMU_KERNEL_IDX:
430 context = env->dmmu.mmu_primary_context & 0x1fff;
431 sfsr |= SFSR_CT_PRIMARY;
432 break;
433 case MMU_USER_SECONDARY_IDX:
434 case MMU_KERNEL_SECONDARY_IDX:
435 context = env->dmmu.mmu_secondary_context & 0x1fff;
436 sfsr |= SFSR_CT_SECONDARY;
437 break;
438 case MMU_NUCLEUS_IDX:
439 sfsr |= SFSR_CT_NUCLEUS;
440 /* FALLTHRU */
441 default:
442 context = 0;
443 break;
446 if (rw == 1) {
447 sfsr |= SFSR_WRITE_BIT;
450 for (i = 0; i < 64; i++) {
451 // ctx match, vaddr match, valid?
452 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
454 // access ok?
455 if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
456 sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
457 env->exception_index = TT_DFAULT;
459 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
460 " mmu_idx=%d tl=%d\n",
461 address, context, mmu_idx, env->tl);
462 } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
463 env->exception_index = TT_DPROT;
465 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
466 " mmu_idx=%d tl=%d\n",
467 address, context, mmu_idx, env->tl);
468 } else {
469 *prot = PAGE_READ;
470 if (TTE_IS_W_OK(env->dtlb[i].tte)) {
471 *prot |= PAGE_WRITE;
474 TTE_SET_USED(env->dtlb[i].tte);
476 return 0;
479 if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
480 sfsr |= SFSR_OW_BIT; /* overflow (not read before
481 another fault) */
484 if (env->pstate & PS_PRIV) {
485 sfsr |= SFSR_PR_BIT;
488 /* FIXME: ASI field in SFSR must be set */
489 env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
491 env->dmmu.sfar = address; /* Fault address register */
493 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
495 return 1;
499 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
500 address, context);
503 * On MMU misses:
504 * - UltraSPARC IIi: SFSR and SFAR unmodified
505 * - JPS1: SFAR updated and some fields of SFSR updated
507 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
508 env->exception_index = TT_DMISS;
509 return 1;
512 static int get_physical_address_code(CPUState *env,
513 target_phys_addr_t *physical, int *prot,
514 target_ulong address, int mmu_idx)
516 unsigned int i;
517 uint64_t context;
519 int is_user = (mmu_idx == MMU_USER_IDX ||
520 mmu_idx == MMU_USER_SECONDARY_IDX);
522 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
523 /* IMMU disabled */
524 *physical = ultrasparc_truncate_physical(address);
525 *prot = PAGE_EXEC;
526 return 0;
529 if (env->tl == 0) {
530 /* PRIMARY context */
531 context = env->dmmu.mmu_primary_context & 0x1fff;
532 } else {
533 /* NUCLEUS context */
534 context = 0;
537 for (i = 0; i < 64; i++) {
538 // ctx match, vaddr match, valid?
539 if (ultrasparc_tag_match(&env->itlb[i],
540 address, context, physical)) {
541 // access ok?
542 if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
543 /* Fault status register */
544 if (env->immu.sfsr & SFSR_VALID_BIT) {
545 env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
546 another fault) */
547 } else {
548 env->immu.sfsr = 0;
550 if (env->pstate & PS_PRIV) {
551 env->immu.sfsr |= SFSR_PR_BIT;
553 if (env->tl > 0) {
554 env->immu.sfsr |= SFSR_CT_NUCLEUS;
557 /* FIXME: ASI field in SFSR must be set */
558 env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
559 env->exception_index = TT_TFAULT;
561 env->immu.tag_access = (address & ~0x1fffULL) | context;
563 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
564 address, context);
566 return 1;
568 *prot = PAGE_EXEC;
569 TTE_SET_USED(env->itlb[i].tte);
570 return 0;
574 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
575 address, context);
577 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
578 env->immu.tag_access = (address & ~0x1fffULL) | context;
579 env->exception_index = TT_TMISS;
580 return 1;
583 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
584 int *prot, int *access_index,
585 target_ulong address, int rw, int mmu_idx,
586 target_ulong *page_size)
588 /* ??? We treat everything as a small page, then explicitly flush
589 everything when an entry is evicted. */
590 *page_size = TARGET_PAGE_SIZE;
592 #if defined (DEBUG_MMU)
593 /* safety net to catch wrong softmmu index use from dynamic code */
594 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
595 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
596 " primary context=%" PRIx64
597 " secondary context=%" PRIx64
598 " address=%" PRIx64
599 "\n",
600 (rw == 2 ? "CODE" : "DATA"),
601 env->tl, mmu_idx,
602 env->dmmu.mmu_primary_context,
603 env->dmmu.mmu_secondary_context,
604 address);
606 #endif
608 if (rw == 2)
609 return get_physical_address_code(env, physical, prot, address,
610 mmu_idx);
611 else
612 return get_physical_address_data(env, physical, prot, address, rw,
613 mmu_idx);
616 /* Perform address translation */
617 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
618 int mmu_idx, int is_softmmu)
620 target_ulong virt_addr, vaddr;
621 target_phys_addr_t paddr;
622 target_ulong page_size;
623 int error_code = 0, prot, access_index;
625 error_code = get_physical_address(env, &paddr, &prot, &access_index,
626 address, rw, mmu_idx, &page_size);
627 if (error_code == 0) {
628 virt_addr = address & TARGET_PAGE_MASK;
629 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
630 (TARGET_PAGE_SIZE - 1));
632 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
633 " vaddr %" PRIx64
634 " mmu_idx=%d"
635 " tl=%d"
636 " primary context=%" PRIx64
637 " secondary context=%" PRIx64
638 "\n",
639 address, paddr, vaddr, mmu_idx, env->tl,
640 env->dmmu.mmu_primary_context,
641 env->dmmu.mmu_secondary_context);
643 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
644 return 0;
646 // XXX
647 return 1;
650 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
652 unsigned int i;
653 const char *mask;
655 (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
656 PRId64 "\n",
657 env->dmmu.mmu_primary_context,
658 env->dmmu.mmu_secondary_context);
659 if ((env->lsu & DMMU_E) == 0) {
660 (*cpu_fprintf)(f, "DMMU disabled\n");
661 } else {
662 (*cpu_fprintf)(f, "DMMU dump\n");
663 for (i = 0; i < 64; i++) {
664 switch (TTE_PGSIZE(env->dtlb[i].tte)) {
665 default:
666 case 0x0:
667 mask = " 8k";
668 break;
669 case 0x1:
670 mask = " 64k";
671 break;
672 case 0x2:
673 mask = "512k";
674 break;
675 case 0x3:
676 mask = " 4M";
677 break;
679 if (TTE_IS_VALID(env->dtlb[i].tte)) {
680 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
681 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
683 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
684 TTE_PA(env->dtlb[i].tte),
685 mask,
686 TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user",
687 TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO",
688 TTE_IS_LOCKED(env->dtlb[i].tte) ?
689 "locked" : "unlocked",
690 env->dtlb[i].tag & (uint64_t)0x1fffULL,
691 TTE_IS_GLOBAL(env->dtlb[i].tte)?
692 "global" : "local");
696 if ((env->lsu & IMMU_E) == 0) {
697 (*cpu_fprintf)(f, "IMMU disabled\n");
698 } else {
699 (*cpu_fprintf)(f, "IMMU dump\n");
700 for (i = 0; i < 64; i++) {
701 switch (TTE_PGSIZE(env->itlb[i].tte)) {
702 default:
703 case 0x0:
704 mask = " 8k";
705 break;
706 case 0x1:
707 mask = " 64k";
708 break;
709 case 0x2:
710 mask = "512k";
711 break;
712 case 0x3:
713 mask = " 4M";
714 break;
716 if (TTE_IS_VALID(env->itlb[i].tte)) {
717 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
718 ", %s, %s, %s, ctx %" PRId64 " %s\n",
720 env->itlb[i].tag & (uint64_t)~0x1fffULL,
721 TTE_PA(env->itlb[i].tte),
722 mask,
723 TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user",
724 TTE_IS_LOCKED(env->itlb[i].tte) ?
725 "locked" : "unlocked",
726 env->itlb[i].tag & (uint64_t)0x1fffULL,
727 TTE_IS_GLOBAL(env->itlb[i].tte)?
728 "global" : "local");
734 #endif /* TARGET_SPARC64 */
735 #endif /* !CONFIG_USER_ONLY */
738 #if !defined(CONFIG_USER_ONLY)
739 static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
740 target_ulong addr, int rw, int mmu_idx)
742 target_ulong page_size;
743 int prot, access_index;
745 return get_physical_address(env, phys, &prot, &access_index, addr, rw,
746 mmu_idx, &page_size);
749 #if defined(TARGET_SPARC64)
750 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
751 int mmu_idx)
753 target_phys_addr_t phys_addr;
755 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
756 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
757 return -1;
760 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
761 return -1;
762 return phys_addr;
764 #endif
766 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
768 target_phys_addr_t phys_addr;
769 int mmu_idx = cpu_mmu_index(env);
771 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
772 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
773 return -1;
776 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) {
777 return -1;
779 return phys_addr;
781 #endif
783 #ifdef TARGET_SPARC64
784 #ifdef DEBUG_PCALL
785 static const char * const excp_names[0x80] = {
786 [TT_TFAULT] = "Instruction Access Fault",
787 [TT_TMISS] = "Instruction Access MMU Miss",
788 [TT_CODE_ACCESS] = "Instruction Access Error",
789 [TT_ILL_INSN] = "Illegal Instruction",
790 [TT_PRIV_INSN] = "Privileged Instruction",
791 [TT_NFPU_INSN] = "FPU Disabled",
792 [TT_FP_EXCP] = "FPU Exception",
793 [TT_TOVF] = "Tag Overflow",
794 [TT_CLRWIN] = "Clean Windows",
795 [TT_DIV_ZERO] = "Division By Zero",
796 [TT_DFAULT] = "Data Access Fault",
797 [TT_DMISS] = "Data Access MMU Miss",
798 [TT_DATA_ACCESS] = "Data Access Error",
799 [TT_DPROT] = "Data Protection Error",
800 [TT_UNALIGNED] = "Unaligned Memory Access",
801 [TT_PRIV_ACT] = "Privileged Action",
802 [TT_EXTINT | 0x1] = "External Interrupt 1",
803 [TT_EXTINT | 0x2] = "External Interrupt 2",
804 [TT_EXTINT | 0x3] = "External Interrupt 3",
805 [TT_EXTINT | 0x4] = "External Interrupt 4",
806 [TT_EXTINT | 0x5] = "External Interrupt 5",
807 [TT_EXTINT | 0x6] = "External Interrupt 6",
808 [TT_EXTINT | 0x7] = "External Interrupt 7",
809 [TT_EXTINT | 0x8] = "External Interrupt 8",
810 [TT_EXTINT | 0x9] = "External Interrupt 9",
811 [TT_EXTINT | 0xa] = "External Interrupt 10",
812 [TT_EXTINT | 0xb] = "External Interrupt 11",
813 [TT_EXTINT | 0xc] = "External Interrupt 12",
814 [TT_EXTINT | 0xd] = "External Interrupt 13",
815 [TT_EXTINT | 0xe] = "External Interrupt 14",
816 [TT_EXTINT | 0xf] = "External Interrupt 15",
818 #endif
820 void do_interrupt(CPUState *env)
822 int intno = env->exception_index;
823 trap_state *tsptr;
825 #ifdef DEBUG_PCALL
826 if (qemu_loglevel_mask(CPU_LOG_INT)) {
827 static int count;
828 const char *name;
830 if (intno < 0 || intno >= 0x180) {
831 name = "Unknown";
832 } else if (intno >= 0x100) {
833 name = "Trap Instruction";
834 } else if (intno >= 0xc0) {
835 name = "Window Fill";
836 } else if (intno >= 0x80) {
837 name = "Window Spill";
838 } else {
839 name = excp_names[intno];
840 if (!name) {
841 name = "Unknown";
845 qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
846 " SP=%016" PRIx64 "\n",
847 count, name, intno,
848 env->pc,
849 env->npc, env->regwptr[6]);
850 log_cpu_state(env, 0);
851 #if 0
853 int i;
854 uint8_t *ptr;
856 qemu_log(" code=");
857 ptr = (uint8_t *)env->pc;
858 for (i = 0; i < 16; i++) {
859 qemu_log(" %02x", ldub(ptr + i));
861 qemu_log("\n");
863 #endif
864 count++;
866 #endif
867 #if !defined(CONFIG_USER_ONLY)
868 if (env->tl >= env->maxtl) {
869 cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
870 " Error state", env->exception_index, env->tl, env->maxtl);
871 return;
873 #endif
874 if (env->tl < env->maxtl - 1) {
875 env->tl++;
876 } else {
877 env->pstate |= PS_RED;
878 if (env->tl < env->maxtl) {
879 env->tl++;
882 tsptr = cpu_tsptr(env);
884 tsptr->tstate = (cpu_get_ccr(env) << 32) |
885 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
886 cpu_get_cwp64(env);
887 tsptr->tpc = env->pc;
888 tsptr->tnpc = env->npc;
889 tsptr->tt = intno;
891 switch (intno) {
892 case TT_IVEC:
893 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
894 break;
895 case TT_TFAULT:
896 case TT_DFAULT:
897 case TT_TMISS ... TT_TMISS + 3:
898 case TT_DMISS ... TT_DMISS + 3:
899 case TT_DPROT ... TT_DPROT + 3:
900 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
901 break;
902 default:
903 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
904 break;
907 if (intno == TT_CLRWIN) {
908 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
909 } else if ((intno & 0x1c0) == TT_SPILL) {
910 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
911 } else if ((intno & 0x1c0) == TT_FILL) {
912 cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
914 env->tbr &= ~0x7fffULL;
915 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
916 env->pc = env->tbr;
917 env->npc = env->pc + 4;
918 env->exception_index = -1;
920 #else
921 #ifdef DEBUG_PCALL
922 static const char * const excp_names[0x80] = {
923 [TT_TFAULT] = "Instruction Access Fault",
924 [TT_ILL_INSN] = "Illegal Instruction",
925 [TT_PRIV_INSN] = "Privileged Instruction",
926 [TT_NFPU_INSN] = "FPU Disabled",
927 [TT_WIN_OVF] = "Window Overflow",
928 [TT_WIN_UNF] = "Window Underflow",
929 [TT_UNALIGNED] = "Unaligned Memory Access",
930 [TT_FP_EXCP] = "FPU Exception",
931 [TT_DFAULT] = "Data Access Fault",
932 [TT_TOVF] = "Tag Overflow",
933 [TT_EXTINT | 0x1] = "External Interrupt 1",
934 [TT_EXTINT | 0x2] = "External Interrupt 2",
935 [TT_EXTINT | 0x3] = "External Interrupt 3",
936 [TT_EXTINT | 0x4] = "External Interrupt 4",
937 [TT_EXTINT | 0x5] = "External Interrupt 5",
938 [TT_EXTINT | 0x6] = "External Interrupt 6",
939 [TT_EXTINT | 0x7] = "External Interrupt 7",
940 [TT_EXTINT | 0x8] = "External Interrupt 8",
941 [TT_EXTINT | 0x9] = "External Interrupt 9",
942 [TT_EXTINT | 0xa] = "External Interrupt 10",
943 [TT_EXTINT | 0xb] = "External Interrupt 11",
944 [TT_EXTINT | 0xc] = "External Interrupt 12",
945 [TT_EXTINT | 0xd] = "External Interrupt 13",
946 [TT_EXTINT | 0xe] = "External Interrupt 14",
947 [TT_EXTINT | 0xf] = "External Interrupt 15",
948 [TT_TOVF] = "Tag Overflow",
949 [TT_CODE_ACCESS] = "Instruction Access Error",
950 [TT_DATA_ACCESS] = "Data Access Error",
951 [TT_DIV_ZERO] = "Division By Zero",
952 [TT_NCP_INSN] = "Coprocessor Disabled",
954 #endif
956 void do_interrupt(CPUState *env)
958 int cwp, intno = env->exception_index;
960 #ifdef DEBUG_PCALL
961 if (qemu_loglevel_mask(CPU_LOG_INT)) {
962 static int count;
963 const char *name;
965 if (intno < 0 || intno >= 0x100) {
966 name = "Unknown";
967 } else if (intno >= 0x80) {
968 name = "Trap Instruction";
969 } else {
970 name = excp_names[intno];
971 if (!name) {
972 name = "Unknown";
976 qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
977 count, name, intno,
978 env->pc,
979 env->npc, env->regwptr[6]);
980 log_cpu_state(env, 0);
981 #if 0
983 int i;
984 uint8_t *ptr;
986 qemu_log(" code=");
987 ptr = (uint8_t *)env->pc;
988 for (i = 0; i < 16; i++) {
989 qemu_log(" %02x", ldub(ptr + i));
991 qemu_log("\n");
993 #endif
994 count++;
996 #endif
997 #if !defined(CONFIG_USER_ONLY)
998 if (env->psret == 0) {
999 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
1000 env->exception_index);
1001 return;
1003 #endif
1004 env->psret = 0;
1005 cwp = cpu_cwp_dec(env, env->cwp - 1);
1006 cpu_set_cwp(env, cwp);
1007 env->regwptr[9] = env->pc;
1008 env->regwptr[10] = env->npc;
1009 env->psrps = env->psrs;
1010 env->psrs = 1;
1011 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1012 env->pc = env->tbr;
1013 env->npc = env->pc + 4;
1014 env->exception_index = -1;
1016 #if !defined(CONFIG_USER_ONLY)
1017 /* IRQ acknowledgment */
1018 if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
1019 env->qemu_irq_ack(env->irq_manager, intno);
1021 #endif
1023 #endif
1025 void cpu_reset(CPUSPARCState *env)
1027 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1028 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
1029 log_cpu_state(env, 0);
1032 tlb_flush(env, 1);
1033 env->cwp = 0;
1034 #ifndef TARGET_SPARC64
1035 env->wim = 1;
1036 #endif
1037 env->regwptr = env->regbase + (env->cwp * 16);
1038 CC_OP = CC_OP_FLAGS;
1039 #if defined(CONFIG_USER_ONLY)
1040 #ifdef TARGET_SPARC64
1041 env->cleanwin = env->nwindows - 2;
1042 env->cansave = env->nwindows - 2;
1043 env->pstate = PS_RMO | PS_PEF | PS_IE;
1044 env->asi = 0x82; // Primary no-fault
1045 #endif
1046 #else
1047 #if !defined(TARGET_SPARC64)
1048 env->psret = 0;
1049 env->psrs = 1;
1050 env->psrps = 1;
1051 #endif
1052 #ifdef TARGET_SPARC64
1053 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
1054 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
1055 env->tl = env->maxtl;
1056 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
1057 env->lsu = 0;
1058 #else
1059 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
1060 env->mmuregs[0] |= env->def->mmu_bm;
1061 #endif
1062 env->pc = 0;
1063 env->npc = env->pc + 4;
1064 #endif
1065 env->cache_control = 0;
1068 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
1070 sparc_def_t def1, *def = &def1;
1072 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
1073 return -1;
1075 env->def = qemu_mallocz(sizeof(*def));
1076 memcpy(env->def, def, sizeof(*def));
1077 #if defined(CONFIG_USER_ONLY)
1078 if ((env->def->features & CPU_FEATURE_FLOAT))
1079 env->def->features |= CPU_FEATURE_FLOAT128;
1080 #endif
1081 env->cpu_model_str = cpu_model;
1082 env->version = def->iu_version;
1083 env->fsr = def->fpu_version;
1084 env->nwindows = def->nwindows;
1085 #if !defined(TARGET_SPARC64)
1086 env->mmuregs[0] |= def->mmu_version;
1087 cpu_sparc_set_id(env, 0);
1088 env->mxccregs[7] |= def->mxcc_version;
1089 #else
1090 env->mmu_version = def->mmu_version;
1091 env->maxtl = def->maxtl;
1092 env->version |= def->maxtl << 8;
1093 env->version |= def->nwindows - 1;
1094 #endif
1095 return 0;
1098 static void cpu_sparc_close(CPUSPARCState *env)
1100 free(env->def);
1101 free(env);
1104 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
1106 CPUSPARCState *env;
1108 env = qemu_mallocz(sizeof(CPUSPARCState));
1109 cpu_exec_init(env);
1111 gen_intermediate_code_init(env);
1113 if (cpu_sparc_register(env, cpu_model) < 0) {
1114 cpu_sparc_close(env);
1115 return NULL;
1117 qemu_init_vcpu(env);
1119 return env;
1122 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
1124 #if !defined(TARGET_SPARC64)
1125 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
1126 #endif
1129 static const sparc_def_t sparc_defs[] = {
1130 #ifdef TARGET_SPARC64
1132 .name = "Fujitsu Sparc64",
1133 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
1134 .fpu_version = 0x00000000,
1135 .mmu_version = mmu_us_12,
1136 .nwindows = 4,
1137 .maxtl = 4,
1138 .features = CPU_DEFAULT_FEATURES,
1141 .name = "Fujitsu Sparc64 III",
1142 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
1143 .fpu_version = 0x00000000,
1144 .mmu_version = mmu_us_12,
1145 .nwindows = 5,
1146 .maxtl = 4,
1147 .features = CPU_DEFAULT_FEATURES,
1150 .name = "Fujitsu Sparc64 IV",
1151 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
1152 .fpu_version = 0x00000000,
1153 .mmu_version = mmu_us_12,
1154 .nwindows = 8,
1155 .maxtl = 5,
1156 .features = CPU_DEFAULT_FEATURES,
1159 .name = "Fujitsu Sparc64 V",
1160 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
1161 .fpu_version = 0x00000000,
1162 .mmu_version = mmu_us_12,
1163 .nwindows = 8,
1164 .maxtl = 5,
1165 .features = CPU_DEFAULT_FEATURES,
1168 .name = "TI UltraSparc I",
1169 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1170 .fpu_version = 0x00000000,
1171 .mmu_version = mmu_us_12,
1172 .nwindows = 8,
1173 .maxtl = 5,
1174 .features = CPU_DEFAULT_FEATURES,
1177 .name = "TI UltraSparc II",
1178 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
1179 .fpu_version = 0x00000000,
1180 .mmu_version = mmu_us_12,
1181 .nwindows = 8,
1182 .maxtl = 5,
1183 .features = CPU_DEFAULT_FEATURES,
1186 .name = "TI UltraSparc IIi",
1187 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
1188 .fpu_version = 0x00000000,
1189 .mmu_version = mmu_us_12,
1190 .nwindows = 8,
1191 .maxtl = 5,
1192 .features = CPU_DEFAULT_FEATURES,
1195 .name = "TI UltraSparc IIe",
1196 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
1197 .fpu_version = 0x00000000,
1198 .mmu_version = mmu_us_12,
1199 .nwindows = 8,
1200 .maxtl = 5,
1201 .features = CPU_DEFAULT_FEATURES,
1204 .name = "Sun UltraSparc III",
1205 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
1206 .fpu_version = 0x00000000,
1207 .mmu_version = mmu_us_12,
1208 .nwindows = 8,
1209 .maxtl = 5,
1210 .features = CPU_DEFAULT_FEATURES,
1213 .name = "Sun UltraSparc III Cu",
1214 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
1215 .fpu_version = 0x00000000,
1216 .mmu_version = mmu_us_3,
1217 .nwindows = 8,
1218 .maxtl = 5,
1219 .features = CPU_DEFAULT_FEATURES,
1222 .name = "Sun UltraSparc IIIi",
1223 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
1224 .fpu_version = 0x00000000,
1225 .mmu_version = mmu_us_12,
1226 .nwindows = 8,
1227 .maxtl = 5,
1228 .features = CPU_DEFAULT_FEATURES,
1231 .name = "Sun UltraSparc IV",
1232 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
1233 .fpu_version = 0x00000000,
1234 .mmu_version = mmu_us_4,
1235 .nwindows = 8,
1236 .maxtl = 5,
1237 .features = CPU_DEFAULT_FEATURES,
1240 .name = "Sun UltraSparc IV+",
1241 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
1242 .fpu_version = 0x00000000,
1243 .mmu_version = mmu_us_12,
1244 .nwindows = 8,
1245 .maxtl = 5,
1246 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
1249 .name = "Sun UltraSparc IIIi+",
1250 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
1251 .fpu_version = 0x00000000,
1252 .mmu_version = mmu_us_3,
1253 .nwindows = 8,
1254 .maxtl = 5,
1255 .features = CPU_DEFAULT_FEATURES,
1258 .name = "Sun UltraSparc T1",
1259 // defined in sparc_ifu_fdp.v and ctu.h
1260 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
1261 .fpu_version = 0x00000000,
1262 .mmu_version = mmu_sun4v,
1263 .nwindows = 8,
1264 .maxtl = 6,
1265 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1266 | CPU_FEATURE_GL,
1269 .name = "Sun UltraSparc T2",
1270 // defined in tlu_asi_ctl.v and n2_revid_cust.v
1271 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
1272 .fpu_version = 0x00000000,
1273 .mmu_version = mmu_sun4v,
1274 .nwindows = 8,
1275 .maxtl = 6,
1276 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1277 | CPU_FEATURE_GL,
1280 .name = "NEC UltraSparc I",
1281 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1282 .fpu_version = 0x00000000,
1283 .mmu_version = mmu_us_12,
1284 .nwindows = 8,
1285 .maxtl = 5,
1286 .features = CPU_DEFAULT_FEATURES,
1288 #else
1290 .name = "Fujitsu MB86900",
1291 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1292 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1293 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1294 .mmu_bm = 0x00004000,
1295 .mmu_ctpr_mask = 0x007ffff0,
1296 .mmu_cxr_mask = 0x0000003f,
1297 .mmu_sfsr_mask = 0xffffffff,
1298 .mmu_trcr_mask = 0xffffffff,
1299 .nwindows = 7,
1300 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1303 .name = "Fujitsu MB86904",
1304 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1305 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1306 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1307 .mmu_bm = 0x00004000,
1308 .mmu_ctpr_mask = 0x00ffffc0,
1309 .mmu_cxr_mask = 0x000000ff,
1310 .mmu_sfsr_mask = 0x00016fff,
1311 .mmu_trcr_mask = 0x00ffffff,
1312 .nwindows = 8,
1313 .features = CPU_DEFAULT_FEATURES,
1316 .name = "Fujitsu MB86907",
1317 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1318 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1319 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1320 .mmu_bm = 0x00004000,
1321 .mmu_ctpr_mask = 0xffffffc0,
1322 .mmu_cxr_mask = 0x000000ff,
1323 .mmu_sfsr_mask = 0x00016fff,
1324 .mmu_trcr_mask = 0xffffffff,
1325 .nwindows = 8,
1326 .features = CPU_DEFAULT_FEATURES,
1329 .name = "LSI L64811",
1330 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1331 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1332 .mmu_version = 0x10 << 24,
1333 .mmu_bm = 0x00004000,
1334 .mmu_ctpr_mask = 0x007ffff0,
1335 .mmu_cxr_mask = 0x0000003f,
1336 .mmu_sfsr_mask = 0xffffffff,
1337 .mmu_trcr_mask = 0xffffffff,
1338 .nwindows = 8,
1339 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1340 CPU_FEATURE_FSMULD,
1343 .name = "Cypress CY7C601",
1344 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1345 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1346 .mmu_version = 0x10 << 24,
1347 .mmu_bm = 0x00004000,
1348 .mmu_ctpr_mask = 0x007ffff0,
1349 .mmu_cxr_mask = 0x0000003f,
1350 .mmu_sfsr_mask = 0xffffffff,
1351 .mmu_trcr_mask = 0xffffffff,
1352 .nwindows = 8,
1353 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1354 CPU_FEATURE_FSMULD,
1357 .name = "Cypress CY7C611",
1358 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1359 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1360 .mmu_version = 0x10 << 24,
1361 .mmu_bm = 0x00004000,
1362 .mmu_ctpr_mask = 0x007ffff0,
1363 .mmu_cxr_mask = 0x0000003f,
1364 .mmu_sfsr_mask = 0xffffffff,
1365 .mmu_trcr_mask = 0xffffffff,
1366 .nwindows = 8,
1367 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1368 CPU_FEATURE_FSMULD,
1371 .name = "TI MicroSparc I",
1372 .iu_version = 0x41000000,
1373 .fpu_version = 4 << 17,
1374 .mmu_version = 0x41000000,
1375 .mmu_bm = 0x00004000,
1376 .mmu_ctpr_mask = 0x007ffff0,
1377 .mmu_cxr_mask = 0x0000003f,
1378 .mmu_sfsr_mask = 0x00016fff,
1379 .mmu_trcr_mask = 0x0000003f,
1380 .nwindows = 7,
1381 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1382 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1383 CPU_FEATURE_FMUL,
1386 .name = "TI MicroSparc II",
1387 .iu_version = 0x42000000,
1388 .fpu_version = 4 << 17,
1389 .mmu_version = 0x02000000,
1390 .mmu_bm = 0x00004000,
1391 .mmu_ctpr_mask = 0x00ffffc0,
1392 .mmu_cxr_mask = 0x000000ff,
1393 .mmu_sfsr_mask = 0x00016fff,
1394 .mmu_trcr_mask = 0x00ffffff,
1395 .nwindows = 8,
1396 .features = CPU_DEFAULT_FEATURES,
1399 .name = "TI MicroSparc IIep",
1400 .iu_version = 0x42000000,
1401 .fpu_version = 4 << 17,
1402 .mmu_version = 0x04000000,
1403 .mmu_bm = 0x00004000,
1404 .mmu_ctpr_mask = 0x00ffffc0,
1405 .mmu_cxr_mask = 0x000000ff,
1406 .mmu_sfsr_mask = 0x00016bff,
1407 .mmu_trcr_mask = 0x00ffffff,
1408 .nwindows = 8,
1409 .features = CPU_DEFAULT_FEATURES,
1412 .name = "TI SuperSparc 40", // STP1020NPGA
1413 .iu_version = 0x41000000, // SuperSPARC 2.x
1414 .fpu_version = 0 << 17,
1415 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1416 .mmu_bm = 0x00002000,
1417 .mmu_ctpr_mask = 0xffffffc0,
1418 .mmu_cxr_mask = 0x0000ffff,
1419 .mmu_sfsr_mask = 0xffffffff,
1420 .mmu_trcr_mask = 0xffffffff,
1421 .nwindows = 8,
1422 .features = CPU_DEFAULT_FEATURES,
1425 .name = "TI SuperSparc 50", // STP1020PGA
1426 .iu_version = 0x40000000, // SuperSPARC 3.x
1427 .fpu_version = 0 << 17,
1428 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1429 .mmu_bm = 0x00002000,
1430 .mmu_ctpr_mask = 0xffffffc0,
1431 .mmu_cxr_mask = 0x0000ffff,
1432 .mmu_sfsr_mask = 0xffffffff,
1433 .mmu_trcr_mask = 0xffffffff,
1434 .nwindows = 8,
1435 .features = CPU_DEFAULT_FEATURES,
1438 .name = "TI SuperSparc 51",
1439 .iu_version = 0x40000000, // SuperSPARC 3.x
1440 .fpu_version = 0 << 17,
1441 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1442 .mmu_bm = 0x00002000,
1443 .mmu_ctpr_mask = 0xffffffc0,
1444 .mmu_cxr_mask = 0x0000ffff,
1445 .mmu_sfsr_mask = 0xffffffff,
1446 .mmu_trcr_mask = 0xffffffff,
1447 .mxcc_version = 0x00000104,
1448 .nwindows = 8,
1449 .features = CPU_DEFAULT_FEATURES,
1452 .name = "TI SuperSparc 60", // STP1020APGA
1453 .iu_version = 0x40000000, // SuperSPARC 3.x
1454 .fpu_version = 0 << 17,
1455 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1456 .mmu_bm = 0x00002000,
1457 .mmu_ctpr_mask = 0xffffffc0,
1458 .mmu_cxr_mask = 0x0000ffff,
1459 .mmu_sfsr_mask = 0xffffffff,
1460 .mmu_trcr_mask = 0xffffffff,
1461 .nwindows = 8,
1462 .features = CPU_DEFAULT_FEATURES,
1465 .name = "TI SuperSparc 61",
1466 .iu_version = 0x44000000, // SuperSPARC 3.x
1467 .fpu_version = 0 << 17,
1468 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1469 .mmu_bm = 0x00002000,
1470 .mmu_ctpr_mask = 0xffffffc0,
1471 .mmu_cxr_mask = 0x0000ffff,
1472 .mmu_sfsr_mask = 0xffffffff,
1473 .mmu_trcr_mask = 0xffffffff,
1474 .mxcc_version = 0x00000104,
1475 .nwindows = 8,
1476 .features = CPU_DEFAULT_FEATURES,
1479 .name = "TI SuperSparc II",
1480 .iu_version = 0x40000000, // SuperSPARC II 1.x
1481 .fpu_version = 0 << 17,
1482 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1483 .mmu_bm = 0x00002000,
1484 .mmu_ctpr_mask = 0xffffffc0,
1485 .mmu_cxr_mask = 0x0000ffff,
1486 .mmu_sfsr_mask = 0xffffffff,
1487 .mmu_trcr_mask = 0xffffffff,
1488 .mxcc_version = 0x00000104,
1489 .nwindows = 8,
1490 .features = CPU_DEFAULT_FEATURES,
1493 .name = "Ross RT625",
1494 .iu_version = 0x1e000000,
1495 .fpu_version = 1 << 17,
1496 .mmu_version = 0x1e000000,
1497 .mmu_bm = 0x00004000,
1498 .mmu_ctpr_mask = 0x007ffff0,
1499 .mmu_cxr_mask = 0x0000003f,
1500 .mmu_sfsr_mask = 0xffffffff,
1501 .mmu_trcr_mask = 0xffffffff,
1502 .nwindows = 8,
1503 .features = CPU_DEFAULT_FEATURES,
1506 .name = "Ross RT620",
1507 .iu_version = 0x1f000000,
1508 .fpu_version = 1 << 17,
1509 .mmu_version = 0x1f000000,
1510 .mmu_bm = 0x00004000,
1511 .mmu_ctpr_mask = 0x007ffff0,
1512 .mmu_cxr_mask = 0x0000003f,
1513 .mmu_sfsr_mask = 0xffffffff,
1514 .mmu_trcr_mask = 0xffffffff,
1515 .nwindows = 8,
1516 .features = CPU_DEFAULT_FEATURES,
1519 .name = "BIT B5010",
1520 .iu_version = 0x20000000,
1521 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1522 .mmu_version = 0x20000000,
1523 .mmu_bm = 0x00004000,
1524 .mmu_ctpr_mask = 0x007ffff0,
1525 .mmu_cxr_mask = 0x0000003f,
1526 .mmu_sfsr_mask = 0xffffffff,
1527 .mmu_trcr_mask = 0xffffffff,
1528 .nwindows = 8,
1529 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1530 CPU_FEATURE_FSMULD,
1533 .name = "Matsushita MN10501",
1534 .iu_version = 0x50000000,
1535 .fpu_version = 0 << 17,
1536 .mmu_version = 0x50000000,
1537 .mmu_bm = 0x00004000,
1538 .mmu_ctpr_mask = 0x007ffff0,
1539 .mmu_cxr_mask = 0x0000003f,
1540 .mmu_sfsr_mask = 0xffffffff,
1541 .mmu_trcr_mask = 0xffffffff,
1542 .nwindows = 8,
1543 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1544 CPU_FEATURE_FSMULD,
1547 .name = "Weitek W8601",
1548 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1549 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1550 .mmu_version = 0x10 << 24,
1551 .mmu_bm = 0x00004000,
1552 .mmu_ctpr_mask = 0x007ffff0,
1553 .mmu_cxr_mask = 0x0000003f,
1554 .mmu_sfsr_mask = 0xffffffff,
1555 .mmu_trcr_mask = 0xffffffff,
1556 .nwindows = 8,
1557 .features = CPU_DEFAULT_FEATURES,
1560 .name = "LEON2",
1561 .iu_version = 0xf2000000,
1562 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1563 .mmu_version = 0xf2000000,
1564 .mmu_bm = 0x00004000,
1565 .mmu_ctpr_mask = 0x007ffff0,
1566 .mmu_cxr_mask = 0x0000003f,
1567 .mmu_sfsr_mask = 0xffffffff,
1568 .mmu_trcr_mask = 0xffffffff,
1569 .nwindows = 8,
1570 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
1573 .name = "LEON3",
1574 .iu_version = 0xf3000000,
1575 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1576 .mmu_version = 0xf3000000,
1577 .mmu_bm = 0x00000000,
1578 .mmu_ctpr_mask = 0x007ffff0,
1579 .mmu_cxr_mask = 0x0000003f,
1580 .mmu_sfsr_mask = 0xffffffff,
1581 .mmu_trcr_mask = 0xffffffff,
1582 .nwindows = 8,
1583 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
1584 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
1586 #endif
1589 static const char * const feature_name[] = {
1590 "float",
1591 "float128",
1592 "swap",
1593 "mul",
1594 "div",
1595 "flush",
1596 "fsqrt",
1597 "fmul",
1598 "vis1",
1599 "vis2",
1600 "fsmuld",
1601 "hypv",
1602 "cmt",
1603 "gl",
1606 static void print_features(FILE *f, fprintf_function cpu_fprintf,
1607 uint32_t features, const char *prefix)
1609 unsigned int i;
1611 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1612 if (feature_name[i] && (features & (1 << i))) {
1613 if (prefix)
1614 (*cpu_fprintf)(f, "%s", prefix);
1615 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1619 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1621 unsigned int i;
1623 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1624 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1625 *features |= 1 << i;
1626 return;
1628 fprintf(stderr, "CPU feature %s not found\n", flagname);
1631 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1633 unsigned int i;
1634 const sparc_def_t *def = NULL;
1635 char *s = strdup(cpu_model);
1636 char *featurestr, *name = strtok(s, ",");
1637 uint32_t plus_features = 0;
1638 uint32_t minus_features = 0;
1639 uint64_t iu_version;
1640 uint32_t fpu_version, mmu_version, nwindows;
1642 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1643 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1644 def = &sparc_defs[i];
1647 if (!def)
1648 goto error;
1649 memcpy(cpu_def, def, sizeof(*def));
1651 featurestr = strtok(NULL, ",");
1652 while (featurestr) {
1653 char *val;
1655 if (featurestr[0] == '+') {
1656 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1657 } else if (featurestr[0] == '-') {
1658 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1659 } else if ((val = strchr(featurestr, '='))) {
1660 *val = 0; val++;
1661 if (!strcmp(featurestr, "iu_version")) {
1662 char *err;
1664 iu_version = strtoll(val, &err, 0);
1665 if (!*val || *err) {
1666 fprintf(stderr, "bad numerical value %s\n", val);
1667 goto error;
1669 cpu_def->iu_version = iu_version;
1670 #ifdef DEBUG_FEATURES
1671 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1672 #endif
1673 } else if (!strcmp(featurestr, "fpu_version")) {
1674 char *err;
1676 fpu_version = strtol(val, &err, 0);
1677 if (!*val || *err) {
1678 fprintf(stderr, "bad numerical value %s\n", val);
1679 goto error;
1681 cpu_def->fpu_version = fpu_version;
1682 #ifdef DEBUG_FEATURES
1683 fprintf(stderr, "fpu_version %x\n", fpu_version);
1684 #endif
1685 } else if (!strcmp(featurestr, "mmu_version")) {
1686 char *err;
1688 mmu_version = strtol(val, &err, 0);
1689 if (!*val || *err) {
1690 fprintf(stderr, "bad numerical value %s\n", val);
1691 goto error;
1693 cpu_def->mmu_version = mmu_version;
1694 #ifdef DEBUG_FEATURES
1695 fprintf(stderr, "mmu_version %x\n", mmu_version);
1696 #endif
1697 } else if (!strcmp(featurestr, "nwindows")) {
1698 char *err;
1700 nwindows = strtol(val, &err, 0);
1701 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1702 nwindows < MIN_NWINDOWS) {
1703 fprintf(stderr, "bad numerical value %s\n", val);
1704 goto error;
1706 cpu_def->nwindows = nwindows;
1707 #ifdef DEBUG_FEATURES
1708 fprintf(stderr, "nwindows %d\n", nwindows);
1709 #endif
1710 } else {
1711 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1712 goto error;
1714 } else {
1715 fprintf(stderr, "feature string `%s' not in format "
1716 "(+feature|-feature|feature=xyz)\n", featurestr);
1717 goto error;
1719 featurestr = strtok(NULL, ",");
1721 cpu_def->features |= plus_features;
1722 cpu_def->features &= ~minus_features;
1723 #ifdef DEBUG_FEATURES
1724 print_features(stderr, fprintf, cpu_def->features, NULL);
1725 #endif
1726 free(s);
1727 return 0;
1729 error:
1730 free(s);
1731 return -1;
1734 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
1736 unsigned int i;
1738 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1739 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1740 sparc_defs[i].name,
1741 sparc_defs[i].iu_version,
1742 sparc_defs[i].fpu_version,
1743 sparc_defs[i].mmu_version,
1744 sparc_defs[i].nwindows);
1745 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1746 ~sparc_defs[i].features, "-");
1747 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1748 sparc_defs[i].features, "+");
1749 (*cpu_fprintf)(f, "\n");
1751 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1752 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1753 (*cpu_fprintf)(f, "\n");
1754 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1755 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1756 (*cpu_fprintf)(f, "\n");
1757 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1758 "fpu_version mmu_version nwindows\n");
1761 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
1762 uint32_t cc)
1764 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1765 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1766 cc & PSR_CARRY? 'C' : '-');
1769 #ifdef TARGET_SPARC64
1770 #define REGS_PER_LINE 4
1771 #else
1772 #define REGS_PER_LINE 8
1773 #endif
1775 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1776 int flags)
1778 int i, x;
1780 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1781 env->npc);
1782 cpu_fprintf(f, "General Registers:\n");
1784 for (i = 0; i < 8; i++) {
1785 if (i % REGS_PER_LINE == 0) {
1786 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1788 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1789 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1790 cpu_fprintf(f, "\n");
1793 cpu_fprintf(f, "\nCurrent Register Window:\n");
1794 for (x = 0; x < 3; x++) {
1795 for (i = 0; i < 8; i++) {
1796 if (i % REGS_PER_LINE == 0) {
1797 cpu_fprintf(f, "%%%c%d-%d: ",
1798 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1799 i, i + REGS_PER_LINE - 1);
1801 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1802 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1803 cpu_fprintf(f, "\n");
1807 cpu_fprintf(f, "\nFloating Point Registers:\n");
1808 for (i = 0; i < TARGET_FPREGS; i++) {
1809 if ((i & 3) == 0)
1810 cpu_fprintf(f, "%%f%02d:", i);
1811 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1812 if ((i & 3) == 3)
1813 cpu_fprintf(f, "\n");
1815 #ifdef TARGET_SPARC64
1816 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1817 (unsigned)cpu_get_ccr(env));
1818 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1819 cpu_fprintf(f, " xcc: ");
1820 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1821 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1822 env->psrpil);
1823 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1824 "cleanwin: %d cwp: %d\n",
1825 env->cansave, env->canrestore, env->otherwin, env->wstate,
1826 env->cleanwin, env->nwindows - 1 - env->cwp);
1827 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1828 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1829 #else
1830 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1831 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1832 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1833 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1834 env->wim);
1835 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1836 env->fsr, env->y);
1837 #endif