sparc: move do_interrupt to helper.c
[qemu.git] / target-sparc / helper.c
blob6b3510585db4a6421e79d0f9a28187d6af45e29d
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 #ifdef TARGET_SPARC64
733 #ifdef DEBUG_PCALL
734 static const char * const excp_names[0x80] = {
735 [TT_TFAULT] = "Instruction Access Fault",
736 [TT_TMISS] = "Instruction Access MMU Miss",
737 [TT_CODE_ACCESS] = "Instruction Access Error",
738 [TT_ILL_INSN] = "Illegal Instruction",
739 [TT_PRIV_INSN] = "Privileged Instruction",
740 [TT_NFPU_INSN] = "FPU Disabled",
741 [TT_FP_EXCP] = "FPU Exception",
742 [TT_TOVF] = "Tag Overflow",
743 [TT_CLRWIN] = "Clean Windows",
744 [TT_DIV_ZERO] = "Division By Zero",
745 [TT_DFAULT] = "Data Access Fault",
746 [TT_DMISS] = "Data Access MMU Miss",
747 [TT_DATA_ACCESS] = "Data Access Error",
748 [TT_DPROT] = "Data Protection Error",
749 [TT_UNALIGNED] = "Unaligned Memory Access",
750 [TT_PRIV_ACT] = "Privileged Action",
751 [TT_EXTINT | 0x1] = "External Interrupt 1",
752 [TT_EXTINT | 0x2] = "External Interrupt 2",
753 [TT_EXTINT | 0x3] = "External Interrupt 3",
754 [TT_EXTINT | 0x4] = "External Interrupt 4",
755 [TT_EXTINT | 0x5] = "External Interrupt 5",
756 [TT_EXTINT | 0x6] = "External Interrupt 6",
757 [TT_EXTINT | 0x7] = "External Interrupt 7",
758 [TT_EXTINT | 0x8] = "External Interrupt 8",
759 [TT_EXTINT | 0x9] = "External Interrupt 9",
760 [TT_EXTINT | 0xa] = "External Interrupt 10",
761 [TT_EXTINT | 0xb] = "External Interrupt 11",
762 [TT_EXTINT | 0xc] = "External Interrupt 12",
763 [TT_EXTINT | 0xd] = "External Interrupt 13",
764 [TT_EXTINT | 0xe] = "External Interrupt 14",
765 [TT_EXTINT | 0xf] = "External Interrupt 15",
767 #endif
769 void do_interrupt(CPUState *env)
771 int intno = env->exception_index;
772 trap_state *tsptr;
774 #ifdef DEBUG_PCALL
775 if (qemu_loglevel_mask(CPU_LOG_INT)) {
776 static int count;
777 const char *name;
779 if (intno < 0 || intno >= 0x180) {
780 name = "Unknown";
781 } else if (intno >= 0x100) {
782 name = "Trap Instruction";
783 } else if (intno >= 0xc0) {
784 name = "Window Fill";
785 } else if (intno >= 0x80) {
786 name = "Window Spill";
787 } else {
788 name = excp_names[intno];
789 if (!name) {
790 name = "Unknown";
794 qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
795 " SP=%016" PRIx64 "\n",
796 count, name, intno,
797 env->pc,
798 env->npc, env->regwptr[6]);
799 log_cpu_state(env, 0);
800 #if 0
802 int i;
803 uint8_t *ptr;
805 qemu_log(" code=");
806 ptr = (uint8_t *)env->pc;
807 for (i = 0; i < 16; i++) {
808 qemu_log(" %02x", ldub(ptr + i));
810 qemu_log("\n");
812 #endif
813 count++;
815 #endif
816 #if !defined(CONFIG_USER_ONLY)
817 if (env->tl >= env->maxtl) {
818 cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
819 " Error state", env->exception_index, env->tl, env->maxtl);
820 return;
822 #endif
823 if (env->tl < env->maxtl - 1) {
824 env->tl++;
825 } else {
826 env->pstate |= PS_RED;
827 if (env->tl < env->maxtl) {
828 env->tl++;
831 tsptr = cpu_tsptr(env);
833 tsptr->tstate = (cpu_get_ccr(env) << 32) |
834 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
835 cpu_get_cwp64(env);
836 tsptr->tpc = env->pc;
837 tsptr->tnpc = env->npc;
838 tsptr->tt = intno;
840 switch (intno) {
841 case TT_IVEC:
842 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
843 break;
844 case TT_TFAULT:
845 case TT_DFAULT:
846 case TT_TMISS ... TT_TMISS + 3:
847 case TT_DMISS ... TT_DMISS + 3:
848 case TT_DPROT ... TT_DPROT + 3:
849 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
850 break;
851 default:
852 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
853 break;
856 if (intno == TT_CLRWIN) {
857 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
858 } else if ((intno & 0x1c0) == TT_SPILL) {
859 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
860 } else if ((intno & 0x1c0) == TT_FILL) {
861 cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
863 env->tbr &= ~0x7fffULL;
864 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
865 env->pc = env->tbr;
866 env->npc = env->pc + 4;
867 env->exception_index = -1;
869 #else
870 #ifdef DEBUG_PCALL
871 static const char * const excp_names[0x80] = {
872 [TT_TFAULT] = "Instruction Access Fault",
873 [TT_ILL_INSN] = "Illegal Instruction",
874 [TT_PRIV_INSN] = "Privileged Instruction",
875 [TT_NFPU_INSN] = "FPU Disabled",
876 [TT_WIN_OVF] = "Window Overflow",
877 [TT_WIN_UNF] = "Window Underflow",
878 [TT_UNALIGNED] = "Unaligned Memory Access",
879 [TT_FP_EXCP] = "FPU Exception",
880 [TT_DFAULT] = "Data Access Fault",
881 [TT_TOVF] = "Tag Overflow",
882 [TT_EXTINT | 0x1] = "External Interrupt 1",
883 [TT_EXTINT | 0x2] = "External Interrupt 2",
884 [TT_EXTINT | 0x3] = "External Interrupt 3",
885 [TT_EXTINT | 0x4] = "External Interrupt 4",
886 [TT_EXTINT | 0x5] = "External Interrupt 5",
887 [TT_EXTINT | 0x6] = "External Interrupt 6",
888 [TT_EXTINT | 0x7] = "External Interrupt 7",
889 [TT_EXTINT | 0x8] = "External Interrupt 8",
890 [TT_EXTINT | 0x9] = "External Interrupt 9",
891 [TT_EXTINT | 0xa] = "External Interrupt 10",
892 [TT_EXTINT | 0xb] = "External Interrupt 11",
893 [TT_EXTINT | 0xc] = "External Interrupt 12",
894 [TT_EXTINT | 0xd] = "External Interrupt 13",
895 [TT_EXTINT | 0xe] = "External Interrupt 14",
896 [TT_EXTINT | 0xf] = "External Interrupt 15",
897 [TT_TOVF] = "Tag Overflow",
898 [TT_CODE_ACCESS] = "Instruction Access Error",
899 [TT_DATA_ACCESS] = "Data Access Error",
900 [TT_DIV_ZERO] = "Division By Zero",
901 [TT_NCP_INSN] = "Coprocessor Disabled",
903 #endif
905 void do_interrupt(CPUState *env)
907 int cwp, intno = env->exception_index;
909 #ifdef DEBUG_PCALL
910 if (qemu_loglevel_mask(CPU_LOG_INT)) {
911 static int count;
912 const char *name;
914 if (intno < 0 || intno >= 0x100) {
915 name = "Unknown";
916 } else if (intno >= 0x80) {
917 name = "Trap Instruction";
918 } else {
919 name = excp_names[intno];
920 if (!name) {
921 name = "Unknown";
925 qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
926 count, name, intno,
927 env->pc,
928 env->npc, env->regwptr[6]);
929 log_cpu_state(env, 0);
930 #if 0
932 int i;
933 uint8_t *ptr;
935 qemu_log(" code=");
936 ptr = (uint8_t *)env->pc;
937 for (i = 0; i < 16; i++) {
938 qemu_log(" %02x", ldub(ptr + i));
940 qemu_log("\n");
942 #endif
943 count++;
945 #endif
946 #if !defined(CONFIG_USER_ONLY)
947 if (env->psret == 0) {
948 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
949 env->exception_index);
950 return;
952 #endif
953 env->psret = 0;
954 cwp = cpu_cwp_dec(env, env->cwp - 1);
955 cpu_set_cwp(env, cwp);
956 env->regwptr[9] = env->pc;
957 env->regwptr[10] = env->npc;
958 env->psrps = env->psrs;
959 env->psrs = 1;
960 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
961 env->pc = env->tbr;
962 env->npc = env->pc + 4;
963 env->exception_index = -1;
965 #if !defined(CONFIG_USER_ONLY)
966 /* IRQ acknowledgment */
967 if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
968 env->qemu_irq_ack(env->irq_manager, intno);
970 #endif
972 #endif
974 void cpu_reset(CPUSPARCState *env)
976 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
977 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
978 log_cpu_state(env, 0);
981 tlb_flush(env, 1);
982 env->cwp = 0;
983 #ifndef TARGET_SPARC64
984 env->wim = 1;
985 #endif
986 env->regwptr = env->regbase + (env->cwp * 16);
987 CC_OP = CC_OP_FLAGS;
988 #if defined(CONFIG_USER_ONLY)
989 #ifdef TARGET_SPARC64
990 env->cleanwin = env->nwindows - 2;
991 env->cansave = env->nwindows - 2;
992 env->pstate = PS_RMO | PS_PEF | PS_IE;
993 env->asi = 0x82; // Primary no-fault
994 #endif
995 #else
996 #if !defined(TARGET_SPARC64)
997 env->psret = 0;
998 env->psrs = 1;
999 env->psrps = 1;
1000 #endif
1001 #ifdef TARGET_SPARC64
1002 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
1003 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
1004 env->tl = env->maxtl;
1005 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
1006 env->lsu = 0;
1007 #else
1008 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
1009 env->mmuregs[0] |= env->def->mmu_bm;
1010 #endif
1011 env->pc = 0;
1012 env->npc = env->pc + 4;
1013 #endif
1014 env->cache_control = 0;
1017 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
1019 sparc_def_t def1, *def = &def1;
1021 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
1022 return -1;
1024 env->def = qemu_mallocz(sizeof(*def));
1025 memcpy(env->def, def, sizeof(*def));
1026 #if defined(CONFIG_USER_ONLY)
1027 if ((env->def->features & CPU_FEATURE_FLOAT))
1028 env->def->features |= CPU_FEATURE_FLOAT128;
1029 #endif
1030 env->cpu_model_str = cpu_model;
1031 env->version = def->iu_version;
1032 env->fsr = def->fpu_version;
1033 env->nwindows = def->nwindows;
1034 #if !defined(TARGET_SPARC64)
1035 env->mmuregs[0] |= def->mmu_version;
1036 cpu_sparc_set_id(env, 0);
1037 env->mxccregs[7] |= def->mxcc_version;
1038 #else
1039 env->mmu_version = def->mmu_version;
1040 env->maxtl = def->maxtl;
1041 env->version |= def->maxtl << 8;
1042 env->version |= def->nwindows - 1;
1043 #endif
1044 return 0;
1047 static void cpu_sparc_close(CPUSPARCState *env)
1049 free(env->def);
1050 free(env);
1053 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
1055 CPUSPARCState *env;
1057 env = qemu_mallocz(sizeof(CPUSPARCState));
1058 cpu_exec_init(env);
1060 gen_intermediate_code_init(env);
1062 if (cpu_sparc_register(env, cpu_model) < 0) {
1063 cpu_sparc_close(env);
1064 return NULL;
1066 qemu_init_vcpu(env);
1068 return env;
1071 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
1073 #if !defined(TARGET_SPARC64)
1074 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
1075 #endif
1078 static const sparc_def_t sparc_defs[] = {
1079 #ifdef TARGET_SPARC64
1081 .name = "Fujitsu Sparc64",
1082 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
1083 .fpu_version = 0x00000000,
1084 .mmu_version = mmu_us_12,
1085 .nwindows = 4,
1086 .maxtl = 4,
1087 .features = CPU_DEFAULT_FEATURES,
1090 .name = "Fujitsu Sparc64 III",
1091 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
1092 .fpu_version = 0x00000000,
1093 .mmu_version = mmu_us_12,
1094 .nwindows = 5,
1095 .maxtl = 4,
1096 .features = CPU_DEFAULT_FEATURES,
1099 .name = "Fujitsu Sparc64 IV",
1100 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
1101 .fpu_version = 0x00000000,
1102 .mmu_version = mmu_us_12,
1103 .nwindows = 8,
1104 .maxtl = 5,
1105 .features = CPU_DEFAULT_FEATURES,
1108 .name = "Fujitsu Sparc64 V",
1109 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
1110 .fpu_version = 0x00000000,
1111 .mmu_version = mmu_us_12,
1112 .nwindows = 8,
1113 .maxtl = 5,
1114 .features = CPU_DEFAULT_FEATURES,
1117 .name = "TI UltraSparc I",
1118 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1119 .fpu_version = 0x00000000,
1120 .mmu_version = mmu_us_12,
1121 .nwindows = 8,
1122 .maxtl = 5,
1123 .features = CPU_DEFAULT_FEATURES,
1126 .name = "TI UltraSparc II",
1127 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
1128 .fpu_version = 0x00000000,
1129 .mmu_version = mmu_us_12,
1130 .nwindows = 8,
1131 .maxtl = 5,
1132 .features = CPU_DEFAULT_FEATURES,
1135 .name = "TI UltraSparc IIi",
1136 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
1137 .fpu_version = 0x00000000,
1138 .mmu_version = mmu_us_12,
1139 .nwindows = 8,
1140 .maxtl = 5,
1141 .features = CPU_DEFAULT_FEATURES,
1144 .name = "TI UltraSparc IIe",
1145 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
1146 .fpu_version = 0x00000000,
1147 .mmu_version = mmu_us_12,
1148 .nwindows = 8,
1149 .maxtl = 5,
1150 .features = CPU_DEFAULT_FEATURES,
1153 .name = "Sun UltraSparc III",
1154 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
1155 .fpu_version = 0x00000000,
1156 .mmu_version = mmu_us_12,
1157 .nwindows = 8,
1158 .maxtl = 5,
1159 .features = CPU_DEFAULT_FEATURES,
1162 .name = "Sun UltraSparc III Cu",
1163 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
1164 .fpu_version = 0x00000000,
1165 .mmu_version = mmu_us_3,
1166 .nwindows = 8,
1167 .maxtl = 5,
1168 .features = CPU_DEFAULT_FEATURES,
1171 .name = "Sun UltraSparc IIIi",
1172 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
1173 .fpu_version = 0x00000000,
1174 .mmu_version = mmu_us_12,
1175 .nwindows = 8,
1176 .maxtl = 5,
1177 .features = CPU_DEFAULT_FEATURES,
1180 .name = "Sun UltraSparc IV",
1181 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
1182 .fpu_version = 0x00000000,
1183 .mmu_version = mmu_us_4,
1184 .nwindows = 8,
1185 .maxtl = 5,
1186 .features = CPU_DEFAULT_FEATURES,
1189 .name = "Sun UltraSparc IV+",
1190 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
1191 .fpu_version = 0x00000000,
1192 .mmu_version = mmu_us_12,
1193 .nwindows = 8,
1194 .maxtl = 5,
1195 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
1198 .name = "Sun UltraSparc IIIi+",
1199 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
1200 .fpu_version = 0x00000000,
1201 .mmu_version = mmu_us_3,
1202 .nwindows = 8,
1203 .maxtl = 5,
1204 .features = CPU_DEFAULT_FEATURES,
1207 .name = "Sun UltraSparc T1",
1208 // defined in sparc_ifu_fdp.v and ctu.h
1209 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
1210 .fpu_version = 0x00000000,
1211 .mmu_version = mmu_sun4v,
1212 .nwindows = 8,
1213 .maxtl = 6,
1214 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1215 | CPU_FEATURE_GL,
1218 .name = "Sun UltraSparc T2",
1219 // defined in tlu_asi_ctl.v and n2_revid_cust.v
1220 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
1221 .fpu_version = 0x00000000,
1222 .mmu_version = mmu_sun4v,
1223 .nwindows = 8,
1224 .maxtl = 6,
1225 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1226 | CPU_FEATURE_GL,
1229 .name = "NEC UltraSparc I",
1230 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1231 .fpu_version = 0x00000000,
1232 .mmu_version = mmu_us_12,
1233 .nwindows = 8,
1234 .maxtl = 5,
1235 .features = CPU_DEFAULT_FEATURES,
1237 #else
1239 .name = "Fujitsu MB86900",
1240 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1241 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1242 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1243 .mmu_bm = 0x00004000,
1244 .mmu_ctpr_mask = 0x007ffff0,
1245 .mmu_cxr_mask = 0x0000003f,
1246 .mmu_sfsr_mask = 0xffffffff,
1247 .mmu_trcr_mask = 0xffffffff,
1248 .nwindows = 7,
1249 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1252 .name = "Fujitsu MB86904",
1253 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1254 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1255 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1256 .mmu_bm = 0x00004000,
1257 .mmu_ctpr_mask = 0x00ffffc0,
1258 .mmu_cxr_mask = 0x000000ff,
1259 .mmu_sfsr_mask = 0x00016fff,
1260 .mmu_trcr_mask = 0x00ffffff,
1261 .nwindows = 8,
1262 .features = CPU_DEFAULT_FEATURES,
1265 .name = "Fujitsu MB86907",
1266 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1267 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1268 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1269 .mmu_bm = 0x00004000,
1270 .mmu_ctpr_mask = 0xffffffc0,
1271 .mmu_cxr_mask = 0x000000ff,
1272 .mmu_sfsr_mask = 0x00016fff,
1273 .mmu_trcr_mask = 0xffffffff,
1274 .nwindows = 8,
1275 .features = CPU_DEFAULT_FEATURES,
1278 .name = "LSI L64811",
1279 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1280 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1281 .mmu_version = 0x10 << 24,
1282 .mmu_bm = 0x00004000,
1283 .mmu_ctpr_mask = 0x007ffff0,
1284 .mmu_cxr_mask = 0x0000003f,
1285 .mmu_sfsr_mask = 0xffffffff,
1286 .mmu_trcr_mask = 0xffffffff,
1287 .nwindows = 8,
1288 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1289 CPU_FEATURE_FSMULD,
1292 .name = "Cypress CY7C601",
1293 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1294 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1295 .mmu_version = 0x10 << 24,
1296 .mmu_bm = 0x00004000,
1297 .mmu_ctpr_mask = 0x007ffff0,
1298 .mmu_cxr_mask = 0x0000003f,
1299 .mmu_sfsr_mask = 0xffffffff,
1300 .mmu_trcr_mask = 0xffffffff,
1301 .nwindows = 8,
1302 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1303 CPU_FEATURE_FSMULD,
1306 .name = "Cypress CY7C611",
1307 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1308 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1309 .mmu_version = 0x10 << 24,
1310 .mmu_bm = 0x00004000,
1311 .mmu_ctpr_mask = 0x007ffff0,
1312 .mmu_cxr_mask = 0x0000003f,
1313 .mmu_sfsr_mask = 0xffffffff,
1314 .mmu_trcr_mask = 0xffffffff,
1315 .nwindows = 8,
1316 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1317 CPU_FEATURE_FSMULD,
1320 .name = "TI MicroSparc I",
1321 .iu_version = 0x41000000,
1322 .fpu_version = 4 << 17,
1323 .mmu_version = 0x41000000,
1324 .mmu_bm = 0x00004000,
1325 .mmu_ctpr_mask = 0x007ffff0,
1326 .mmu_cxr_mask = 0x0000003f,
1327 .mmu_sfsr_mask = 0x00016fff,
1328 .mmu_trcr_mask = 0x0000003f,
1329 .nwindows = 7,
1330 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1331 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1332 CPU_FEATURE_FMUL,
1335 .name = "TI MicroSparc II",
1336 .iu_version = 0x42000000,
1337 .fpu_version = 4 << 17,
1338 .mmu_version = 0x02000000,
1339 .mmu_bm = 0x00004000,
1340 .mmu_ctpr_mask = 0x00ffffc0,
1341 .mmu_cxr_mask = 0x000000ff,
1342 .mmu_sfsr_mask = 0x00016fff,
1343 .mmu_trcr_mask = 0x00ffffff,
1344 .nwindows = 8,
1345 .features = CPU_DEFAULT_FEATURES,
1348 .name = "TI MicroSparc IIep",
1349 .iu_version = 0x42000000,
1350 .fpu_version = 4 << 17,
1351 .mmu_version = 0x04000000,
1352 .mmu_bm = 0x00004000,
1353 .mmu_ctpr_mask = 0x00ffffc0,
1354 .mmu_cxr_mask = 0x000000ff,
1355 .mmu_sfsr_mask = 0x00016bff,
1356 .mmu_trcr_mask = 0x00ffffff,
1357 .nwindows = 8,
1358 .features = CPU_DEFAULT_FEATURES,
1361 .name = "TI SuperSparc 40", // STP1020NPGA
1362 .iu_version = 0x41000000, // SuperSPARC 2.x
1363 .fpu_version = 0 << 17,
1364 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1365 .mmu_bm = 0x00002000,
1366 .mmu_ctpr_mask = 0xffffffc0,
1367 .mmu_cxr_mask = 0x0000ffff,
1368 .mmu_sfsr_mask = 0xffffffff,
1369 .mmu_trcr_mask = 0xffffffff,
1370 .nwindows = 8,
1371 .features = CPU_DEFAULT_FEATURES,
1374 .name = "TI SuperSparc 50", // STP1020PGA
1375 .iu_version = 0x40000000, // SuperSPARC 3.x
1376 .fpu_version = 0 << 17,
1377 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1378 .mmu_bm = 0x00002000,
1379 .mmu_ctpr_mask = 0xffffffc0,
1380 .mmu_cxr_mask = 0x0000ffff,
1381 .mmu_sfsr_mask = 0xffffffff,
1382 .mmu_trcr_mask = 0xffffffff,
1383 .nwindows = 8,
1384 .features = CPU_DEFAULT_FEATURES,
1387 .name = "TI SuperSparc 51",
1388 .iu_version = 0x40000000, // SuperSPARC 3.x
1389 .fpu_version = 0 << 17,
1390 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1391 .mmu_bm = 0x00002000,
1392 .mmu_ctpr_mask = 0xffffffc0,
1393 .mmu_cxr_mask = 0x0000ffff,
1394 .mmu_sfsr_mask = 0xffffffff,
1395 .mmu_trcr_mask = 0xffffffff,
1396 .mxcc_version = 0x00000104,
1397 .nwindows = 8,
1398 .features = CPU_DEFAULT_FEATURES,
1401 .name = "TI SuperSparc 60", // STP1020APGA
1402 .iu_version = 0x40000000, // SuperSPARC 3.x
1403 .fpu_version = 0 << 17,
1404 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1405 .mmu_bm = 0x00002000,
1406 .mmu_ctpr_mask = 0xffffffc0,
1407 .mmu_cxr_mask = 0x0000ffff,
1408 .mmu_sfsr_mask = 0xffffffff,
1409 .mmu_trcr_mask = 0xffffffff,
1410 .nwindows = 8,
1411 .features = CPU_DEFAULT_FEATURES,
1414 .name = "TI SuperSparc 61",
1415 .iu_version = 0x44000000, // SuperSPARC 3.x
1416 .fpu_version = 0 << 17,
1417 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1418 .mmu_bm = 0x00002000,
1419 .mmu_ctpr_mask = 0xffffffc0,
1420 .mmu_cxr_mask = 0x0000ffff,
1421 .mmu_sfsr_mask = 0xffffffff,
1422 .mmu_trcr_mask = 0xffffffff,
1423 .mxcc_version = 0x00000104,
1424 .nwindows = 8,
1425 .features = CPU_DEFAULT_FEATURES,
1428 .name = "TI SuperSparc II",
1429 .iu_version = 0x40000000, // SuperSPARC II 1.x
1430 .fpu_version = 0 << 17,
1431 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1432 .mmu_bm = 0x00002000,
1433 .mmu_ctpr_mask = 0xffffffc0,
1434 .mmu_cxr_mask = 0x0000ffff,
1435 .mmu_sfsr_mask = 0xffffffff,
1436 .mmu_trcr_mask = 0xffffffff,
1437 .mxcc_version = 0x00000104,
1438 .nwindows = 8,
1439 .features = CPU_DEFAULT_FEATURES,
1442 .name = "Ross RT625",
1443 .iu_version = 0x1e000000,
1444 .fpu_version = 1 << 17,
1445 .mmu_version = 0x1e000000,
1446 .mmu_bm = 0x00004000,
1447 .mmu_ctpr_mask = 0x007ffff0,
1448 .mmu_cxr_mask = 0x0000003f,
1449 .mmu_sfsr_mask = 0xffffffff,
1450 .mmu_trcr_mask = 0xffffffff,
1451 .nwindows = 8,
1452 .features = CPU_DEFAULT_FEATURES,
1455 .name = "Ross RT620",
1456 .iu_version = 0x1f000000,
1457 .fpu_version = 1 << 17,
1458 .mmu_version = 0x1f000000,
1459 .mmu_bm = 0x00004000,
1460 .mmu_ctpr_mask = 0x007ffff0,
1461 .mmu_cxr_mask = 0x0000003f,
1462 .mmu_sfsr_mask = 0xffffffff,
1463 .mmu_trcr_mask = 0xffffffff,
1464 .nwindows = 8,
1465 .features = CPU_DEFAULT_FEATURES,
1468 .name = "BIT B5010",
1469 .iu_version = 0x20000000,
1470 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1471 .mmu_version = 0x20000000,
1472 .mmu_bm = 0x00004000,
1473 .mmu_ctpr_mask = 0x007ffff0,
1474 .mmu_cxr_mask = 0x0000003f,
1475 .mmu_sfsr_mask = 0xffffffff,
1476 .mmu_trcr_mask = 0xffffffff,
1477 .nwindows = 8,
1478 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1479 CPU_FEATURE_FSMULD,
1482 .name = "Matsushita MN10501",
1483 .iu_version = 0x50000000,
1484 .fpu_version = 0 << 17,
1485 .mmu_version = 0x50000000,
1486 .mmu_bm = 0x00004000,
1487 .mmu_ctpr_mask = 0x007ffff0,
1488 .mmu_cxr_mask = 0x0000003f,
1489 .mmu_sfsr_mask = 0xffffffff,
1490 .mmu_trcr_mask = 0xffffffff,
1491 .nwindows = 8,
1492 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1493 CPU_FEATURE_FSMULD,
1496 .name = "Weitek W8601",
1497 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1498 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1499 .mmu_version = 0x10 << 24,
1500 .mmu_bm = 0x00004000,
1501 .mmu_ctpr_mask = 0x007ffff0,
1502 .mmu_cxr_mask = 0x0000003f,
1503 .mmu_sfsr_mask = 0xffffffff,
1504 .mmu_trcr_mask = 0xffffffff,
1505 .nwindows = 8,
1506 .features = CPU_DEFAULT_FEATURES,
1509 .name = "LEON2",
1510 .iu_version = 0xf2000000,
1511 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1512 .mmu_version = 0xf2000000,
1513 .mmu_bm = 0x00004000,
1514 .mmu_ctpr_mask = 0x007ffff0,
1515 .mmu_cxr_mask = 0x0000003f,
1516 .mmu_sfsr_mask = 0xffffffff,
1517 .mmu_trcr_mask = 0xffffffff,
1518 .nwindows = 8,
1519 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
1522 .name = "LEON3",
1523 .iu_version = 0xf3000000,
1524 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1525 .mmu_version = 0xf3000000,
1526 .mmu_bm = 0x00000000,
1527 .mmu_ctpr_mask = 0x007ffff0,
1528 .mmu_cxr_mask = 0x0000003f,
1529 .mmu_sfsr_mask = 0xffffffff,
1530 .mmu_trcr_mask = 0xffffffff,
1531 .nwindows = 8,
1532 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
1533 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
1535 #endif
1538 static const char * const feature_name[] = {
1539 "float",
1540 "float128",
1541 "swap",
1542 "mul",
1543 "div",
1544 "flush",
1545 "fsqrt",
1546 "fmul",
1547 "vis1",
1548 "vis2",
1549 "fsmuld",
1550 "hypv",
1551 "cmt",
1552 "gl",
1555 static void print_features(FILE *f, fprintf_function cpu_fprintf,
1556 uint32_t features, const char *prefix)
1558 unsigned int i;
1560 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1561 if (feature_name[i] && (features & (1 << i))) {
1562 if (prefix)
1563 (*cpu_fprintf)(f, "%s", prefix);
1564 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1568 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1570 unsigned int i;
1572 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1573 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1574 *features |= 1 << i;
1575 return;
1577 fprintf(stderr, "CPU feature %s not found\n", flagname);
1580 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1582 unsigned int i;
1583 const sparc_def_t *def = NULL;
1584 char *s = strdup(cpu_model);
1585 char *featurestr, *name = strtok(s, ",");
1586 uint32_t plus_features = 0;
1587 uint32_t minus_features = 0;
1588 uint64_t iu_version;
1589 uint32_t fpu_version, mmu_version, nwindows;
1591 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1592 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1593 def = &sparc_defs[i];
1596 if (!def)
1597 goto error;
1598 memcpy(cpu_def, def, sizeof(*def));
1600 featurestr = strtok(NULL, ",");
1601 while (featurestr) {
1602 char *val;
1604 if (featurestr[0] == '+') {
1605 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1606 } else if (featurestr[0] == '-') {
1607 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1608 } else if ((val = strchr(featurestr, '='))) {
1609 *val = 0; val++;
1610 if (!strcmp(featurestr, "iu_version")) {
1611 char *err;
1613 iu_version = strtoll(val, &err, 0);
1614 if (!*val || *err) {
1615 fprintf(stderr, "bad numerical value %s\n", val);
1616 goto error;
1618 cpu_def->iu_version = iu_version;
1619 #ifdef DEBUG_FEATURES
1620 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1621 #endif
1622 } else if (!strcmp(featurestr, "fpu_version")) {
1623 char *err;
1625 fpu_version = strtol(val, &err, 0);
1626 if (!*val || *err) {
1627 fprintf(stderr, "bad numerical value %s\n", val);
1628 goto error;
1630 cpu_def->fpu_version = fpu_version;
1631 #ifdef DEBUG_FEATURES
1632 fprintf(stderr, "fpu_version %x\n", fpu_version);
1633 #endif
1634 } else if (!strcmp(featurestr, "mmu_version")) {
1635 char *err;
1637 mmu_version = strtol(val, &err, 0);
1638 if (!*val || *err) {
1639 fprintf(stderr, "bad numerical value %s\n", val);
1640 goto error;
1642 cpu_def->mmu_version = mmu_version;
1643 #ifdef DEBUG_FEATURES
1644 fprintf(stderr, "mmu_version %x\n", mmu_version);
1645 #endif
1646 } else if (!strcmp(featurestr, "nwindows")) {
1647 char *err;
1649 nwindows = strtol(val, &err, 0);
1650 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1651 nwindows < MIN_NWINDOWS) {
1652 fprintf(stderr, "bad numerical value %s\n", val);
1653 goto error;
1655 cpu_def->nwindows = nwindows;
1656 #ifdef DEBUG_FEATURES
1657 fprintf(stderr, "nwindows %d\n", nwindows);
1658 #endif
1659 } else {
1660 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1661 goto error;
1663 } else {
1664 fprintf(stderr, "feature string `%s' not in format "
1665 "(+feature|-feature|feature=xyz)\n", featurestr);
1666 goto error;
1668 featurestr = strtok(NULL, ",");
1670 cpu_def->features |= plus_features;
1671 cpu_def->features &= ~minus_features;
1672 #ifdef DEBUG_FEATURES
1673 print_features(stderr, fprintf, cpu_def->features, NULL);
1674 #endif
1675 free(s);
1676 return 0;
1678 error:
1679 free(s);
1680 return -1;
1683 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
1685 unsigned int i;
1687 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1688 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1689 sparc_defs[i].name,
1690 sparc_defs[i].iu_version,
1691 sparc_defs[i].fpu_version,
1692 sparc_defs[i].mmu_version,
1693 sparc_defs[i].nwindows);
1694 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1695 ~sparc_defs[i].features, "-");
1696 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1697 sparc_defs[i].features, "+");
1698 (*cpu_fprintf)(f, "\n");
1700 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1701 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1702 (*cpu_fprintf)(f, "\n");
1703 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1704 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1705 (*cpu_fprintf)(f, "\n");
1706 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1707 "fpu_version mmu_version nwindows\n");
1710 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
1711 uint32_t cc)
1713 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1714 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1715 cc & PSR_CARRY? 'C' : '-');
1718 #ifdef TARGET_SPARC64
1719 #define REGS_PER_LINE 4
1720 #else
1721 #define REGS_PER_LINE 8
1722 #endif
1724 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1725 int flags)
1727 int i, x;
1729 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1730 env->npc);
1731 cpu_fprintf(f, "General Registers:\n");
1733 for (i = 0; i < 8; i++) {
1734 if (i % REGS_PER_LINE == 0) {
1735 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1737 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1738 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1739 cpu_fprintf(f, "\n");
1742 cpu_fprintf(f, "\nCurrent Register Window:\n");
1743 for (x = 0; x < 3; x++) {
1744 for (i = 0; i < 8; i++) {
1745 if (i % REGS_PER_LINE == 0) {
1746 cpu_fprintf(f, "%%%c%d-%d: ",
1747 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1748 i, i + REGS_PER_LINE - 1);
1750 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1751 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1752 cpu_fprintf(f, "\n");
1756 cpu_fprintf(f, "\nFloating Point Registers:\n");
1757 for (i = 0; i < TARGET_FPREGS; i++) {
1758 if ((i & 3) == 0)
1759 cpu_fprintf(f, "%%f%02d:", i);
1760 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1761 if ((i & 3) == 3)
1762 cpu_fprintf(f, "\n");
1764 #ifdef TARGET_SPARC64
1765 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1766 (unsigned)cpu_get_ccr(env));
1767 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1768 cpu_fprintf(f, " xcc: ");
1769 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1770 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1771 env->psrpil);
1772 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1773 "cleanwin: %d cwp: %d\n",
1774 env->cansave, env->canrestore, env->otherwin, env->wstate,
1775 env->cleanwin, env->nwindows - 1 - env->cwp);
1776 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1777 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1778 #else
1779 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1780 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1781 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1782 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1783 env->wim);
1784 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1785 env->fsr, env->y);
1786 #endif