Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging
[qemu.git] / target-sparc / helper.c
blob7eea1acbd596dafabf1342aaf9f1e53761ded355
1 /*
2 * sparc helpers
4 * Copyright (c) 2003-2005 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
25 #include "cpu.h"
26 #include "qemu-common.h"
28 //#define DEBUG_MMU
29 //#define DEBUG_FEATURES
31 #ifdef DEBUG_MMU
32 #define DPRINTF_MMU(fmt, ...) \
33 do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
34 #else
35 #define DPRINTF_MMU(fmt, ...) do {} while (0)
36 #endif
38 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
40 /* Sparc MMU emulation */
42 #if defined(CONFIG_USER_ONLY)
44 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
45 int mmu_idx, int is_softmmu)
47 if (rw & 2)
48 env1->exception_index = TT_TFAULT;
49 else
50 env1->exception_index = TT_DFAULT;
51 return 1;
54 #else
56 #ifndef TARGET_SPARC64
58 * Sparc V8 Reference MMU (SRMMU)
60 static const int access_table[8][8] = {
61 { 0, 0, 0, 0, 8, 0, 12, 12 },
62 { 0, 0, 0, 0, 8, 0, 0, 0 },
63 { 8, 8, 0, 0, 0, 8, 12, 12 },
64 { 8, 8, 0, 0, 0, 8, 0, 0 },
65 { 8, 0, 8, 0, 8, 8, 12, 12 },
66 { 8, 0, 8, 0, 8, 0, 8, 0 },
67 { 8, 8, 8, 0, 8, 8, 12, 12 },
68 { 8, 8, 8, 0, 8, 8, 8, 0 }
71 static const int perm_table[2][8] = {
73 PAGE_READ,
74 PAGE_READ | PAGE_WRITE,
75 PAGE_READ | PAGE_EXEC,
76 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
77 PAGE_EXEC,
78 PAGE_READ | PAGE_WRITE,
79 PAGE_READ | PAGE_EXEC,
80 PAGE_READ | PAGE_WRITE | PAGE_EXEC
83 PAGE_READ,
84 PAGE_READ | PAGE_WRITE,
85 PAGE_READ | PAGE_EXEC,
86 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
87 PAGE_EXEC,
88 PAGE_READ,
94 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
95 int *prot, int *access_index,
96 target_ulong address, int rw, int mmu_idx,
97 target_ulong *page_size)
99 int access_perms = 0;
100 target_phys_addr_t pde_ptr;
101 uint32_t pde;
102 int error_code = 0, is_dirty, is_user;
103 unsigned long page_offset;
105 is_user = mmu_idx == MMU_USER_IDX;
107 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
108 *page_size = TARGET_PAGE_SIZE;
109 // Boot mode: instruction fetches are taken from PROM
110 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
111 *physical = env->prom_addr | (address & 0x7ffffULL);
112 *prot = PAGE_READ | PAGE_EXEC;
113 return 0;
115 *physical = address;
116 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
117 return 0;
120 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
121 *physical = 0xffffffffffff0000ULL;
123 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
124 /* Context base + context number */
125 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
126 pde = ldl_phys(pde_ptr);
128 /* Ctx pde */
129 switch (pde & PTE_ENTRYTYPE_MASK) {
130 default:
131 case 0: /* Invalid */
132 return 1 << 2;
133 case 2: /* L0 PTE, maybe should not happen? */
134 case 3: /* Reserved */
135 return 4 << 2;
136 case 1: /* L0 PDE */
137 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
138 pde = ldl_phys(pde_ptr);
140 switch (pde & PTE_ENTRYTYPE_MASK) {
141 default:
142 case 0: /* Invalid */
143 return (1 << 8) | (1 << 2);
144 case 3: /* Reserved */
145 return (1 << 8) | (4 << 2);
146 case 1: /* L1 PDE */
147 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
148 pde = ldl_phys(pde_ptr);
150 switch (pde & PTE_ENTRYTYPE_MASK) {
151 default:
152 case 0: /* Invalid */
153 return (2 << 8) | (1 << 2);
154 case 3: /* Reserved */
155 return (2 << 8) | (4 << 2);
156 case 1: /* L2 PDE */
157 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
158 pde = ldl_phys(pde_ptr);
160 switch (pde & PTE_ENTRYTYPE_MASK) {
161 default:
162 case 0: /* Invalid */
163 return (3 << 8) | (1 << 2);
164 case 1: /* PDE, should not happen */
165 case 3: /* Reserved */
166 return (3 << 8) | (4 << 2);
167 case 2: /* L3 PTE */
168 page_offset = (address & TARGET_PAGE_MASK) &
169 (TARGET_PAGE_SIZE - 1);
171 *page_size = TARGET_PAGE_SIZE;
172 break;
173 case 2: /* L2 PTE */
174 page_offset = address & 0x3ffff;
175 *page_size = 0x40000;
177 break;
178 case 2: /* L1 PTE */
179 page_offset = address & 0xffffff;
180 *page_size = 0x1000000;
184 /* check access */
185 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
186 error_code = access_table[*access_index][access_perms];
187 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
188 return error_code;
190 /* update page modified and dirty bits */
191 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
192 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
193 pde |= PG_ACCESSED_MASK;
194 if (is_dirty)
195 pde |= PG_MODIFIED_MASK;
196 stl_phys_notdirty(pde_ptr, pde);
199 /* the page can be put in the TLB */
200 *prot = perm_table[is_user][access_perms];
201 if (!(pde & PG_MODIFIED_MASK)) {
202 /* only set write access if already dirty... otherwise wait
203 for dirty access */
204 *prot &= ~PAGE_WRITE;
207 /* Even if large ptes, we map only one 4KB page in the cache to
208 avoid filling it too fast */
209 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
210 return error_code;
213 /* Perform address translation */
214 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
215 int mmu_idx, int is_softmmu)
217 target_phys_addr_t paddr;
218 target_ulong vaddr;
219 target_ulong page_size;
220 int error_code = 0, prot, access_index;
222 error_code = get_physical_address(env, &paddr, &prot, &access_index,
223 address, rw, mmu_idx, &page_size);
224 if (error_code == 0) {
225 vaddr = address & TARGET_PAGE_MASK;
226 paddr &= TARGET_PAGE_MASK;
227 #ifdef DEBUG_MMU
228 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
229 TARGET_FMT_lx "\n", address, paddr, vaddr);
230 #endif
231 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
232 return 0;
235 if (env->mmuregs[3]) /* Fault status register */
236 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
237 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
238 env->mmuregs[4] = address; /* Fault address register */
240 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
241 // No fault mode: if a mapping is available, just override
242 // permissions. If no mapping is available, redirect accesses to
243 // neverland. Fake/overridden mappings will be flushed when
244 // switching to normal mode.
245 vaddr = address & TARGET_PAGE_MASK;
246 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
247 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
248 return 0;
249 } else {
250 if (rw & 2)
251 env->exception_index = TT_TFAULT;
252 else
253 env->exception_index = TT_DFAULT;
254 return 1;
258 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
260 target_phys_addr_t pde_ptr;
261 uint32_t pde;
263 /* Context base + context number */
264 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
265 (env->mmuregs[2] << 2);
266 pde = ldl_phys(pde_ptr);
268 switch (pde & PTE_ENTRYTYPE_MASK) {
269 default:
270 case 0: /* Invalid */
271 case 2: /* PTE, maybe should not happen? */
272 case 3: /* Reserved */
273 return 0;
274 case 1: /* L1 PDE */
275 if (mmulev == 3)
276 return pde;
277 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
278 pde = ldl_phys(pde_ptr);
280 switch (pde & PTE_ENTRYTYPE_MASK) {
281 default:
282 case 0: /* Invalid */
283 case 3: /* Reserved */
284 return 0;
285 case 2: /* L1 PTE */
286 return pde;
287 case 1: /* L2 PDE */
288 if (mmulev == 2)
289 return pde;
290 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
291 pde = ldl_phys(pde_ptr);
293 switch (pde & PTE_ENTRYTYPE_MASK) {
294 default:
295 case 0: /* Invalid */
296 case 3: /* Reserved */
297 return 0;
298 case 2: /* L2 PTE */
299 return pde;
300 case 1: /* L3 PDE */
301 if (mmulev == 1)
302 return pde;
303 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
304 pde = ldl_phys(pde_ptr);
306 switch (pde & PTE_ENTRYTYPE_MASK) {
307 default:
308 case 0: /* Invalid */
309 case 1: /* PDE, should not happen */
310 case 3: /* Reserved */
311 return 0;
312 case 2: /* L3 PTE */
313 return pde;
318 return 0;
321 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
323 target_ulong va, va1, va2;
324 unsigned int n, m, o;
325 target_phys_addr_t pde_ptr, pa;
326 uint32_t pde;
328 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
329 pde = ldl_phys(pde_ptr);
330 (*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
331 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
332 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
333 pde = mmu_probe(env, va, 2);
334 if (pde) {
335 pa = cpu_get_phys_page_debug(env, va);
336 (*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
337 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
338 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
339 pde = mmu_probe(env, va1, 1);
340 if (pde) {
341 pa = cpu_get_phys_page_debug(env, va1);
342 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
343 TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
344 va1, pa, pde);
345 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
346 pde = mmu_probe(env, va2, 0);
347 if (pde) {
348 pa = cpu_get_phys_page_debug(env, va2);
349 (*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
350 TARGET_FMT_plx " PTE: "
351 TARGET_FMT_lx "\n",
352 va2, pa, pde);
361 #else /* !TARGET_SPARC64 */
363 // 41 bit physical address space
364 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
366 return x & 0x1ffffffffffULL;
370 * UltraSparc IIi I/DMMUs
373 // Returns true if TTE tag is valid and matches virtual address value in context
374 // requires virtual address mask value calculated from TTE entry size
375 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
376 uint64_t address, uint64_t context,
377 target_phys_addr_t *physical)
379 uint64_t mask;
381 switch ((tlb->tte >> 61) & 3) {
382 default:
383 case 0x0: // 8k
384 mask = 0xffffffffffffe000ULL;
385 break;
386 case 0x1: // 64k
387 mask = 0xffffffffffff0000ULL;
388 break;
389 case 0x2: // 512k
390 mask = 0xfffffffffff80000ULL;
391 break;
392 case 0x3: // 4M
393 mask = 0xffffffffffc00000ULL;
394 break;
397 // valid, context match, virtual address match?
398 if (TTE_IS_VALID(tlb->tte) &&
399 (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
400 && compare_masked(address, tlb->tag, mask))
402 // decode physical address
403 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
404 return 1;
407 return 0;
410 static int get_physical_address_data(CPUState *env,
411 target_phys_addr_t *physical, int *prot,
412 target_ulong address, int rw, int mmu_idx)
414 unsigned int i;
415 uint64_t context;
417 int is_user = (mmu_idx == MMU_USER_IDX ||
418 mmu_idx == MMU_USER_SECONDARY_IDX);
420 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
421 *physical = ultrasparc_truncate_physical(address);
422 *prot = PAGE_READ | PAGE_WRITE;
423 return 0;
426 switch(mmu_idx) {
427 case MMU_USER_IDX:
428 case MMU_KERNEL_IDX:
429 context = env->dmmu.mmu_primary_context & 0x1fff;
430 break;
431 case MMU_USER_SECONDARY_IDX:
432 case MMU_KERNEL_SECONDARY_IDX:
433 context = env->dmmu.mmu_secondary_context & 0x1fff;
434 break;
435 case MMU_NUCLEUS_IDX:
436 default:
437 context = 0;
438 break;
441 for (i = 0; i < 64; i++) {
442 // ctx match, vaddr match, valid?
443 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
445 uint8_t fault_type = 0;
447 // access ok?
448 if ((env->dtlb[i].tte & 0x4) && is_user) {
449 fault_type |= 1; /* privilege violation */
450 env->exception_index = TT_DFAULT;
452 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
453 " mmu_idx=%d tl=%d\n",
454 address, context, mmu_idx, env->tl);
455 } else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) {
456 env->exception_index = TT_DPROT;
458 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
459 " mmu_idx=%d tl=%d\n",
460 address, context, mmu_idx, env->tl);
461 } else {
462 *prot = PAGE_READ;
463 if (env->dtlb[i].tte & 0x2)
464 *prot |= PAGE_WRITE;
466 TTE_SET_USED(env->dtlb[i].tte);
468 return 0;
471 if (env->dmmu.sfsr & 1) /* Fault status register */
472 env->dmmu.sfsr = 2; /* overflow (not read before
473 another fault) */
475 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
477 env->dmmu.sfsr |= (fault_type << 7);
479 env->dmmu.sfar = address; /* Fault address register */
481 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
483 return 1;
487 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
488 address, context);
490 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
491 env->exception_index = TT_DMISS;
492 return 1;
495 static int get_physical_address_code(CPUState *env,
496 target_phys_addr_t *physical, int *prot,
497 target_ulong address, int mmu_idx)
499 unsigned int i;
500 uint64_t context;
502 int is_user = (mmu_idx == MMU_USER_IDX ||
503 mmu_idx == MMU_USER_SECONDARY_IDX);
505 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
506 /* IMMU disabled */
507 *physical = ultrasparc_truncate_physical(address);
508 *prot = PAGE_EXEC;
509 return 0;
512 if (env->tl == 0) {
513 /* PRIMARY context */
514 context = env->dmmu.mmu_primary_context & 0x1fff;
515 } else {
516 /* NUCLEUS context */
517 context = 0;
520 for (i = 0; i < 64; i++) {
521 // ctx match, vaddr match, valid?
522 if (ultrasparc_tag_match(&env->itlb[i],
523 address, context, physical)) {
524 // access ok?
525 if ((env->itlb[i].tte & 0x4) && is_user) {
526 if (env->immu.sfsr) /* Fault status register */
527 env->immu.sfsr = 2; /* overflow (not read before
528 another fault) */
529 env->immu.sfsr |= (is_user << 3) | 1;
530 env->exception_index = TT_TFAULT;
532 env->immu.tag_access = (address & ~0x1fffULL) | context;
534 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
535 address, context);
537 return 1;
539 *prot = PAGE_EXEC;
540 TTE_SET_USED(env->itlb[i].tte);
541 return 0;
545 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
546 address, context);
548 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
549 env->immu.tag_access = (address & ~0x1fffULL) | context;
550 env->exception_index = TT_TMISS;
551 return 1;
554 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
555 int *prot, int *access_index,
556 target_ulong address, int rw, int mmu_idx,
557 target_ulong *page_size)
559 /* ??? We treat everything as a small page, then explicitly flush
560 everything when an entry is evicted. */
561 *page_size = TARGET_PAGE_SIZE;
563 #if defined (DEBUG_MMU)
564 /* safety net to catch wrong softmmu index use from dynamic code */
565 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
566 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
567 " primary context=%" PRIx64
568 " secondary context=%" PRIx64
569 " address=%" PRIx64
570 "\n",
571 (rw == 2 ? "CODE" : "DATA"),
572 env->tl, mmu_idx,
573 env->dmmu.mmu_primary_context,
574 env->dmmu.mmu_secondary_context,
575 address);
577 #endif
579 if (rw == 2)
580 return get_physical_address_code(env, physical, prot, address,
581 mmu_idx);
582 else
583 return get_physical_address_data(env, physical, prot, address, rw,
584 mmu_idx);
587 /* Perform address translation */
588 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
589 int mmu_idx, int is_softmmu)
591 target_ulong virt_addr, vaddr;
592 target_phys_addr_t paddr;
593 target_ulong page_size;
594 int error_code = 0, prot, access_index;
596 error_code = get_physical_address(env, &paddr, &prot, &access_index,
597 address, rw, mmu_idx, &page_size);
598 if (error_code == 0) {
599 virt_addr = address & TARGET_PAGE_MASK;
600 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
601 (TARGET_PAGE_SIZE - 1));
603 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
604 " vaddr %" PRIx64
605 " mmu_idx=%d"
606 " tl=%d"
607 " primary context=%" PRIx64
608 " secondary context=%" PRIx64
609 "\n",
610 address, paddr, vaddr, mmu_idx, env->tl,
611 env->dmmu.mmu_primary_context,
612 env->dmmu.mmu_secondary_context);
614 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
615 return 0;
617 // XXX
618 return 1;
621 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
623 unsigned int i;
624 const char *mask;
626 (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
627 PRId64 "\n",
628 env->dmmu.mmu_primary_context,
629 env->dmmu.mmu_secondary_context);
630 if ((env->lsu & DMMU_E) == 0) {
631 (*cpu_fprintf)(f, "DMMU disabled\n");
632 } else {
633 (*cpu_fprintf)(f, "DMMU dump\n");
634 for (i = 0; i < 64; i++) {
635 switch ((env->dtlb[i].tte >> 61) & 3) {
636 default:
637 case 0x0:
638 mask = " 8k";
639 break;
640 case 0x1:
641 mask = " 64k";
642 break;
643 case 0x2:
644 mask = "512k";
645 break;
646 case 0x3:
647 mask = " 4M";
648 break;
650 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
651 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
652 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
654 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
655 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
656 mask,
657 env->dtlb[i].tte & 0x4? "priv": "user",
658 env->dtlb[i].tte & 0x2? "RW": "RO",
659 env->dtlb[i].tte & 0x40? "locked": "unlocked",
660 env->dtlb[i].tag & (uint64_t)0x1fffULL,
661 TTE_IS_GLOBAL(env->dtlb[i].tte)?
662 "global" : "local");
666 if ((env->lsu & IMMU_E) == 0) {
667 (*cpu_fprintf)(f, "IMMU disabled\n");
668 } else {
669 (*cpu_fprintf)(f, "IMMU dump\n");
670 for (i = 0; i < 64; i++) {
671 switch ((env->itlb[i].tte >> 61) & 3) {
672 default:
673 case 0x0:
674 mask = " 8k";
675 break;
676 case 0x1:
677 mask = " 64k";
678 break;
679 case 0x2:
680 mask = "512k";
681 break;
682 case 0x3:
683 mask = " 4M";
684 break;
686 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
687 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
688 ", %s, %s, %s, ctx %" PRId64 " %s\n",
690 env->itlb[i].tag & (uint64_t)~0x1fffULL,
691 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
692 mask,
693 env->itlb[i].tte & 0x4? "priv": "user",
694 env->itlb[i].tte & 0x40? "locked": "unlocked",
695 env->itlb[i].tag & (uint64_t)0x1fffULL,
696 TTE_IS_GLOBAL(env->itlb[i].tte)?
697 "global" : "local");
703 #endif /* TARGET_SPARC64 */
704 #endif /* !CONFIG_USER_ONLY */
707 #if !defined(CONFIG_USER_ONLY)
708 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
709 int mmu_idx)
711 target_phys_addr_t phys_addr;
712 target_ulong page_size;
713 int prot, access_index;
715 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
716 mmu_idx, &page_size) != 0)
717 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
718 0, mmu_idx, &page_size) != 0)
719 return -1;
720 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
721 return -1;
722 return phys_addr;
725 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
727 return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
729 #endif
731 #ifdef TARGET_SPARC64
732 #ifdef DEBUG_PCALL
733 static const char * const excp_names[0x80] = {
734 [TT_TFAULT] = "Instruction Access Fault",
735 [TT_TMISS] = "Instruction Access MMU Miss",
736 [TT_CODE_ACCESS] = "Instruction Access Error",
737 [TT_ILL_INSN] = "Illegal Instruction",
738 [TT_PRIV_INSN] = "Privileged Instruction",
739 [TT_NFPU_INSN] = "FPU Disabled",
740 [TT_FP_EXCP] = "FPU Exception",
741 [TT_TOVF] = "Tag Overflow",
742 [TT_CLRWIN] = "Clean Windows",
743 [TT_DIV_ZERO] = "Division By Zero",
744 [TT_DFAULT] = "Data Access Fault",
745 [TT_DMISS] = "Data Access MMU Miss",
746 [TT_DATA_ACCESS] = "Data Access Error",
747 [TT_DPROT] = "Data Protection Error",
748 [TT_UNALIGNED] = "Unaligned Memory Access",
749 [TT_PRIV_ACT] = "Privileged Action",
750 [TT_EXTINT | 0x1] = "External Interrupt 1",
751 [TT_EXTINT | 0x2] = "External Interrupt 2",
752 [TT_EXTINT | 0x3] = "External Interrupt 3",
753 [TT_EXTINT | 0x4] = "External Interrupt 4",
754 [TT_EXTINT | 0x5] = "External Interrupt 5",
755 [TT_EXTINT | 0x6] = "External Interrupt 6",
756 [TT_EXTINT | 0x7] = "External Interrupt 7",
757 [TT_EXTINT | 0x8] = "External Interrupt 8",
758 [TT_EXTINT | 0x9] = "External Interrupt 9",
759 [TT_EXTINT | 0xa] = "External Interrupt 10",
760 [TT_EXTINT | 0xb] = "External Interrupt 11",
761 [TT_EXTINT | 0xc] = "External Interrupt 12",
762 [TT_EXTINT | 0xd] = "External Interrupt 13",
763 [TT_EXTINT | 0xe] = "External Interrupt 14",
764 [TT_EXTINT | 0xf] = "External Interrupt 15",
766 #endif
768 void do_interrupt(CPUState *env)
770 int intno = env->exception_index;
771 trap_state *tsptr;
773 #ifdef DEBUG_PCALL
774 if (qemu_loglevel_mask(CPU_LOG_INT)) {
775 static int count;
776 const char *name;
778 if (intno < 0 || intno >= 0x180) {
779 name = "Unknown";
780 } else if (intno >= 0x100) {
781 name = "Trap Instruction";
782 } else if (intno >= 0xc0) {
783 name = "Window Fill";
784 } else if (intno >= 0x80) {
785 name = "Window Spill";
786 } else {
787 name = excp_names[intno];
788 if (!name) {
789 name = "Unknown";
793 qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
794 " SP=%016" PRIx64 "\n",
795 count, name, intno,
796 env->pc,
797 env->npc, env->regwptr[6]);
798 log_cpu_state(env, 0);
799 #if 0
801 int i;
802 uint8_t *ptr;
804 qemu_log(" code=");
805 ptr = (uint8_t *)env->pc;
806 for (i = 0; i < 16; i++) {
807 qemu_log(" %02x", ldub(ptr + i));
809 qemu_log("\n");
811 #endif
812 count++;
814 #endif
815 #if !defined(CONFIG_USER_ONLY)
816 if (env->tl >= env->maxtl) {
817 cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
818 " Error state", env->exception_index, env->tl, env->maxtl);
819 return;
821 #endif
822 if (env->tl < env->maxtl - 1) {
823 env->tl++;
824 } else {
825 env->pstate |= PS_RED;
826 if (env->tl < env->maxtl) {
827 env->tl++;
830 tsptr = cpu_tsptr(env);
832 tsptr->tstate = (cpu_get_ccr(env) << 32) |
833 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
834 cpu_get_cwp64(env);
835 tsptr->tpc = env->pc;
836 tsptr->tnpc = env->npc;
837 tsptr->tt = intno;
839 switch (intno) {
840 case TT_IVEC:
841 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
842 break;
843 case TT_TFAULT:
844 case TT_DFAULT:
845 case TT_TMISS ... TT_TMISS + 3:
846 case TT_DMISS ... TT_DMISS + 3:
847 case TT_DPROT ... TT_DPROT + 3:
848 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
849 break;
850 default:
851 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
852 break;
855 if (intno == TT_CLRWIN) {
856 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
857 } else if ((intno & 0x1c0) == TT_SPILL) {
858 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
859 } else if ((intno & 0x1c0) == TT_FILL) {
860 cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
862 env->tbr &= ~0x7fffULL;
863 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
864 env->pc = env->tbr;
865 env->npc = env->pc + 4;
866 env->exception_index = -1;
868 #else
869 #ifdef DEBUG_PCALL
870 static const char * const excp_names[0x80] = {
871 [TT_TFAULT] = "Instruction Access Fault",
872 [TT_ILL_INSN] = "Illegal Instruction",
873 [TT_PRIV_INSN] = "Privileged Instruction",
874 [TT_NFPU_INSN] = "FPU Disabled",
875 [TT_WIN_OVF] = "Window Overflow",
876 [TT_WIN_UNF] = "Window Underflow",
877 [TT_UNALIGNED] = "Unaligned Memory Access",
878 [TT_FP_EXCP] = "FPU Exception",
879 [TT_DFAULT] = "Data Access Fault",
880 [TT_TOVF] = "Tag Overflow",
881 [TT_EXTINT | 0x1] = "External Interrupt 1",
882 [TT_EXTINT | 0x2] = "External Interrupt 2",
883 [TT_EXTINT | 0x3] = "External Interrupt 3",
884 [TT_EXTINT | 0x4] = "External Interrupt 4",
885 [TT_EXTINT | 0x5] = "External Interrupt 5",
886 [TT_EXTINT | 0x6] = "External Interrupt 6",
887 [TT_EXTINT | 0x7] = "External Interrupt 7",
888 [TT_EXTINT | 0x8] = "External Interrupt 8",
889 [TT_EXTINT | 0x9] = "External Interrupt 9",
890 [TT_EXTINT | 0xa] = "External Interrupt 10",
891 [TT_EXTINT | 0xb] = "External Interrupt 11",
892 [TT_EXTINT | 0xc] = "External Interrupt 12",
893 [TT_EXTINT | 0xd] = "External Interrupt 13",
894 [TT_EXTINT | 0xe] = "External Interrupt 14",
895 [TT_EXTINT | 0xf] = "External Interrupt 15",
896 [TT_TOVF] = "Tag Overflow",
897 [TT_CODE_ACCESS] = "Instruction Access Error",
898 [TT_DATA_ACCESS] = "Data Access Error",
899 [TT_DIV_ZERO] = "Division By Zero",
900 [TT_NCP_INSN] = "Coprocessor Disabled",
902 #endif
904 void do_interrupt(CPUState *env)
906 int cwp, intno = env->exception_index;
908 #ifdef DEBUG_PCALL
909 if (qemu_loglevel_mask(CPU_LOG_INT)) {
910 static int count;
911 const char *name;
913 if (intno < 0 || intno >= 0x100) {
914 name = "Unknown";
915 } else if (intno >= 0x80) {
916 name = "Trap Instruction";
917 } else {
918 name = excp_names[intno];
919 if (!name) {
920 name = "Unknown";
924 qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
925 count, name, intno,
926 env->pc,
927 env->npc, env->regwptr[6]);
928 log_cpu_state(env, 0);
929 #if 0
931 int i;
932 uint8_t *ptr;
934 qemu_log(" code=");
935 ptr = (uint8_t *)env->pc;
936 for (i = 0; i < 16; i++) {
937 qemu_log(" %02x", ldub(ptr + i));
939 qemu_log("\n");
941 #endif
942 count++;
944 #endif
945 #if !defined(CONFIG_USER_ONLY)
946 if (env->psret == 0) {
947 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
948 env->exception_index);
949 return;
951 #endif
952 env->psret = 0;
953 cwp = cpu_cwp_dec(env, env->cwp - 1);
954 cpu_set_cwp(env, cwp);
955 env->regwptr[9] = env->pc;
956 env->regwptr[10] = env->npc;
957 env->psrps = env->psrs;
958 env->psrs = 1;
959 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
960 env->pc = env->tbr;
961 env->npc = env->pc + 4;
962 env->exception_index = -1;
964 #if !defined(CONFIG_USER_ONLY)
965 /* IRQ acknowledgment */
966 if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
967 env->qemu_irq_ack(env->irq_manager, intno);
969 #endif
971 #endif
973 void cpu_reset(CPUSPARCState *env)
975 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
976 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
977 log_cpu_state(env, 0);
980 tlb_flush(env, 1);
981 env->cwp = 0;
982 #ifndef TARGET_SPARC64
983 env->wim = 1;
984 #endif
985 env->regwptr = env->regbase + (env->cwp * 16);
986 CC_OP = CC_OP_FLAGS;
987 #if defined(CONFIG_USER_ONLY)
988 #ifdef TARGET_SPARC64
989 env->cleanwin = env->nwindows - 2;
990 env->cansave = env->nwindows - 2;
991 env->pstate = PS_RMO | PS_PEF | PS_IE;
992 env->asi = 0x82; // Primary no-fault
993 #endif
994 #else
995 #if !defined(TARGET_SPARC64)
996 env->psret = 0;
997 env->psrs = 1;
998 env->psrps = 1;
999 #endif
1000 #ifdef TARGET_SPARC64
1001 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
1002 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
1003 env->tl = env->maxtl;
1004 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
1005 env->lsu = 0;
1006 #else
1007 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
1008 env->mmuregs[0] |= env->def->mmu_bm;
1009 #endif
1010 env->pc = 0;
1011 env->npc = env->pc + 4;
1012 #endif
1013 env->cache_control = 0;
1016 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
1018 sparc_def_t def1, *def = &def1;
1020 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
1021 return -1;
1023 env->def = qemu_mallocz(sizeof(*def));
1024 memcpy(env->def, def, sizeof(*def));
1025 #if defined(CONFIG_USER_ONLY)
1026 if ((env->def->features & CPU_FEATURE_FLOAT))
1027 env->def->features |= CPU_FEATURE_FLOAT128;
1028 #endif
1029 env->cpu_model_str = cpu_model;
1030 env->version = def->iu_version;
1031 env->fsr = def->fpu_version;
1032 env->nwindows = def->nwindows;
1033 #if !defined(TARGET_SPARC64)
1034 env->mmuregs[0] |= def->mmu_version;
1035 cpu_sparc_set_id(env, 0);
1036 env->mxccregs[7] |= def->mxcc_version;
1037 #else
1038 env->mmu_version = def->mmu_version;
1039 env->maxtl = def->maxtl;
1040 env->version |= def->maxtl << 8;
1041 env->version |= def->nwindows - 1;
1042 #endif
1043 return 0;
1046 static void cpu_sparc_close(CPUSPARCState *env)
1048 free(env->def);
1049 free(env);
1052 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
1054 CPUSPARCState *env;
1056 env = qemu_mallocz(sizeof(CPUSPARCState));
1057 cpu_exec_init(env);
1059 gen_intermediate_code_init(env);
1061 if (cpu_sparc_register(env, cpu_model) < 0) {
1062 cpu_sparc_close(env);
1063 return NULL;
1065 qemu_init_vcpu(env);
1067 return env;
1070 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
1072 #if !defined(TARGET_SPARC64)
1073 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
1074 #endif
1077 static const sparc_def_t sparc_defs[] = {
1078 #ifdef TARGET_SPARC64
1080 .name = "Fujitsu Sparc64",
1081 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
1082 .fpu_version = 0x00000000,
1083 .mmu_version = mmu_us_12,
1084 .nwindows = 4,
1085 .maxtl = 4,
1086 .features = CPU_DEFAULT_FEATURES,
1089 .name = "Fujitsu Sparc64 III",
1090 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
1091 .fpu_version = 0x00000000,
1092 .mmu_version = mmu_us_12,
1093 .nwindows = 5,
1094 .maxtl = 4,
1095 .features = CPU_DEFAULT_FEATURES,
1098 .name = "Fujitsu Sparc64 IV",
1099 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
1100 .fpu_version = 0x00000000,
1101 .mmu_version = mmu_us_12,
1102 .nwindows = 8,
1103 .maxtl = 5,
1104 .features = CPU_DEFAULT_FEATURES,
1107 .name = "Fujitsu Sparc64 V",
1108 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
1109 .fpu_version = 0x00000000,
1110 .mmu_version = mmu_us_12,
1111 .nwindows = 8,
1112 .maxtl = 5,
1113 .features = CPU_DEFAULT_FEATURES,
1116 .name = "TI UltraSparc I",
1117 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1118 .fpu_version = 0x00000000,
1119 .mmu_version = mmu_us_12,
1120 .nwindows = 8,
1121 .maxtl = 5,
1122 .features = CPU_DEFAULT_FEATURES,
1125 .name = "TI UltraSparc II",
1126 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
1127 .fpu_version = 0x00000000,
1128 .mmu_version = mmu_us_12,
1129 .nwindows = 8,
1130 .maxtl = 5,
1131 .features = CPU_DEFAULT_FEATURES,
1134 .name = "TI UltraSparc IIi",
1135 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
1136 .fpu_version = 0x00000000,
1137 .mmu_version = mmu_us_12,
1138 .nwindows = 8,
1139 .maxtl = 5,
1140 .features = CPU_DEFAULT_FEATURES,
1143 .name = "TI UltraSparc IIe",
1144 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
1145 .fpu_version = 0x00000000,
1146 .mmu_version = mmu_us_12,
1147 .nwindows = 8,
1148 .maxtl = 5,
1149 .features = CPU_DEFAULT_FEATURES,
1152 .name = "Sun UltraSparc III",
1153 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
1154 .fpu_version = 0x00000000,
1155 .mmu_version = mmu_us_12,
1156 .nwindows = 8,
1157 .maxtl = 5,
1158 .features = CPU_DEFAULT_FEATURES,
1161 .name = "Sun UltraSparc III Cu",
1162 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
1163 .fpu_version = 0x00000000,
1164 .mmu_version = mmu_us_3,
1165 .nwindows = 8,
1166 .maxtl = 5,
1167 .features = CPU_DEFAULT_FEATURES,
1170 .name = "Sun UltraSparc IIIi",
1171 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
1172 .fpu_version = 0x00000000,
1173 .mmu_version = mmu_us_12,
1174 .nwindows = 8,
1175 .maxtl = 5,
1176 .features = CPU_DEFAULT_FEATURES,
1179 .name = "Sun UltraSparc IV",
1180 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
1181 .fpu_version = 0x00000000,
1182 .mmu_version = mmu_us_4,
1183 .nwindows = 8,
1184 .maxtl = 5,
1185 .features = CPU_DEFAULT_FEATURES,
1188 .name = "Sun UltraSparc IV+",
1189 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
1190 .fpu_version = 0x00000000,
1191 .mmu_version = mmu_us_12,
1192 .nwindows = 8,
1193 .maxtl = 5,
1194 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
1197 .name = "Sun UltraSparc IIIi+",
1198 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
1199 .fpu_version = 0x00000000,
1200 .mmu_version = mmu_us_3,
1201 .nwindows = 8,
1202 .maxtl = 5,
1203 .features = CPU_DEFAULT_FEATURES,
1206 .name = "Sun UltraSparc T1",
1207 // defined in sparc_ifu_fdp.v and ctu.h
1208 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
1209 .fpu_version = 0x00000000,
1210 .mmu_version = mmu_sun4v,
1211 .nwindows = 8,
1212 .maxtl = 6,
1213 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1214 | CPU_FEATURE_GL,
1217 .name = "Sun UltraSparc T2",
1218 // defined in tlu_asi_ctl.v and n2_revid_cust.v
1219 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
1220 .fpu_version = 0x00000000,
1221 .mmu_version = mmu_sun4v,
1222 .nwindows = 8,
1223 .maxtl = 6,
1224 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1225 | CPU_FEATURE_GL,
1228 .name = "NEC UltraSparc I",
1229 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1230 .fpu_version = 0x00000000,
1231 .mmu_version = mmu_us_12,
1232 .nwindows = 8,
1233 .maxtl = 5,
1234 .features = CPU_DEFAULT_FEATURES,
1236 #else
1238 .name = "Fujitsu MB86900",
1239 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1240 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1241 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1242 .mmu_bm = 0x00004000,
1243 .mmu_ctpr_mask = 0x007ffff0,
1244 .mmu_cxr_mask = 0x0000003f,
1245 .mmu_sfsr_mask = 0xffffffff,
1246 .mmu_trcr_mask = 0xffffffff,
1247 .nwindows = 7,
1248 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1251 .name = "Fujitsu MB86904",
1252 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1253 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1254 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1255 .mmu_bm = 0x00004000,
1256 .mmu_ctpr_mask = 0x00ffffc0,
1257 .mmu_cxr_mask = 0x000000ff,
1258 .mmu_sfsr_mask = 0x00016fff,
1259 .mmu_trcr_mask = 0x00ffffff,
1260 .nwindows = 8,
1261 .features = CPU_DEFAULT_FEATURES,
1264 .name = "Fujitsu MB86907",
1265 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1266 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1267 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1268 .mmu_bm = 0x00004000,
1269 .mmu_ctpr_mask = 0xffffffc0,
1270 .mmu_cxr_mask = 0x000000ff,
1271 .mmu_sfsr_mask = 0x00016fff,
1272 .mmu_trcr_mask = 0xffffffff,
1273 .nwindows = 8,
1274 .features = CPU_DEFAULT_FEATURES,
1277 .name = "LSI L64811",
1278 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1279 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1280 .mmu_version = 0x10 << 24,
1281 .mmu_bm = 0x00004000,
1282 .mmu_ctpr_mask = 0x007ffff0,
1283 .mmu_cxr_mask = 0x0000003f,
1284 .mmu_sfsr_mask = 0xffffffff,
1285 .mmu_trcr_mask = 0xffffffff,
1286 .nwindows = 8,
1287 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1288 CPU_FEATURE_FSMULD,
1291 .name = "Cypress CY7C601",
1292 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1293 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1294 .mmu_version = 0x10 << 24,
1295 .mmu_bm = 0x00004000,
1296 .mmu_ctpr_mask = 0x007ffff0,
1297 .mmu_cxr_mask = 0x0000003f,
1298 .mmu_sfsr_mask = 0xffffffff,
1299 .mmu_trcr_mask = 0xffffffff,
1300 .nwindows = 8,
1301 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1302 CPU_FEATURE_FSMULD,
1305 .name = "Cypress CY7C611",
1306 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1307 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1308 .mmu_version = 0x10 << 24,
1309 .mmu_bm = 0x00004000,
1310 .mmu_ctpr_mask = 0x007ffff0,
1311 .mmu_cxr_mask = 0x0000003f,
1312 .mmu_sfsr_mask = 0xffffffff,
1313 .mmu_trcr_mask = 0xffffffff,
1314 .nwindows = 8,
1315 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1316 CPU_FEATURE_FSMULD,
1319 .name = "TI MicroSparc I",
1320 .iu_version = 0x41000000,
1321 .fpu_version = 4 << 17,
1322 .mmu_version = 0x41000000,
1323 .mmu_bm = 0x00004000,
1324 .mmu_ctpr_mask = 0x007ffff0,
1325 .mmu_cxr_mask = 0x0000003f,
1326 .mmu_sfsr_mask = 0x00016fff,
1327 .mmu_trcr_mask = 0x0000003f,
1328 .nwindows = 7,
1329 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1330 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1331 CPU_FEATURE_FMUL,
1334 .name = "TI MicroSparc II",
1335 .iu_version = 0x42000000,
1336 .fpu_version = 4 << 17,
1337 .mmu_version = 0x02000000,
1338 .mmu_bm = 0x00004000,
1339 .mmu_ctpr_mask = 0x00ffffc0,
1340 .mmu_cxr_mask = 0x000000ff,
1341 .mmu_sfsr_mask = 0x00016fff,
1342 .mmu_trcr_mask = 0x00ffffff,
1343 .nwindows = 8,
1344 .features = CPU_DEFAULT_FEATURES,
1347 .name = "TI MicroSparc IIep",
1348 .iu_version = 0x42000000,
1349 .fpu_version = 4 << 17,
1350 .mmu_version = 0x04000000,
1351 .mmu_bm = 0x00004000,
1352 .mmu_ctpr_mask = 0x00ffffc0,
1353 .mmu_cxr_mask = 0x000000ff,
1354 .mmu_sfsr_mask = 0x00016bff,
1355 .mmu_trcr_mask = 0x00ffffff,
1356 .nwindows = 8,
1357 .features = CPU_DEFAULT_FEATURES,
1360 .name = "TI SuperSparc 40", // STP1020NPGA
1361 .iu_version = 0x41000000, // SuperSPARC 2.x
1362 .fpu_version = 0 << 17,
1363 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1364 .mmu_bm = 0x00002000,
1365 .mmu_ctpr_mask = 0xffffffc0,
1366 .mmu_cxr_mask = 0x0000ffff,
1367 .mmu_sfsr_mask = 0xffffffff,
1368 .mmu_trcr_mask = 0xffffffff,
1369 .nwindows = 8,
1370 .features = CPU_DEFAULT_FEATURES,
1373 .name = "TI SuperSparc 50", // STP1020PGA
1374 .iu_version = 0x40000000, // SuperSPARC 3.x
1375 .fpu_version = 0 << 17,
1376 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1377 .mmu_bm = 0x00002000,
1378 .mmu_ctpr_mask = 0xffffffc0,
1379 .mmu_cxr_mask = 0x0000ffff,
1380 .mmu_sfsr_mask = 0xffffffff,
1381 .mmu_trcr_mask = 0xffffffff,
1382 .nwindows = 8,
1383 .features = CPU_DEFAULT_FEATURES,
1386 .name = "TI SuperSparc 51",
1387 .iu_version = 0x40000000, // SuperSPARC 3.x
1388 .fpu_version = 0 << 17,
1389 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1390 .mmu_bm = 0x00002000,
1391 .mmu_ctpr_mask = 0xffffffc0,
1392 .mmu_cxr_mask = 0x0000ffff,
1393 .mmu_sfsr_mask = 0xffffffff,
1394 .mmu_trcr_mask = 0xffffffff,
1395 .mxcc_version = 0x00000104,
1396 .nwindows = 8,
1397 .features = CPU_DEFAULT_FEATURES,
1400 .name = "TI SuperSparc 60", // STP1020APGA
1401 .iu_version = 0x40000000, // SuperSPARC 3.x
1402 .fpu_version = 0 << 17,
1403 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1404 .mmu_bm = 0x00002000,
1405 .mmu_ctpr_mask = 0xffffffc0,
1406 .mmu_cxr_mask = 0x0000ffff,
1407 .mmu_sfsr_mask = 0xffffffff,
1408 .mmu_trcr_mask = 0xffffffff,
1409 .nwindows = 8,
1410 .features = CPU_DEFAULT_FEATURES,
1413 .name = "TI SuperSparc 61",
1414 .iu_version = 0x44000000, // SuperSPARC 3.x
1415 .fpu_version = 0 << 17,
1416 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1417 .mmu_bm = 0x00002000,
1418 .mmu_ctpr_mask = 0xffffffc0,
1419 .mmu_cxr_mask = 0x0000ffff,
1420 .mmu_sfsr_mask = 0xffffffff,
1421 .mmu_trcr_mask = 0xffffffff,
1422 .mxcc_version = 0x00000104,
1423 .nwindows = 8,
1424 .features = CPU_DEFAULT_FEATURES,
1427 .name = "TI SuperSparc II",
1428 .iu_version = 0x40000000, // SuperSPARC II 1.x
1429 .fpu_version = 0 << 17,
1430 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1431 .mmu_bm = 0x00002000,
1432 .mmu_ctpr_mask = 0xffffffc0,
1433 .mmu_cxr_mask = 0x0000ffff,
1434 .mmu_sfsr_mask = 0xffffffff,
1435 .mmu_trcr_mask = 0xffffffff,
1436 .mxcc_version = 0x00000104,
1437 .nwindows = 8,
1438 .features = CPU_DEFAULT_FEATURES,
1441 .name = "Ross RT625",
1442 .iu_version = 0x1e000000,
1443 .fpu_version = 1 << 17,
1444 .mmu_version = 0x1e000000,
1445 .mmu_bm = 0x00004000,
1446 .mmu_ctpr_mask = 0x007ffff0,
1447 .mmu_cxr_mask = 0x0000003f,
1448 .mmu_sfsr_mask = 0xffffffff,
1449 .mmu_trcr_mask = 0xffffffff,
1450 .nwindows = 8,
1451 .features = CPU_DEFAULT_FEATURES,
1454 .name = "Ross RT620",
1455 .iu_version = 0x1f000000,
1456 .fpu_version = 1 << 17,
1457 .mmu_version = 0x1f000000,
1458 .mmu_bm = 0x00004000,
1459 .mmu_ctpr_mask = 0x007ffff0,
1460 .mmu_cxr_mask = 0x0000003f,
1461 .mmu_sfsr_mask = 0xffffffff,
1462 .mmu_trcr_mask = 0xffffffff,
1463 .nwindows = 8,
1464 .features = CPU_DEFAULT_FEATURES,
1467 .name = "BIT B5010",
1468 .iu_version = 0x20000000,
1469 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1470 .mmu_version = 0x20000000,
1471 .mmu_bm = 0x00004000,
1472 .mmu_ctpr_mask = 0x007ffff0,
1473 .mmu_cxr_mask = 0x0000003f,
1474 .mmu_sfsr_mask = 0xffffffff,
1475 .mmu_trcr_mask = 0xffffffff,
1476 .nwindows = 8,
1477 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1478 CPU_FEATURE_FSMULD,
1481 .name = "Matsushita MN10501",
1482 .iu_version = 0x50000000,
1483 .fpu_version = 0 << 17,
1484 .mmu_version = 0x50000000,
1485 .mmu_bm = 0x00004000,
1486 .mmu_ctpr_mask = 0x007ffff0,
1487 .mmu_cxr_mask = 0x0000003f,
1488 .mmu_sfsr_mask = 0xffffffff,
1489 .mmu_trcr_mask = 0xffffffff,
1490 .nwindows = 8,
1491 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1492 CPU_FEATURE_FSMULD,
1495 .name = "Weitek W8601",
1496 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1497 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1498 .mmu_version = 0x10 << 24,
1499 .mmu_bm = 0x00004000,
1500 .mmu_ctpr_mask = 0x007ffff0,
1501 .mmu_cxr_mask = 0x0000003f,
1502 .mmu_sfsr_mask = 0xffffffff,
1503 .mmu_trcr_mask = 0xffffffff,
1504 .nwindows = 8,
1505 .features = CPU_DEFAULT_FEATURES,
1508 .name = "LEON2",
1509 .iu_version = 0xf2000000,
1510 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1511 .mmu_version = 0xf2000000,
1512 .mmu_bm = 0x00004000,
1513 .mmu_ctpr_mask = 0x007ffff0,
1514 .mmu_cxr_mask = 0x0000003f,
1515 .mmu_sfsr_mask = 0xffffffff,
1516 .mmu_trcr_mask = 0xffffffff,
1517 .nwindows = 8,
1518 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
1521 .name = "LEON3",
1522 .iu_version = 0xf3000000,
1523 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1524 .mmu_version = 0xf3000000,
1525 .mmu_bm = 0x00000000,
1526 .mmu_ctpr_mask = 0x007ffff0,
1527 .mmu_cxr_mask = 0x0000003f,
1528 .mmu_sfsr_mask = 0xffffffff,
1529 .mmu_trcr_mask = 0xffffffff,
1530 .nwindows = 8,
1531 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
1532 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
1534 #endif
1537 static const char * const feature_name[] = {
1538 "float",
1539 "float128",
1540 "swap",
1541 "mul",
1542 "div",
1543 "flush",
1544 "fsqrt",
1545 "fmul",
1546 "vis1",
1547 "vis2",
1548 "fsmuld",
1549 "hypv",
1550 "cmt",
1551 "gl",
1554 static void print_features(FILE *f, fprintf_function cpu_fprintf,
1555 uint32_t features, const char *prefix)
1557 unsigned int i;
1559 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1560 if (feature_name[i] && (features & (1 << i))) {
1561 if (prefix)
1562 (*cpu_fprintf)(f, "%s", prefix);
1563 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1567 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1569 unsigned int i;
1571 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1572 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1573 *features |= 1 << i;
1574 return;
1576 fprintf(stderr, "CPU feature %s not found\n", flagname);
1579 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1581 unsigned int i;
1582 const sparc_def_t *def = NULL;
1583 char *s = strdup(cpu_model);
1584 char *featurestr, *name = strtok(s, ",");
1585 uint32_t plus_features = 0;
1586 uint32_t minus_features = 0;
1587 uint64_t iu_version;
1588 uint32_t fpu_version, mmu_version, nwindows;
1590 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1591 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1592 def = &sparc_defs[i];
1595 if (!def)
1596 goto error;
1597 memcpy(cpu_def, def, sizeof(*def));
1599 featurestr = strtok(NULL, ",");
1600 while (featurestr) {
1601 char *val;
1603 if (featurestr[0] == '+') {
1604 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1605 } else if (featurestr[0] == '-') {
1606 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1607 } else if ((val = strchr(featurestr, '='))) {
1608 *val = 0; val++;
1609 if (!strcmp(featurestr, "iu_version")) {
1610 char *err;
1612 iu_version = strtoll(val, &err, 0);
1613 if (!*val || *err) {
1614 fprintf(stderr, "bad numerical value %s\n", val);
1615 goto error;
1617 cpu_def->iu_version = iu_version;
1618 #ifdef DEBUG_FEATURES
1619 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1620 #endif
1621 } else if (!strcmp(featurestr, "fpu_version")) {
1622 char *err;
1624 fpu_version = strtol(val, &err, 0);
1625 if (!*val || *err) {
1626 fprintf(stderr, "bad numerical value %s\n", val);
1627 goto error;
1629 cpu_def->fpu_version = fpu_version;
1630 #ifdef DEBUG_FEATURES
1631 fprintf(stderr, "fpu_version %x\n", fpu_version);
1632 #endif
1633 } else if (!strcmp(featurestr, "mmu_version")) {
1634 char *err;
1636 mmu_version = strtol(val, &err, 0);
1637 if (!*val || *err) {
1638 fprintf(stderr, "bad numerical value %s\n", val);
1639 goto error;
1641 cpu_def->mmu_version = mmu_version;
1642 #ifdef DEBUG_FEATURES
1643 fprintf(stderr, "mmu_version %x\n", mmu_version);
1644 #endif
1645 } else if (!strcmp(featurestr, "nwindows")) {
1646 char *err;
1648 nwindows = strtol(val, &err, 0);
1649 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1650 nwindows < MIN_NWINDOWS) {
1651 fprintf(stderr, "bad numerical value %s\n", val);
1652 goto error;
1654 cpu_def->nwindows = nwindows;
1655 #ifdef DEBUG_FEATURES
1656 fprintf(stderr, "nwindows %d\n", nwindows);
1657 #endif
1658 } else {
1659 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1660 goto error;
1662 } else {
1663 fprintf(stderr, "feature string `%s' not in format "
1664 "(+feature|-feature|feature=xyz)\n", featurestr);
1665 goto error;
1667 featurestr = strtok(NULL, ",");
1669 cpu_def->features |= plus_features;
1670 cpu_def->features &= ~minus_features;
1671 #ifdef DEBUG_FEATURES
1672 print_features(stderr, fprintf, cpu_def->features, NULL);
1673 #endif
1674 free(s);
1675 return 0;
1677 error:
1678 free(s);
1679 return -1;
1682 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
1684 unsigned int i;
1686 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1687 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1688 sparc_defs[i].name,
1689 sparc_defs[i].iu_version,
1690 sparc_defs[i].fpu_version,
1691 sparc_defs[i].mmu_version,
1692 sparc_defs[i].nwindows);
1693 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1694 ~sparc_defs[i].features, "-");
1695 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1696 sparc_defs[i].features, "+");
1697 (*cpu_fprintf)(f, "\n");
1699 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1700 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1701 (*cpu_fprintf)(f, "\n");
1702 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1703 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1704 (*cpu_fprintf)(f, "\n");
1705 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1706 "fpu_version mmu_version nwindows\n");
1709 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
1710 uint32_t cc)
1712 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1713 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1714 cc & PSR_CARRY? 'C' : '-');
1717 #ifdef TARGET_SPARC64
1718 #define REGS_PER_LINE 4
1719 #else
1720 #define REGS_PER_LINE 8
1721 #endif
1723 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1724 int flags)
1726 int i, x;
1728 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1729 env->npc);
1730 cpu_fprintf(f, "General Registers:\n");
1732 for (i = 0; i < 8; i++) {
1733 if (i % REGS_PER_LINE == 0) {
1734 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1736 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1737 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1738 cpu_fprintf(f, "\n");
1741 cpu_fprintf(f, "\nCurrent Register Window:\n");
1742 for (x = 0; x < 3; x++) {
1743 for (i = 0; i < 8; i++) {
1744 if (i % REGS_PER_LINE == 0) {
1745 cpu_fprintf(f, "%%%c%d-%d: ",
1746 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1747 i, i + REGS_PER_LINE - 1);
1749 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1750 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1751 cpu_fprintf(f, "\n");
1755 cpu_fprintf(f, "\nFloating Point Registers:\n");
1756 for (i = 0; i < TARGET_FPREGS; i++) {
1757 if ((i & 3) == 0)
1758 cpu_fprintf(f, "%%f%02d:", i);
1759 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1760 if ((i & 3) == 3)
1761 cpu_fprintf(f, "\n");
1763 #ifdef TARGET_SPARC64
1764 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1765 (unsigned)cpu_get_ccr(env));
1766 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1767 cpu_fprintf(f, " xcc: ");
1768 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1769 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1770 env->psrpil);
1771 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1772 "cleanwin: %d cwp: %d\n",
1773 env->cansave, env->canrestore, env->otherwin, env->wstate,
1774 env->cleanwin, env->nwindows - 1 - env->cwp);
1775 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1776 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1777 #else
1778 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1779 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1780 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1781 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1782 env->wim);
1783 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1784 env->fsr, env->y);
1785 #endif