Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
[qemu.git] / target-sparc / helper.c
blobe9b42d03a908d9a721646e0c30fea4c494d44e28
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 "exec-all.h"
27 #include "qemu-common.h"
29 //#define DEBUG_MMU
30 //#define DEBUG_FEATURES
32 #ifdef DEBUG_MMU
33 #define DPRINTF_MMU(fmt, ...) \
34 do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
35 #else
36 #define DPRINTF_MMU(fmt, ...) do {} while (0)
37 #endif
39 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
41 /* Sparc MMU emulation */
43 #if defined(CONFIG_USER_ONLY)
45 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
46 int mmu_idx, int is_softmmu)
48 if (rw & 2)
49 env1->exception_index = TT_TFAULT;
50 else
51 env1->exception_index = TT_DFAULT;
52 return 1;
55 #else
57 #ifndef TARGET_SPARC64
59 * Sparc V8 Reference MMU (SRMMU)
61 static const int access_table[8][8] = {
62 { 0, 0, 0, 0, 8, 0, 12, 12 },
63 { 0, 0, 0, 0, 8, 0, 0, 0 },
64 { 8, 8, 0, 0, 0, 8, 12, 12 },
65 { 8, 8, 0, 0, 0, 8, 0, 0 },
66 { 8, 0, 8, 0, 8, 8, 12, 12 },
67 { 8, 0, 8, 0, 8, 0, 8, 0 },
68 { 8, 8, 8, 0, 8, 8, 12, 12 },
69 { 8, 8, 8, 0, 8, 8, 8, 0 }
72 static const int perm_table[2][8] = {
74 PAGE_READ,
75 PAGE_READ | PAGE_WRITE,
76 PAGE_READ | PAGE_EXEC,
77 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
78 PAGE_EXEC,
79 PAGE_READ | PAGE_WRITE,
80 PAGE_READ | PAGE_EXEC,
81 PAGE_READ | PAGE_WRITE | PAGE_EXEC
84 PAGE_READ,
85 PAGE_READ | PAGE_WRITE,
86 PAGE_READ | PAGE_EXEC,
87 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
88 PAGE_EXEC,
89 PAGE_READ,
95 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
96 int *prot, int *access_index,
97 target_ulong address, int rw, int mmu_idx,
98 target_ulong *page_size)
100 int access_perms = 0;
101 target_phys_addr_t pde_ptr;
102 uint32_t pde;
103 int error_code = 0, is_dirty, is_user;
104 unsigned long page_offset;
106 is_user = mmu_idx == MMU_USER_IDX;
108 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
109 *page_size = TARGET_PAGE_SIZE;
110 // Boot mode: instruction fetches are taken from PROM
111 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
112 *physical = env->prom_addr | (address & 0x7ffffULL);
113 *prot = PAGE_READ | PAGE_EXEC;
114 return 0;
116 *physical = address;
117 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
118 return 0;
121 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
122 *physical = 0xffffffffffff0000ULL;
124 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
125 /* Context base + context number */
126 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
127 pde = ldl_phys(pde_ptr);
129 /* Ctx pde */
130 switch (pde & PTE_ENTRYTYPE_MASK) {
131 default:
132 case 0: /* Invalid */
133 return 1 << 2;
134 case 2: /* L0 PTE, maybe should not happen? */
135 case 3: /* Reserved */
136 return 4 << 2;
137 case 1: /* L0 PDE */
138 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
139 pde = ldl_phys(pde_ptr);
141 switch (pde & PTE_ENTRYTYPE_MASK) {
142 default:
143 case 0: /* Invalid */
144 return (1 << 8) | (1 << 2);
145 case 3: /* Reserved */
146 return (1 << 8) | (4 << 2);
147 case 1: /* L1 PDE */
148 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
149 pde = ldl_phys(pde_ptr);
151 switch (pde & PTE_ENTRYTYPE_MASK) {
152 default:
153 case 0: /* Invalid */
154 return (2 << 8) | (1 << 2);
155 case 3: /* Reserved */
156 return (2 << 8) | (4 << 2);
157 case 1: /* L2 PDE */
158 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
159 pde = ldl_phys(pde_ptr);
161 switch (pde & PTE_ENTRYTYPE_MASK) {
162 default:
163 case 0: /* Invalid */
164 return (3 << 8) | (1 << 2);
165 case 1: /* PDE, should not happen */
166 case 3: /* Reserved */
167 return (3 << 8) | (4 << 2);
168 case 2: /* L3 PTE */
169 page_offset = (address & TARGET_PAGE_MASK) &
170 (TARGET_PAGE_SIZE - 1);
172 *page_size = TARGET_PAGE_SIZE;
173 break;
174 case 2: /* L2 PTE */
175 page_offset = address & 0x3ffff;
176 *page_size = 0x40000;
178 break;
179 case 2: /* L1 PTE */
180 page_offset = address & 0xffffff;
181 *page_size = 0x1000000;
185 /* check access */
186 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
187 error_code = access_table[*access_index][access_perms];
188 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
189 return error_code;
191 /* update page modified and dirty bits */
192 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
193 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
194 pde |= PG_ACCESSED_MASK;
195 if (is_dirty)
196 pde |= PG_MODIFIED_MASK;
197 stl_phys_notdirty(pde_ptr, pde);
200 /* the page can be put in the TLB */
201 *prot = perm_table[is_user][access_perms];
202 if (!(pde & PG_MODIFIED_MASK)) {
203 /* only set write access if already dirty... otherwise wait
204 for dirty access */
205 *prot &= ~PAGE_WRITE;
208 /* Even if large ptes, we map only one 4KB page in the cache to
209 avoid filling it too fast */
210 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
211 return error_code;
214 /* Perform address translation */
215 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
216 int mmu_idx, int is_softmmu)
218 target_phys_addr_t paddr;
219 target_ulong vaddr;
220 target_ulong page_size;
221 int error_code = 0, prot, access_index;
223 error_code = get_physical_address(env, &paddr, &prot, &access_index,
224 address, rw, mmu_idx, &page_size);
225 if (error_code == 0) {
226 vaddr = address & TARGET_PAGE_MASK;
227 paddr &= TARGET_PAGE_MASK;
228 #ifdef DEBUG_MMU
229 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
230 TARGET_FMT_lx "\n", address, paddr, vaddr);
231 #endif
232 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
233 return 0;
236 if (env->mmuregs[3]) /* Fault status register */
237 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
238 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
239 env->mmuregs[4] = address; /* Fault address register */
241 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
242 // No fault mode: if a mapping is available, just override
243 // permissions. If no mapping is available, redirect accesses to
244 // neverland. Fake/overridden mappings will be flushed when
245 // switching to normal mode.
246 vaddr = address & TARGET_PAGE_MASK;
247 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
248 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
249 return 0;
250 } else {
251 if (rw & 2)
252 env->exception_index = TT_TFAULT;
253 else
254 env->exception_index = TT_DFAULT;
255 return 1;
259 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
261 target_phys_addr_t pde_ptr;
262 uint32_t pde;
264 /* Context base + context number */
265 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
266 (env->mmuregs[2] << 2);
267 pde = ldl_phys(pde_ptr);
269 switch (pde & PTE_ENTRYTYPE_MASK) {
270 default:
271 case 0: /* Invalid */
272 case 2: /* PTE, maybe should not happen? */
273 case 3: /* Reserved */
274 return 0;
275 case 1: /* L1 PDE */
276 if (mmulev == 3)
277 return pde;
278 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
279 pde = ldl_phys(pde_ptr);
281 switch (pde & PTE_ENTRYTYPE_MASK) {
282 default:
283 case 0: /* Invalid */
284 case 3: /* Reserved */
285 return 0;
286 case 2: /* L1 PTE */
287 return pde;
288 case 1: /* L2 PDE */
289 if (mmulev == 2)
290 return pde;
291 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
292 pde = ldl_phys(pde_ptr);
294 switch (pde & PTE_ENTRYTYPE_MASK) {
295 default:
296 case 0: /* Invalid */
297 case 3: /* Reserved */
298 return 0;
299 case 2: /* L2 PTE */
300 return pde;
301 case 1: /* L3 PDE */
302 if (mmulev == 1)
303 return pde;
304 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
305 pde = ldl_phys(pde_ptr);
307 switch (pde & PTE_ENTRYTYPE_MASK) {
308 default:
309 case 0: /* Invalid */
310 case 1: /* PDE, should not happen */
311 case 3: /* Reserved */
312 return 0;
313 case 2: /* L3 PTE */
314 return pde;
319 return 0;
322 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
324 target_ulong va, va1, va2;
325 unsigned int n, m, o;
326 target_phys_addr_t pde_ptr, pa;
327 uint32_t pde;
329 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
330 pde = ldl_phys(pde_ptr);
331 (*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
332 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
333 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
334 pde = mmu_probe(env, va, 2);
335 if (pde) {
336 pa = cpu_get_phys_page_debug(env, va);
337 (*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
338 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
339 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
340 pde = mmu_probe(env, va1, 1);
341 if (pde) {
342 pa = cpu_get_phys_page_debug(env, va1);
343 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
344 TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
345 va1, pa, pde);
346 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
347 pde = mmu_probe(env, va2, 0);
348 if (pde) {
349 pa = cpu_get_phys_page_debug(env, va2);
350 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
351 TARGET_FMT_plx " PTE: "
352 TARGET_FMT_lx "\n",
353 va2, pa, pde);
362 #else /* !TARGET_SPARC64 */
364 // 41 bit physical address space
365 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
367 return x & 0x1ffffffffffULL;
371 * UltraSparc IIi I/DMMUs
374 // Returns true if TTE tag is valid and matches virtual address value in context
375 // requires virtual address mask value calculated from TTE entry size
376 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
377 uint64_t address, uint64_t context,
378 target_phys_addr_t *physical)
380 uint64_t mask;
382 switch ((tlb->tte >> 61) & 3) {
383 default:
384 case 0x0: // 8k
385 mask = 0xffffffffffffe000ULL;
386 break;
387 case 0x1: // 64k
388 mask = 0xffffffffffff0000ULL;
389 break;
390 case 0x2: // 512k
391 mask = 0xfffffffffff80000ULL;
392 break;
393 case 0x3: // 4M
394 mask = 0xffffffffffc00000ULL;
395 break;
398 // valid, context match, virtual address match?
399 if (TTE_IS_VALID(tlb->tte) &&
400 (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
401 && compare_masked(address, tlb->tag, mask))
403 // decode physical address
404 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
405 return 1;
408 return 0;
411 static int get_physical_address_data(CPUState *env,
412 target_phys_addr_t *physical, int *prot,
413 target_ulong address, int rw, int mmu_idx)
415 unsigned int i;
416 uint64_t context;
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 break;
432 case MMU_USER_SECONDARY_IDX:
433 case MMU_KERNEL_SECONDARY_IDX:
434 context = env->dmmu.mmu_secondary_context & 0x1fff;
435 break;
436 case MMU_NUCLEUS_IDX:
437 default:
438 context = 0;
439 break;
442 for (i = 0; i < 64; i++) {
443 // ctx match, vaddr match, valid?
444 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
446 uint8_t fault_type = 0;
448 // access ok?
449 if ((env->dtlb[i].tte & 0x4) && is_user) {
450 fault_type |= 1; /* privilege violation */
451 env->exception_index = TT_DFAULT;
453 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
454 " mmu_idx=%d tl=%d\n",
455 address, context, mmu_idx, env->tl);
456 } else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) {
457 env->exception_index = TT_DPROT;
459 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
460 " mmu_idx=%d tl=%d\n",
461 address, context, mmu_idx, env->tl);
462 } else {
463 *prot = PAGE_READ;
464 if (env->dtlb[i].tte & 0x2)
465 *prot |= PAGE_WRITE;
467 TTE_SET_USED(env->dtlb[i].tte);
469 return 0;
472 if (env->dmmu.sfsr & 1) /* Fault status register */
473 env->dmmu.sfsr = 2; /* overflow (not read before
474 another fault) */
476 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
478 env->dmmu.sfsr |= (fault_type << 7);
480 env->dmmu.sfar = address; /* Fault address register */
482 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
484 return 1;
488 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
489 address, context);
491 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
492 env->exception_index = TT_DMISS;
493 return 1;
496 static int get_physical_address_code(CPUState *env,
497 target_phys_addr_t *physical, int *prot,
498 target_ulong address, int mmu_idx)
500 unsigned int i;
501 uint64_t context;
503 int is_user = (mmu_idx == MMU_USER_IDX ||
504 mmu_idx == MMU_USER_SECONDARY_IDX);
506 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
507 /* IMMU disabled */
508 *physical = ultrasparc_truncate_physical(address);
509 *prot = PAGE_EXEC;
510 return 0;
513 if (env->tl == 0) {
514 /* PRIMARY context */
515 context = env->dmmu.mmu_primary_context & 0x1fff;
516 } else {
517 /* NUCLEUS context */
518 context = 0;
521 for (i = 0; i < 64; i++) {
522 // ctx match, vaddr match, valid?
523 if (ultrasparc_tag_match(&env->itlb[i],
524 address, context, physical)) {
525 // access ok?
526 if ((env->itlb[i].tte & 0x4) && is_user) {
527 if (env->immu.sfsr) /* Fault status register */
528 env->immu.sfsr = 2; /* overflow (not read before
529 another fault) */
530 env->immu.sfsr |= (is_user << 3) | 1;
531 env->exception_index = TT_TFAULT;
533 env->immu.tag_access = (address & ~0x1fffULL) | context;
535 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
536 address, context);
538 return 1;
540 *prot = PAGE_EXEC;
541 TTE_SET_USED(env->itlb[i].tte);
542 return 0;
546 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
547 address, context);
549 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
550 env->immu.tag_access = (address & ~0x1fffULL) | context;
551 env->exception_index = TT_TMISS;
552 return 1;
555 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
556 int *prot, int *access_index,
557 target_ulong address, int rw, int mmu_idx,
558 target_ulong *page_size)
560 /* ??? We treat everything as a small page, then explicitly flush
561 everything when an entry is evicted. */
562 *page_size = TARGET_PAGE_SIZE;
564 #if defined (DEBUG_MMU)
565 /* safety net to catch wrong softmmu index use from dynamic code */
566 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
567 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
568 " primary context=%" PRIx64
569 " secondary context=%" PRIx64
570 " address=%" PRIx64
571 "\n",
572 (rw == 2 ? "CODE" : "DATA"),
573 env->tl, mmu_idx,
574 env->dmmu.mmu_primary_context,
575 env->dmmu.mmu_secondary_context,
576 address);
578 #endif
580 if (rw == 2)
581 return get_physical_address_code(env, physical, prot, address,
582 mmu_idx);
583 else
584 return get_physical_address_data(env, physical, prot, address, rw,
585 mmu_idx);
588 /* Perform address translation */
589 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
590 int mmu_idx, int is_softmmu)
592 target_ulong virt_addr, vaddr;
593 target_phys_addr_t paddr;
594 target_ulong page_size;
595 int error_code = 0, prot, access_index;
597 error_code = get_physical_address(env, &paddr, &prot, &access_index,
598 address, rw, mmu_idx, &page_size);
599 if (error_code == 0) {
600 virt_addr = address & TARGET_PAGE_MASK;
601 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
602 (TARGET_PAGE_SIZE - 1));
604 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
605 " vaddr %" PRIx64
606 " mmu_idx=%d"
607 " tl=%d"
608 " primary context=%" PRIx64
609 " secondary context=%" PRIx64
610 "\n",
611 address, paddr, vaddr, mmu_idx, env->tl,
612 env->dmmu.mmu_primary_context,
613 env->dmmu.mmu_secondary_context);
615 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
616 return 0;
618 // XXX
619 return 1;
622 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
624 unsigned int i;
625 const char *mask;
627 (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
628 PRId64 "\n",
629 env->dmmu.mmu_primary_context,
630 env->dmmu.mmu_secondary_context);
631 if ((env->lsu & DMMU_E) == 0) {
632 (*cpu_fprintf)(f, "DMMU disabled\n");
633 } else {
634 (*cpu_fprintf)(f, "DMMU dump\n");
635 for (i = 0; i < 64; i++) {
636 switch ((env->dtlb[i].tte >> 61) & 3) {
637 default:
638 case 0x0:
639 mask = " 8k";
640 break;
641 case 0x1:
642 mask = " 64k";
643 break;
644 case 0x2:
645 mask = "512k";
646 break;
647 case 0x3:
648 mask = " 4M";
649 break;
651 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
652 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
653 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
655 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
656 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
657 mask,
658 env->dtlb[i].tte & 0x4? "priv": "user",
659 env->dtlb[i].tte & 0x2? "RW": "RO",
660 env->dtlb[i].tte & 0x40? "locked": "unlocked",
661 env->dtlb[i].tag & (uint64_t)0x1fffULL,
662 TTE_IS_GLOBAL(env->dtlb[i].tte)?
663 "global" : "local");
667 if ((env->lsu & IMMU_E) == 0) {
668 (*cpu_fprintf)(f, "IMMU disabled\n");
669 } else {
670 (*cpu_fprintf)(f, "IMMU dump\n");
671 for (i = 0; i < 64; i++) {
672 switch ((env->itlb[i].tte >> 61) & 3) {
673 default:
674 case 0x0:
675 mask = " 8k";
676 break;
677 case 0x1:
678 mask = " 64k";
679 break;
680 case 0x2:
681 mask = "512k";
682 break;
683 case 0x3:
684 mask = " 4M";
685 break;
687 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
688 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
689 ", %s, %s, %s, ctx %" PRId64 " %s\n",
691 env->itlb[i].tag & (uint64_t)~0x1fffULL,
692 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
693 mask,
694 env->itlb[i].tte & 0x4? "priv": "user",
695 env->itlb[i].tte & 0x40? "locked": "unlocked",
696 env->itlb[i].tag & (uint64_t)0x1fffULL,
697 TTE_IS_GLOBAL(env->itlb[i].tte)?
698 "global" : "local");
704 #endif /* TARGET_SPARC64 */
705 #endif /* !CONFIG_USER_ONLY */
708 #if !defined(CONFIG_USER_ONLY)
709 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
710 int mmu_idx)
712 target_phys_addr_t phys_addr;
713 target_ulong page_size;
714 int prot, access_index;
716 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
717 mmu_idx, &page_size) != 0)
718 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
719 0, mmu_idx, &page_size) != 0)
720 return -1;
721 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
722 return -1;
723 return phys_addr;
726 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
728 return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
730 #endif
732 void cpu_reset(CPUSPARCState *env)
734 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
735 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
736 log_cpu_state(env, 0);
739 tlb_flush(env, 1);
740 env->cwp = 0;
741 #ifndef TARGET_SPARC64
742 env->wim = 1;
743 #endif
744 env->regwptr = env->regbase + (env->cwp * 16);
745 CC_OP = CC_OP_FLAGS;
746 #if defined(CONFIG_USER_ONLY)
747 #ifdef TARGET_SPARC64
748 env->cleanwin = env->nwindows - 2;
749 env->cansave = env->nwindows - 2;
750 env->pstate = PS_RMO | PS_PEF | PS_IE;
751 env->asi = 0x82; // Primary no-fault
752 #endif
753 #else
754 #if !defined(TARGET_SPARC64)
755 env->psret = 0;
756 env->psrs = 1;
757 env->psrps = 1;
758 #endif
759 #ifdef TARGET_SPARC64
760 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
761 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
762 env->tl = env->maxtl;
763 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
764 env->lsu = 0;
765 #else
766 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
767 env->mmuregs[0] |= env->def->mmu_bm;
768 #endif
769 env->pc = 0;
770 env->npc = env->pc + 4;
771 #endif
772 env->cache_control = 0;
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 | CPU_FEATURE_TA0_SHUTDOWN,
1280 .name = "LEON3",
1281 .iu_version = 0xf3000000,
1282 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1283 .mmu_version = 0xf3000000,
1284 .mmu_bm = 0x00000000,
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 | CPU_FEATURE_TA0_SHUTDOWN |
1291 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
1293 #endif
1296 static const char * const feature_name[] = {
1297 "float",
1298 "float128",
1299 "swap",
1300 "mul",
1301 "div",
1302 "flush",
1303 "fsqrt",
1304 "fmul",
1305 "vis1",
1306 "vis2",
1307 "fsmuld",
1308 "hypv",
1309 "cmt",
1310 "gl",
1313 static void print_features(FILE *f, fprintf_function cpu_fprintf,
1314 uint32_t features, const char *prefix)
1316 unsigned int i;
1318 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1319 if (feature_name[i] && (features & (1 << i))) {
1320 if (prefix)
1321 (*cpu_fprintf)(f, "%s", prefix);
1322 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1326 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1328 unsigned int i;
1330 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1331 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1332 *features |= 1 << i;
1333 return;
1335 fprintf(stderr, "CPU feature %s not found\n", flagname);
1338 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1340 unsigned int i;
1341 const sparc_def_t *def = NULL;
1342 char *s = strdup(cpu_model);
1343 char *featurestr, *name = strtok(s, ",");
1344 uint32_t plus_features = 0;
1345 uint32_t minus_features = 0;
1346 uint64_t iu_version;
1347 uint32_t fpu_version, mmu_version, nwindows;
1349 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1350 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1351 def = &sparc_defs[i];
1354 if (!def)
1355 goto error;
1356 memcpy(cpu_def, def, sizeof(*def));
1358 featurestr = strtok(NULL, ",");
1359 while (featurestr) {
1360 char *val;
1362 if (featurestr[0] == '+') {
1363 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1364 } else if (featurestr[0] == '-') {
1365 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1366 } else if ((val = strchr(featurestr, '='))) {
1367 *val = 0; val++;
1368 if (!strcmp(featurestr, "iu_version")) {
1369 char *err;
1371 iu_version = strtoll(val, &err, 0);
1372 if (!*val || *err) {
1373 fprintf(stderr, "bad numerical value %s\n", val);
1374 goto error;
1376 cpu_def->iu_version = iu_version;
1377 #ifdef DEBUG_FEATURES
1378 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1379 #endif
1380 } else if (!strcmp(featurestr, "fpu_version")) {
1381 char *err;
1383 fpu_version = strtol(val, &err, 0);
1384 if (!*val || *err) {
1385 fprintf(stderr, "bad numerical value %s\n", val);
1386 goto error;
1388 cpu_def->fpu_version = fpu_version;
1389 #ifdef DEBUG_FEATURES
1390 fprintf(stderr, "fpu_version %x\n", fpu_version);
1391 #endif
1392 } else if (!strcmp(featurestr, "mmu_version")) {
1393 char *err;
1395 mmu_version = strtol(val, &err, 0);
1396 if (!*val || *err) {
1397 fprintf(stderr, "bad numerical value %s\n", val);
1398 goto error;
1400 cpu_def->mmu_version = mmu_version;
1401 #ifdef DEBUG_FEATURES
1402 fprintf(stderr, "mmu_version %x\n", mmu_version);
1403 #endif
1404 } else if (!strcmp(featurestr, "nwindows")) {
1405 char *err;
1407 nwindows = strtol(val, &err, 0);
1408 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1409 nwindows < MIN_NWINDOWS) {
1410 fprintf(stderr, "bad numerical value %s\n", val);
1411 goto error;
1413 cpu_def->nwindows = nwindows;
1414 #ifdef DEBUG_FEATURES
1415 fprintf(stderr, "nwindows %d\n", nwindows);
1416 #endif
1417 } else {
1418 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1419 goto error;
1421 } else {
1422 fprintf(stderr, "feature string `%s' not in format "
1423 "(+feature|-feature|feature=xyz)\n", featurestr);
1424 goto error;
1426 featurestr = strtok(NULL, ",");
1428 cpu_def->features |= plus_features;
1429 cpu_def->features &= ~minus_features;
1430 #ifdef DEBUG_FEATURES
1431 print_features(stderr, fprintf, cpu_def->features, NULL);
1432 #endif
1433 free(s);
1434 return 0;
1436 error:
1437 free(s);
1438 return -1;
1441 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
1443 unsigned int i;
1445 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1446 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1447 sparc_defs[i].name,
1448 sparc_defs[i].iu_version,
1449 sparc_defs[i].fpu_version,
1450 sparc_defs[i].mmu_version,
1451 sparc_defs[i].nwindows);
1452 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1453 ~sparc_defs[i].features, "-");
1454 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1455 sparc_defs[i].features, "+");
1456 (*cpu_fprintf)(f, "\n");
1458 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1459 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1460 (*cpu_fprintf)(f, "\n");
1461 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1462 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1463 (*cpu_fprintf)(f, "\n");
1464 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1465 "fpu_version mmu_version nwindows\n");
1468 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
1469 uint32_t cc)
1471 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1472 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1473 cc & PSR_CARRY? 'C' : '-');
1476 #ifdef TARGET_SPARC64
1477 #define REGS_PER_LINE 4
1478 #else
1479 #define REGS_PER_LINE 8
1480 #endif
1482 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1483 int flags)
1485 int i, x;
1487 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1488 env->npc);
1489 cpu_fprintf(f, "General Registers:\n");
1491 for (i = 0; i < 8; i++) {
1492 if (i % REGS_PER_LINE == 0) {
1493 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1495 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1496 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1497 cpu_fprintf(f, "\n");
1500 cpu_fprintf(f, "\nCurrent Register Window:\n");
1501 for (x = 0; x < 3; x++) {
1502 for (i = 0; i < 8; i++) {
1503 if (i % REGS_PER_LINE == 0) {
1504 cpu_fprintf(f, "%%%c%d-%d: ",
1505 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1506 i, i + REGS_PER_LINE - 1);
1508 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1509 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1510 cpu_fprintf(f, "\n");
1514 cpu_fprintf(f, "\nFloating Point Registers:\n");
1515 for (i = 0; i < TARGET_FPREGS; i++) {
1516 if ((i & 3) == 0)
1517 cpu_fprintf(f, "%%f%02d:", i);
1518 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1519 if ((i & 3) == 3)
1520 cpu_fprintf(f, "\n");
1522 #ifdef TARGET_SPARC64
1523 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1524 (unsigned)cpu_get_ccr(env));
1525 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1526 cpu_fprintf(f, " xcc: ");
1527 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1528 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1529 env->psrpil);
1530 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1531 "cleanwin: %d cwp: %d\n",
1532 env->cansave, env->canrestore, env->otherwin, env->wstate,
1533 env->cleanwin, env->nwindows - 1 - env->cwp);
1534 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1535 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1536 #else
1537 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1538 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1539 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1540 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1541 env->wim);
1542 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1543 env->fsr, env->y);
1544 #endif