add migration state change notifiers
[qemu.git] / target-sparc / helper.c
blob6b337ca0910fbc701728d612d996a86cfdf65e1e
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 #if defined(CONFIG_USER_ONLY)
46 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
47 int mmu_idx, int is_softmmu)
49 if (rw & 2)
50 env1->exception_index = TT_TFAULT;
51 else
52 env1->exception_index = TT_DFAULT;
53 return 1;
56 #else
58 #ifndef TARGET_SPARC64
60 * Sparc V8 Reference MMU (SRMMU)
62 static const int access_table[8][8] = {
63 { 0, 0, 0, 0, 8, 0, 12, 12 },
64 { 0, 0, 0, 0, 8, 0, 0, 0 },
65 { 8, 8, 0, 0, 0, 8, 12, 12 },
66 { 8, 8, 0, 0, 0, 8, 0, 0 },
67 { 8, 0, 8, 0, 8, 8, 12, 12 },
68 { 8, 0, 8, 0, 8, 0, 8, 0 },
69 { 8, 8, 8, 0, 8, 8, 12, 12 },
70 { 8, 8, 8, 0, 8, 8, 8, 0 }
73 static const int perm_table[2][8] = {
75 PAGE_READ,
76 PAGE_READ | PAGE_WRITE,
77 PAGE_READ | PAGE_EXEC,
78 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
79 PAGE_EXEC,
80 PAGE_READ | PAGE_WRITE,
81 PAGE_READ | PAGE_EXEC,
82 PAGE_READ | PAGE_WRITE | PAGE_EXEC
85 PAGE_READ,
86 PAGE_READ | PAGE_WRITE,
87 PAGE_READ | PAGE_EXEC,
88 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
89 PAGE_EXEC,
90 PAGE_READ,
96 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
97 int *prot, int *access_index,
98 target_ulong address, int rw, int mmu_idx,
99 target_ulong *page_size)
101 int access_perms = 0;
102 target_phys_addr_t pde_ptr;
103 uint32_t pde;
104 int error_code = 0, is_dirty, is_user;
105 unsigned long page_offset;
107 is_user = mmu_idx == MMU_USER_IDX;
109 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
110 *page_size = TARGET_PAGE_SIZE;
111 // Boot mode: instruction fetches are taken from PROM
112 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
113 *physical = env->prom_addr | (address & 0x7ffffULL);
114 *prot = PAGE_READ | PAGE_EXEC;
115 return 0;
117 *physical = address;
118 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
119 return 0;
122 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
123 *physical = 0xffffffffffff0000ULL;
125 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
126 /* Context base + context number */
127 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
128 pde = ldl_phys(pde_ptr);
130 /* Ctx pde */
131 switch (pde & PTE_ENTRYTYPE_MASK) {
132 default:
133 case 0: /* Invalid */
134 return 1 << 2;
135 case 2: /* L0 PTE, maybe should not happen? */
136 case 3: /* Reserved */
137 return 4 << 2;
138 case 1: /* L0 PDE */
139 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
140 pde = ldl_phys(pde_ptr);
142 switch (pde & PTE_ENTRYTYPE_MASK) {
143 default:
144 case 0: /* Invalid */
145 return (1 << 8) | (1 << 2);
146 case 3: /* Reserved */
147 return (1 << 8) | (4 << 2);
148 case 1: /* L1 PDE */
149 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
150 pde = ldl_phys(pde_ptr);
152 switch (pde & PTE_ENTRYTYPE_MASK) {
153 default:
154 case 0: /* Invalid */
155 return (2 << 8) | (1 << 2);
156 case 3: /* Reserved */
157 return (2 << 8) | (4 << 2);
158 case 1: /* L2 PDE */
159 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
160 pde = ldl_phys(pde_ptr);
162 switch (pde & PTE_ENTRYTYPE_MASK) {
163 default:
164 case 0: /* Invalid */
165 return (3 << 8) | (1 << 2);
166 case 1: /* PDE, should not happen */
167 case 3: /* Reserved */
168 return (3 << 8) | (4 << 2);
169 case 2: /* L3 PTE */
170 page_offset = (address & TARGET_PAGE_MASK) &
171 (TARGET_PAGE_SIZE - 1);
173 *page_size = TARGET_PAGE_SIZE;
174 break;
175 case 2: /* L2 PTE */
176 page_offset = address & 0x3ffff;
177 *page_size = 0x40000;
179 break;
180 case 2: /* L1 PTE */
181 page_offset = address & 0xffffff;
182 *page_size = 0x1000000;
186 /* check access */
187 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
188 error_code = access_table[*access_index][access_perms];
189 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
190 return error_code;
192 /* update page modified and dirty bits */
193 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
194 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
195 pde |= PG_ACCESSED_MASK;
196 if (is_dirty)
197 pde |= PG_MODIFIED_MASK;
198 stl_phys_notdirty(pde_ptr, pde);
201 /* the page can be put in the TLB */
202 *prot = perm_table[is_user][access_perms];
203 if (!(pde & PG_MODIFIED_MASK)) {
204 /* only set write access if already dirty... otherwise wait
205 for dirty access */
206 *prot &= ~PAGE_WRITE;
209 /* Even if large ptes, we map only one 4KB page in the cache to
210 avoid filling it too fast */
211 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
212 return error_code;
215 /* Perform address translation */
216 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
217 int mmu_idx, int is_softmmu)
219 target_phys_addr_t paddr;
220 target_ulong vaddr;
221 target_ulong page_size;
222 int error_code = 0, prot, access_index;
224 error_code = get_physical_address(env, &paddr, &prot, &access_index,
225 address, rw, mmu_idx, &page_size);
226 if (error_code == 0) {
227 vaddr = address & TARGET_PAGE_MASK;
228 paddr &= TARGET_PAGE_MASK;
229 #ifdef DEBUG_MMU
230 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
231 TARGET_FMT_lx "\n", address, paddr, vaddr);
232 #endif
233 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
234 return 0;
237 if (env->mmuregs[3]) /* Fault status register */
238 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
239 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
240 env->mmuregs[4] = address; /* Fault address register */
242 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
243 // No fault mode: if a mapping is available, just override
244 // permissions. If no mapping is available, redirect accesses to
245 // neverland. Fake/overridden mappings will be flushed when
246 // switching to normal mode.
247 vaddr = address & TARGET_PAGE_MASK;
248 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
249 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
250 return 0;
251 } else {
252 if (rw & 2)
253 env->exception_index = TT_TFAULT;
254 else
255 env->exception_index = TT_DFAULT;
256 return 1;
260 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
262 target_phys_addr_t pde_ptr;
263 uint32_t pde;
265 /* Context base + context number */
266 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
267 (env->mmuregs[2] << 2);
268 pde = ldl_phys(pde_ptr);
270 switch (pde & PTE_ENTRYTYPE_MASK) {
271 default:
272 case 0: /* Invalid */
273 case 2: /* PTE, maybe should not happen? */
274 case 3: /* Reserved */
275 return 0;
276 case 1: /* L1 PDE */
277 if (mmulev == 3)
278 return pde;
279 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
280 pde = ldl_phys(pde_ptr);
282 switch (pde & PTE_ENTRYTYPE_MASK) {
283 default:
284 case 0: /* Invalid */
285 case 3: /* Reserved */
286 return 0;
287 case 2: /* L1 PTE */
288 return pde;
289 case 1: /* L2 PDE */
290 if (mmulev == 2)
291 return pde;
292 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
293 pde = ldl_phys(pde_ptr);
295 switch (pde & PTE_ENTRYTYPE_MASK) {
296 default:
297 case 0: /* Invalid */
298 case 3: /* Reserved */
299 return 0;
300 case 2: /* L2 PTE */
301 return pde;
302 case 1: /* L3 PDE */
303 if (mmulev == 1)
304 return pde;
305 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
306 pde = ldl_phys(pde_ptr);
308 switch (pde & PTE_ENTRYTYPE_MASK) {
309 default:
310 case 0: /* Invalid */
311 case 1: /* PDE, should not happen */
312 case 3: /* Reserved */
313 return 0;
314 case 2: /* L3 PTE */
315 return pde;
320 return 0;
323 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
325 target_ulong va, va1, va2;
326 unsigned int n, m, o;
327 target_phys_addr_t pde_ptr, pa;
328 uint32_t pde;
330 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
331 pde = ldl_phys(pde_ptr);
332 (*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
333 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
334 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
335 pde = mmu_probe(env, va, 2);
336 if (pde) {
337 pa = cpu_get_phys_page_debug(env, va);
338 (*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
339 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
340 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
341 pde = mmu_probe(env, va1, 1);
342 if (pde) {
343 pa = cpu_get_phys_page_debug(env, va1);
344 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
345 TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
346 va1, pa, pde);
347 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
348 pde = mmu_probe(env, va2, 0);
349 if (pde) {
350 pa = cpu_get_phys_page_debug(env, va2);
351 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
352 TARGET_FMT_plx " PTE: "
353 TARGET_FMT_lx "\n",
354 va2, pa, pde);
363 #else /* !TARGET_SPARC64 */
365 // 41 bit physical address space
366 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
368 return x & 0x1ffffffffffULL;
372 * UltraSparc IIi I/DMMUs
375 // Returns true if TTE tag is valid and matches virtual address value in context
376 // requires virtual address mask value calculated from TTE entry size
377 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
378 uint64_t address, uint64_t context,
379 target_phys_addr_t *physical)
381 uint64_t mask;
383 switch ((tlb->tte >> 61) & 3) {
384 default:
385 case 0x0: // 8k
386 mask = 0xffffffffffffe000ULL;
387 break;
388 case 0x1: // 64k
389 mask = 0xffffffffffff0000ULL;
390 break;
391 case 0x2: // 512k
392 mask = 0xfffffffffff80000ULL;
393 break;
394 case 0x3: // 4M
395 mask = 0xffffffffffc00000ULL;
396 break;
399 // valid, context match, virtual address match?
400 if (TTE_IS_VALID(tlb->tte) &&
401 (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
402 && compare_masked(address, tlb->tag, mask))
404 // decode physical address
405 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
406 return 1;
409 return 0;
412 static int get_physical_address_data(CPUState *env,
413 target_phys_addr_t *physical, int *prot,
414 target_ulong address, int rw, int mmu_idx)
416 unsigned int i;
417 uint64_t context;
419 int is_user = (mmu_idx == MMU_USER_IDX ||
420 mmu_idx == MMU_USER_SECONDARY_IDX);
422 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
423 *physical = ultrasparc_truncate_physical(address);
424 *prot = PAGE_READ | PAGE_WRITE;
425 return 0;
428 switch(mmu_idx) {
429 case MMU_USER_IDX:
430 case MMU_KERNEL_IDX:
431 context = env->dmmu.mmu_primary_context & 0x1fff;
432 break;
433 case MMU_USER_SECONDARY_IDX:
434 case MMU_KERNEL_SECONDARY_IDX:
435 context = env->dmmu.mmu_secondary_context & 0x1fff;
436 break;
437 case MMU_NUCLEUS_IDX:
438 default:
439 context = 0;
440 break;
443 for (i = 0; i < 64; i++) {
444 // ctx match, vaddr match, valid?
445 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
447 uint8_t fault_type = 0;
449 // access ok?
450 if ((env->dtlb[i].tte & 0x4) && is_user) {
451 fault_type |= 1; /* privilege violation */
452 env->exception_index = TT_DFAULT;
454 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
455 " mmu_idx=%d tl=%d\n",
456 address, context, mmu_idx, env->tl);
457 } else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) {
458 env->exception_index = TT_DPROT;
460 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
461 " mmu_idx=%d tl=%d\n",
462 address, context, mmu_idx, env->tl);
463 } else {
464 *prot = PAGE_READ;
465 if (env->dtlb[i].tte & 0x2)
466 *prot |= PAGE_WRITE;
468 TTE_SET_USED(env->dtlb[i].tte);
470 return 0;
473 if (env->dmmu.sfsr & 1) /* Fault status register */
474 env->dmmu.sfsr = 2; /* overflow (not read before
475 another fault) */
477 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
479 env->dmmu.sfsr |= (fault_type << 7);
481 env->dmmu.sfar = address; /* Fault address register */
483 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
485 return 1;
489 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
490 address, context);
492 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
493 env->exception_index = TT_DMISS;
494 return 1;
497 static int get_physical_address_code(CPUState *env,
498 target_phys_addr_t *physical, int *prot,
499 target_ulong address, int mmu_idx)
501 unsigned int i;
502 uint64_t context;
504 int is_user = (mmu_idx == MMU_USER_IDX ||
505 mmu_idx == MMU_USER_SECONDARY_IDX);
507 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
508 /* IMMU disabled */
509 *physical = ultrasparc_truncate_physical(address);
510 *prot = PAGE_EXEC;
511 return 0;
514 if (env->tl == 0) {
515 /* PRIMARY context */
516 context = env->dmmu.mmu_primary_context & 0x1fff;
517 } else {
518 /* NUCLEUS context */
519 context = 0;
522 for (i = 0; i < 64; i++) {
523 // ctx match, vaddr match, valid?
524 if (ultrasparc_tag_match(&env->itlb[i],
525 address, context, physical)) {
526 // access ok?
527 if ((env->itlb[i].tte & 0x4) && is_user) {
528 if (env->immu.sfsr) /* Fault status register */
529 env->immu.sfsr = 2; /* overflow (not read before
530 another fault) */
531 env->immu.sfsr |= (is_user << 3) | 1;
532 env->exception_index = TT_TFAULT;
534 env->immu.tag_access = (address & ~0x1fffULL) | context;
536 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
537 address, context);
539 return 1;
541 *prot = PAGE_EXEC;
542 TTE_SET_USED(env->itlb[i].tte);
543 return 0;
547 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
548 address, context);
550 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
551 env->immu.tag_access = (address & ~0x1fffULL) | context;
552 env->exception_index = TT_TMISS;
553 return 1;
556 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
557 int *prot, int *access_index,
558 target_ulong address, int rw, int mmu_idx,
559 target_ulong *page_size)
561 /* ??? We treat everything as a small page, then explicitly flush
562 everything when an entry is evicted. */
563 *page_size = TARGET_PAGE_SIZE;
565 #if defined (DEBUG_MMU)
566 /* safety net to catch wrong softmmu index use from dynamic code */
567 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
568 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
569 " primary context=%" PRIx64
570 " secondary context=%" PRIx64
571 " address=%" PRIx64
572 "\n",
573 (rw == 2 ? "CODE" : "DATA"),
574 env->tl, mmu_idx,
575 env->dmmu.mmu_primary_context,
576 env->dmmu.mmu_secondary_context,
577 address);
579 #endif
581 if (rw == 2)
582 return get_physical_address_code(env, physical, prot, address,
583 mmu_idx);
584 else
585 return get_physical_address_data(env, physical, prot, address, rw,
586 mmu_idx);
589 /* Perform address translation */
590 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
591 int mmu_idx, int is_softmmu)
593 target_ulong virt_addr, vaddr;
594 target_phys_addr_t paddr;
595 target_ulong page_size;
596 int error_code = 0, prot, access_index;
598 error_code = get_physical_address(env, &paddr, &prot, &access_index,
599 address, rw, mmu_idx, &page_size);
600 if (error_code == 0) {
601 virt_addr = address & TARGET_PAGE_MASK;
602 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
603 (TARGET_PAGE_SIZE - 1));
605 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
606 " vaddr %" PRIx64
607 " mmu_idx=%d"
608 " tl=%d"
609 " primary context=%" PRIx64
610 " secondary context=%" PRIx64
611 "\n",
612 address, paddr, vaddr, mmu_idx, env->tl,
613 env->dmmu.mmu_primary_context,
614 env->dmmu.mmu_secondary_context);
616 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
617 return 0;
619 // XXX
620 return 1;
623 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
625 unsigned int i;
626 const char *mask;
628 (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
629 PRId64 "\n",
630 env->dmmu.mmu_primary_context,
631 env->dmmu.mmu_secondary_context);
632 if ((env->lsu & DMMU_E) == 0) {
633 (*cpu_fprintf)(f, "DMMU disabled\n");
634 } else {
635 (*cpu_fprintf)(f, "DMMU dump\n");
636 for (i = 0; i < 64; i++) {
637 switch ((env->dtlb[i].tte >> 61) & 3) {
638 default:
639 case 0x0:
640 mask = " 8k";
641 break;
642 case 0x1:
643 mask = " 64k";
644 break;
645 case 0x2:
646 mask = "512k";
647 break;
648 case 0x3:
649 mask = " 4M";
650 break;
652 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
653 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
654 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
656 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
657 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
658 mask,
659 env->dtlb[i].tte & 0x4? "priv": "user",
660 env->dtlb[i].tte & 0x2? "RW": "RO",
661 env->dtlb[i].tte & 0x40? "locked": "unlocked",
662 env->dtlb[i].tag & (uint64_t)0x1fffULL,
663 TTE_IS_GLOBAL(env->dtlb[i].tte)?
664 "global" : "local");
668 if ((env->lsu & IMMU_E) == 0) {
669 (*cpu_fprintf)(f, "IMMU disabled\n");
670 } else {
671 (*cpu_fprintf)(f, "IMMU dump\n");
672 for (i = 0; i < 64; i++) {
673 switch ((env->itlb[i].tte >> 61) & 3) {
674 default:
675 case 0x0:
676 mask = " 8k";
677 break;
678 case 0x1:
679 mask = " 64k";
680 break;
681 case 0x2:
682 mask = "512k";
683 break;
684 case 0x3:
685 mask = " 4M";
686 break;
688 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
689 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
690 ", %s, %s, %s, ctx %" PRId64 " %s\n",
692 env->itlb[i].tag & (uint64_t)~0x1fffULL,
693 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
694 mask,
695 env->itlb[i].tte & 0x4? "priv": "user",
696 env->itlb[i].tte & 0x40? "locked": "unlocked",
697 env->itlb[i].tag & (uint64_t)0x1fffULL,
698 TTE_IS_GLOBAL(env->itlb[i].tte)?
699 "global" : "local");
705 #endif /* TARGET_SPARC64 */
706 #endif /* !CONFIG_USER_ONLY */
709 #if !defined(CONFIG_USER_ONLY)
710 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
711 int mmu_idx)
713 target_phys_addr_t phys_addr;
714 target_ulong page_size;
715 int prot, access_index;
717 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
718 mmu_idx, &page_size) != 0)
719 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
720 0, mmu_idx, &page_size) != 0)
721 return -1;
722 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
723 return -1;
724 return phys_addr;
727 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
729 return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
731 #endif
733 void cpu_reset(CPUSPARCState *env)
735 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
736 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
737 log_cpu_state(env, 0);
740 tlb_flush(env, 1);
741 env->cwp = 0;
742 #ifndef TARGET_SPARC64
743 env->wim = 1;
744 #endif
745 env->regwptr = env->regbase + (env->cwp * 16);
746 CC_OP = CC_OP_FLAGS;
747 #if defined(CONFIG_USER_ONLY)
748 #ifdef TARGET_SPARC64
749 env->cleanwin = env->nwindows - 2;
750 env->cansave = env->nwindows - 2;
751 env->pstate = PS_RMO | PS_PEF | PS_IE;
752 env->asi = 0x82; // Primary no-fault
753 #endif
754 #else
755 #if !defined(TARGET_SPARC64)
756 env->psret = 0;
757 env->psrs = 1;
758 env->psrps = 1;
759 #endif
760 #ifdef TARGET_SPARC64
761 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
762 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
763 env->tl = env->maxtl;
764 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
765 env->lsu = 0;
766 #else
767 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
768 env->mmuregs[0] |= env->def->mmu_bm;
769 #endif
770 env->pc = 0;
771 env->npc = env->pc + 4;
772 #endif
775 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
777 sparc_def_t def1, *def = &def1;
779 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
780 return -1;
782 env->def = qemu_mallocz(sizeof(*def));
783 memcpy(env->def, def, sizeof(*def));
784 #if defined(CONFIG_USER_ONLY)
785 if ((env->def->features & CPU_FEATURE_FLOAT))
786 env->def->features |= CPU_FEATURE_FLOAT128;
787 #endif
788 env->cpu_model_str = cpu_model;
789 env->version = def->iu_version;
790 env->fsr = def->fpu_version;
791 env->nwindows = def->nwindows;
792 #if !defined(TARGET_SPARC64)
793 env->mmuregs[0] |= def->mmu_version;
794 cpu_sparc_set_id(env, 0);
795 env->mxccregs[7] |= def->mxcc_version;
796 #else
797 env->mmu_version = def->mmu_version;
798 env->maxtl = def->maxtl;
799 env->version |= def->maxtl << 8;
800 env->version |= def->nwindows - 1;
801 #endif
802 return 0;
805 static void cpu_sparc_close(CPUSPARCState *env)
807 free(env->def);
808 free(env);
811 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
813 CPUSPARCState *env;
815 env = qemu_mallocz(sizeof(CPUSPARCState));
816 cpu_exec_init(env);
818 gen_intermediate_code_init(env);
820 if (cpu_sparc_register(env, cpu_model) < 0) {
821 cpu_sparc_close(env);
822 return NULL;
824 qemu_init_vcpu(env);
826 return env;
829 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
831 #if !defined(TARGET_SPARC64)
832 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
833 #endif
836 static const sparc_def_t sparc_defs[] = {
837 #ifdef TARGET_SPARC64
839 .name = "Fujitsu Sparc64",
840 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
841 .fpu_version = 0x00000000,
842 .mmu_version = mmu_us_12,
843 .nwindows = 4,
844 .maxtl = 4,
845 .features = CPU_DEFAULT_FEATURES,
848 .name = "Fujitsu Sparc64 III",
849 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
850 .fpu_version = 0x00000000,
851 .mmu_version = mmu_us_12,
852 .nwindows = 5,
853 .maxtl = 4,
854 .features = CPU_DEFAULT_FEATURES,
857 .name = "Fujitsu Sparc64 IV",
858 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
859 .fpu_version = 0x00000000,
860 .mmu_version = mmu_us_12,
861 .nwindows = 8,
862 .maxtl = 5,
863 .features = CPU_DEFAULT_FEATURES,
866 .name = "Fujitsu Sparc64 V",
867 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
868 .fpu_version = 0x00000000,
869 .mmu_version = mmu_us_12,
870 .nwindows = 8,
871 .maxtl = 5,
872 .features = CPU_DEFAULT_FEATURES,
875 .name = "TI UltraSparc I",
876 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
877 .fpu_version = 0x00000000,
878 .mmu_version = mmu_us_12,
879 .nwindows = 8,
880 .maxtl = 5,
881 .features = CPU_DEFAULT_FEATURES,
884 .name = "TI UltraSparc II",
885 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
886 .fpu_version = 0x00000000,
887 .mmu_version = mmu_us_12,
888 .nwindows = 8,
889 .maxtl = 5,
890 .features = CPU_DEFAULT_FEATURES,
893 .name = "TI UltraSparc IIi",
894 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
895 .fpu_version = 0x00000000,
896 .mmu_version = mmu_us_12,
897 .nwindows = 8,
898 .maxtl = 5,
899 .features = CPU_DEFAULT_FEATURES,
902 .name = "TI UltraSparc IIe",
903 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
904 .fpu_version = 0x00000000,
905 .mmu_version = mmu_us_12,
906 .nwindows = 8,
907 .maxtl = 5,
908 .features = CPU_DEFAULT_FEATURES,
911 .name = "Sun UltraSparc III",
912 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
913 .fpu_version = 0x00000000,
914 .mmu_version = mmu_us_12,
915 .nwindows = 8,
916 .maxtl = 5,
917 .features = CPU_DEFAULT_FEATURES,
920 .name = "Sun UltraSparc III Cu",
921 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
922 .fpu_version = 0x00000000,
923 .mmu_version = mmu_us_3,
924 .nwindows = 8,
925 .maxtl = 5,
926 .features = CPU_DEFAULT_FEATURES,
929 .name = "Sun UltraSparc IIIi",
930 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
931 .fpu_version = 0x00000000,
932 .mmu_version = mmu_us_12,
933 .nwindows = 8,
934 .maxtl = 5,
935 .features = CPU_DEFAULT_FEATURES,
938 .name = "Sun UltraSparc IV",
939 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
940 .fpu_version = 0x00000000,
941 .mmu_version = mmu_us_4,
942 .nwindows = 8,
943 .maxtl = 5,
944 .features = CPU_DEFAULT_FEATURES,
947 .name = "Sun UltraSparc IV+",
948 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
949 .fpu_version = 0x00000000,
950 .mmu_version = mmu_us_12,
951 .nwindows = 8,
952 .maxtl = 5,
953 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
956 .name = "Sun UltraSparc IIIi+",
957 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
958 .fpu_version = 0x00000000,
959 .mmu_version = mmu_us_3,
960 .nwindows = 8,
961 .maxtl = 5,
962 .features = CPU_DEFAULT_FEATURES,
965 .name = "Sun UltraSparc T1",
966 // defined in sparc_ifu_fdp.v and ctu.h
967 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
968 .fpu_version = 0x00000000,
969 .mmu_version = mmu_sun4v,
970 .nwindows = 8,
971 .maxtl = 6,
972 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
973 | CPU_FEATURE_GL,
976 .name = "Sun UltraSparc T2",
977 // defined in tlu_asi_ctl.v and n2_revid_cust.v
978 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
979 .fpu_version = 0x00000000,
980 .mmu_version = mmu_sun4v,
981 .nwindows = 8,
982 .maxtl = 6,
983 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
984 | CPU_FEATURE_GL,
987 .name = "NEC UltraSparc I",
988 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
989 .fpu_version = 0x00000000,
990 .mmu_version = mmu_us_12,
991 .nwindows = 8,
992 .maxtl = 5,
993 .features = CPU_DEFAULT_FEATURES,
995 #else
997 .name = "Fujitsu MB86900",
998 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
999 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1000 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1001 .mmu_bm = 0x00004000,
1002 .mmu_ctpr_mask = 0x007ffff0,
1003 .mmu_cxr_mask = 0x0000003f,
1004 .mmu_sfsr_mask = 0xffffffff,
1005 .mmu_trcr_mask = 0xffffffff,
1006 .nwindows = 7,
1007 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1010 .name = "Fujitsu MB86904",
1011 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1012 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1013 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1014 .mmu_bm = 0x00004000,
1015 .mmu_ctpr_mask = 0x00ffffc0,
1016 .mmu_cxr_mask = 0x000000ff,
1017 .mmu_sfsr_mask = 0x00016fff,
1018 .mmu_trcr_mask = 0x00ffffff,
1019 .nwindows = 8,
1020 .features = CPU_DEFAULT_FEATURES,
1023 .name = "Fujitsu MB86907",
1024 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1025 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1026 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1027 .mmu_bm = 0x00004000,
1028 .mmu_ctpr_mask = 0xffffffc0,
1029 .mmu_cxr_mask = 0x000000ff,
1030 .mmu_sfsr_mask = 0x00016fff,
1031 .mmu_trcr_mask = 0xffffffff,
1032 .nwindows = 8,
1033 .features = CPU_DEFAULT_FEATURES,
1036 .name = "LSI L64811",
1037 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1038 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1039 .mmu_version = 0x10 << 24,
1040 .mmu_bm = 0x00004000,
1041 .mmu_ctpr_mask = 0x007ffff0,
1042 .mmu_cxr_mask = 0x0000003f,
1043 .mmu_sfsr_mask = 0xffffffff,
1044 .mmu_trcr_mask = 0xffffffff,
1045 .nwindows = 8,
1046 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1047 CPU_FEATURE_FSMULD,
1050 .name = "Cypress CY7C601",
1051 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1052 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
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 CY7C611",
1065 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
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 = "TI MicroSparc I",
1079 .iu_version = 0x41000000,
1080 .fpu_version = 4 << 17,
1081 .mmu_version = 0x41000000,
1082 .mmu_bm = 0x00004000,
1083 .mmu_ctpr_mask = 0x007ffff0,
1084 .mmu_cxr_mask = 0x0000003f,
1085 .mmu_sfsr_mask = 0x00016fff,
1086 .mmu_trcr_mask = 0x0000003f,
1087 .nwindows = 7,
1088 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1089 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1090 CPU_FEATURE_FMUL,
1093 .name = "TI MicroSparc II",
1094 .iu_version = 0x42000000,
1095 .fpu_version = 4 << 17,
1096 .mmu_version = 0x02000000,
1097 .mmu_bm = 0x00004000,
1098 .mmu_ctpr_mask = 0x00ffffc0,
1099 .mmu_cxr_mask = 0x000000ff,
1100 .mmu_sfsr_mask = 0x00016fff,
1101 .mmu_trcr_mask = 0x00ffffff,
1102 .nwindows = 8,
1103 .features = CPU_DEFAULT_FEATURES,
1106 .name = "TI MicroSparc IIep",
1107 .iu_version = 0x42000000,
1108 .fpu_version = 4 << 17,
1109 .mmu_version = 0x04000000,
1110 .mmu_bm = 0x00004000,
1111 .mmu_ctpr_mask = 0x00ffffc0,
1112 .mmu_cxr_mask = 0x000000ff,
1113 .mmu_sfsr_mask = 0x00016bff,
1114 .mmu_trcr_mask = 0x00ffffff,
1115 .nwindows = 8,
1116 .features = CPU_DEFAULT_FEATURES,
1119 .name = "TI SuperSparc 40", // STP1020NPGA
1120 .iu_version = 0x41000000, // SuperSPARC 2.x
1121 .fpu_version = 0 << 17,
1122 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1123 .mmu_bm = 0x00002000,
1124 .mmu_ctpr_mask = 0xffffffc0,
1125 .mmu_cxr_mask = 0x0000ffff,
1126 .mmu_sfsr_mask = 0xffffffff,
1127 .mmu_trcr_mask = 0xffffffff,
1128 .nwindows = 8,
1129 .features = CPU_DEFAULT_FEATURES,
1132 .name = "TI SuperSparc 50", // STP1020PGA
1133 .iu_version = 0x40000000, // SuperSPARC 3.x
1134 .fpu_version = 0 << 17,
1135 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1136 .mmu_bm = 0x00002000,
1137 .mmu_ctpr_mask = 0xffffffc0,
1138 .mmu_cxr_mask = 0x0000ffff,
1139 .mmu_sfsr_mask = 0xffffffff,
1140 .mmu_trcr_mask = 0xffffffff,
1141 .nwindows = 8,
1142 .features = CPU_DEFAULT_FEATURES,
1145 .name = "TI SuperSparc 51",
1146 .iu_version = 0x40000000, // SuperSPARC 3.x
1147 .fpu_version = 0 << 17,
1148 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1149 .mmu_bm = 0x00002000,
1150 .mmu_ctpr_mask = 0xffffffc0,
1151 .mmu_cxr_mask = 0x0000ffff,
1152 .mmu_sfsr_mask = 0xffffffff,
1153 .mmu_trcr_mask = 0xffffffff,
1154 .mxcc_version = 0x00000104,
1155 .nwindows = 8,
1156 .features = CPU_DEFAULT_FEATURES,
1159 .name = "TI SuperSparc 60", // STP1020APGA
1160 .iu_version = 0x40000000, // SuperSPARC 3.x
1161 .fpu_version = 0 << 17,
1162 .mmu_version = 0x01000800, // SuperSPARC 3.x, no 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 .nwindows = 8,
1169 .features = CPU_DEFAULT_FEATURES,
1172 .name = "TI SuperSparc 61",
1173 .iu_version = 0x44000000, // SuperSPARC 3.x
1174 .fpu_version = 0 << 17,
1175 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1176 .mmu_bm = 0x00002000,
1177 .mmu_ctpr_mask = 0xffffffc0,
1178 .mmu_cxr_mask = 0x0000ffff,
1179 .mmu_sfsr_mask = 0xffffffff,
1180 .mmu_trcr_mask = 0xffffffff,
1181 .mxcc_version = 0x00000104,
1182 .nwindows = 8,
1183 .features = CPU_DEFAULT_FEATURES,
1186 .name = "TI SuperSparc II",
1187 .iu_version = 0x40000000, // SuperSPARC II 1.x
1188 .fpu_version = 0 << 17,
1189 .mmu_version = 0x08000000, // SuperSPARC II 1.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 = "Ross RT625",
1201 .iu_version = 0x1e000000,
1202 .fpu_version = 1 << 17,
1203 .mmu_version = 0x1e000000,
1204 .mmu_bm = 0x00004000,
1205 .mmu_ctpr_mask = 0x007ffff0,
1206 .mmu_cxr_mask = 0x0000003f,
1207 .mmu_sfsr_mask = 0xffffffff,
1208 .mmu_trcr_mask = 0xffffffff,
1209 .nwindows = 8,
1210 .features = CPU_DEFAULT_FEATURES,
1213 .name = "Ross RT620",
1214 .iu_version = 0x1f000000,
1215 .fpu_version = 1 << 17,
1216 .mmu_version = 0x1f000000,
1217 .mmu_bm = 0x00004000,
1218 .mmu_ctpr_mask = 0x007ffff0,
1219 .mmu_cxr_mask = 0x0000003f,
1220 .mmu_sfsr_mask = 0xffffffff,
1221 .mmu_trcr_mask = 0xffffffff,
1222 .nwindows = 8,
1223 .features = CPU_DEFAULT_FEATURES,
1226 .name = "BIT B5010",
1227 .iu_version = 0x20000000,
1228 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1229 .mmu_version = 0x20000000,
1230 .mmu_bm = 0x00004000,
1231 .mmu_ctpr_mask = 0x007ffff0,
1232 .mmu_cxr_mask = 0x0000003f,
1233 .mmu_sfsr_mask = 0xffffffff,
1234 .mmu_trcr_mask = 0xffffffff,
1235 .nwindows = 8,
1236 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1237 CPU_FEATURE_FSMULD,
1240 .name = "Matsushita MN10501",
1241 .iu_version = 0x50000000,
1242 .fpu_version = 0 << 17,
1243 .mmu_version = 0x50000000,
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_MUL | CPU_FEATURE_FSQRT |
1251 CPU_FEATURE_FSMULD,
1254 .name = "Weitek W8601",
1255 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1256 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1257 .mmu_version = 0x10 << 24,
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_DEFAULT_FEATURES,
1267 .name = "LEON2",
1268 .iu_version = 0xf2000000,
1269 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1270 .mmu_version = 0xf2000000,
1271 .mmu_bm = 0x00004000,
1272 .mmu_ctpr_mask = 0x007ffff0,
1273 .mmu_cxr_mask = 0x0000003f,
1274 .mmu_sfsr_mask = 0xffffffff,
1275 .mmu_trcr_mask = 0xffffffff,
1276 .nwindows = 8,
1277 .features = CPU_DEFAULT_FEATURES,
1280 .name = "LEON3",
1281 .iu_version = 0xf3000000,
1282 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1283 .mmu_version = 0xf3000000,
1284 .mmu_bm = 0x00004000,
1285 .mmu_ctpr_mask = 0x007ffff0,
1286 .mmu_cxr_mask = 0x0000003f,
1287 .mmu_sfsr_mask = 0xffffffff,
1288 .mmu_trcr_mask = 0xffffffff,
1289 .nwindows = 8,
1290 .features = CPU_DEFAULT_FEATURES,
1292 #endif
1295 static const char * const feature_name[] = {
1296 "float",
1297 "float128",
1298 "swap",
1299 "mul",
1300 "div",
1301 "flush",
1302 "fsqrt",
1303 "fmul",
1304 "vis1",
1305 "vis2",
1306 "fsmuld",
1307 "hypv",
1308 "cmt",
1309 "gl",
1312 static void print_features(FILE *f, fprintf_function cpu_fprintf,
1313 uint32_t features, const char *prefix)
1315 unsigned int i;
1317 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1318 if (feature_name[i] && (features & (1 << i))) {
1319 if (prefix)
1320 (*cpu_fprintf)(f, "%s", prefix);
1321 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1325 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1327 unsigned int i;
1329 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1330 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1331 *features |= 1 << i;
1332 return;
1334 fprintf(stderr, "CPU feature %s not found\n", flagname);
1337 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1339 unsigned int i;
1340 const sparc_def_t *def = NULL;
1341 char *s = strdup(cpu_model);
1342 char *featurestr, *name = strtok(s, ",");
1343 uint32_t plus_features = 0;
1344 uint32_t minus_features = 0;
1345 uint64_t iu_version;
1346 uint32_t fpu_version, mmu_version, nwindows;
1348 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1349 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1350 def = &sparc_defs[i];
1353 if (!def)
1354 goto error;
1355 memcpy(cpu_def, def, sizeof(*def));
1357 featurestr = strtok(NULL, ",");
1358 while (featurestr) {
1359 char *val;
1361 if (featurestr[0] == '+') {
1362 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1363 } else if (featurestr[0] == '-') {
1364 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1365 } else if ((val = strchr(featurestr, '='))) {
1366 *val = 0; val++;
1367 if (!strcmp(featurestr, "iu_version")) {
1368 char *err;
1370 iu_version = strtoll(val, &err, 0);
1371 if (!*val || *err) {
1372 fprintf(stderr, "bad numerical value %s\n", val);
1373 goto error;
1375 cpu_def->iu_version = iu_version;
1376 #ifdef DEBUG_FEATURES
1377 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1378 #endif
1379 } else if (!strcmp(featurestr, "fpu_version")) {
1380 char *err;
1382 fpu_version = strtol(val, &err, 0);
1383 if (!*val || *err) {
1384 fprintf(stderr, "bad numerical value %s\n", val);
1385 goto error;
1387 cpu_def->fpu_version = fpu_version;
1388 #ifdef DEBUG_FEATURES
1389 fprintf(stderr, "fpu_version %x\n", fpu_version);
1390 #endif
1391 } else if (!strcmp(featurestr, "mmu_version")) {
1392 char *err;
1394 mmu_version = strtol(val, &err, 0);
1395 if (!*val || *err) {
1396 fprintf(stderr, "bad numerical value %s\n", val);
1397 goto error;
1399 cpu_def->mmu_version = mmu_version;
1400 #ifdef DEBUG_FEATURES
1401 fprintf(stderr, "mmu_version %x\n", mmu_version);
1402 #endif
1403 } else if (!strcmp(featurestr, "nwindows")) {
1404 char *err;
1406 nwindows = strtol(val, &err, 0);
1407 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1408 nwindows < MIN_NWINDOWS) {
1409 fprintf(stderr, "bad numerical value %s\n", val);
1410 goto error;
1412 cpu_def->nwindows = nwindows;
1413 #ifdef DEBUG_FEATURES
1414 fprintf(stderr, "nwindows %d\n", nwindows);
1415 #endif
1416 } else {
1417 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1418 goto error;
1420 } else {
1421 fprintf(stderr, "feature string `%s' not in format "
1422 "(+feature|-feature|feature=xyz)\n", featurestr);
1423 goto error;
1425 featurestr = strtok(NULL, ",");
1427 cpu_def->features |= plus_features;
1428 cpu_def->features &= ~minus_features;
1429 #ifdef DEBUG_FEATURES
1430 print_features(stderr, fprintf, cpu_def->features, NULL);
1431 #endif
1432 free(s);
1433 return 0;
1435 error:
1436 free(s);
1437 return -1;
1440 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
1442 unsigned int i;
1444 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1445 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1446 sparc_defs[i].name,
1447 sparc_defs[i].iu_version,
1448 sparc_defs[i].fpu_version,
1449 sparc_defs[i].mmu_version,
1450 sparc_defs[i].nwindows);
1451 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1452 ~sparc_defs[i].features, "-");
1453 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1454 sparc_defs[i].features, "+");
1455 (*cpu_fprintf)(f, "\n");
1457 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1458 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1459 (*cpu_fprintf)(f, "\n");
1460 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1461 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1462 (*cpu_fprintf)(f, "\n");
1463 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1464 "fpu_version mmu_version nwindows\n");
1467 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
1468 uint32_t cc)
1470 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1471 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1472 cc & PSR_CARRY? 'C' : '-');
1475 #ifdef TARGET_SPARC64
1476 #define REGS_PER_LINE 4
1477 #else
1478 #define REGS_PER_LINE 8
1479 #endif
1481 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1482 int flags)
1484 int i, x;
1486 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1487 env->npc);
1488 cpu_fprintf(f, "General Registers:\n");
1490 for (i = 0; i < 8; i++) {
1491 if (i % REGS_PER_LINE == 0) {
1492 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1494 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1495 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1496 cpu_fprintf(f, "\n");
1499 cpu_fprintf(f, "\nCurrent Register Window:\n");
1500 for (x = 0; x < 3; x++) {
1501 for (i = 0; i < 8; i++) {
1502 if (i % REGS_PER_LINE == 0) {
1503 cpu_fprintf(f, "%%%c%d-%d: ",
1504 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1505 i, i + REGS_PER_LINE - 1);
1507 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1508 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1509 cpu_fprintf(f, "\n");
1513 cpu_fprintf(f, "\nFloating Point Registers:\n");
1514 for (i = 0; i < TARGET_FPREGS; i++) {
1515 if ((i & 3) == 0)
1516 cpu_fprintf(f, "%%f%02d:", i);
1517 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1518 if ((i & 3) == 3)
1519 cpu_fprintf(f, "\n");
1521 #ifdef TARGET_SPARC64
1522 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1523 (unsigned)cpu_get_ccr(env));
1524 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1525 cpu_fprintf(f, " xcc: ");
1526 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1527 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1528 env->psrpil);
1529 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1530 "cleanwin: %d cwp: %d\n",
1531 env->cansave, env->canrestore, env->otherwin, env->wstate,
1532 env->cleanwin, env->nwindows - 1 - env->cwp);
1533 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1534 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1535 #else
1536 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1537 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1538 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1539 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1540 env->wim);
1541 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1542 env->fsr, env->y);
1543 #endif