hw/9pfs: Use read-write lock for protecting fid path.
[qemu.git] / target-sparc / helper.c
blobc80531a16c24aeeb49eb453b872e99e9afa7a071
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)
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)
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 #if !defined(CONFIG_USER_ONLY)
363 /* Gdb expects all registers windows to be flushed in ram. This function handles
364 * reads (and only reads) in stack frames as if windows were flushed. We assume
365 * that the sparc ABI is followed.
367 int target_memory_rw_debug(CPUState *env, target_ulong addr,
368 uint8_t *buf, int len, int is_write)
370 int i;
371 int len1;
372 int cwp = env->cwp;
374 if (!is_write) {
375 for (i = 0; i < env->nwindows; i++) {
376 int off;
377 target_ulong fp = env->regbase[cwp * 16 + 22];
379 /* Assume fp == 0 means end of frame. */
380 if (fp == 0) {
381 break;
384 cwp = cpu_cwp_inc(env, cwp + 1);
386 /* Invalid window ? */
387 if (env->wim & (1 << cwp)) {
388 break;
391 /* According to the ABI, the stack is growing downward. */
392 if (addr + len < fp) {
393 break;
396 /* Not in this frame. */
397 if (addr > fp + 64) {
398 continue;
401 /* Handle access before this window. */
402 if (addr < fp) {
403 len1 = fp - addr;
404 if (cpu_memory_rw_debug(env, addr, buf, len1, is_write) != 0) {
405 return -1;
407 addr += len1;
408 len -= len1;
409 buf += len1;
412 /* Access byte per byte to registers. Not very efficient but speed
413 * is not critical.
415 off = addr - fp;
416 len1 = 64 - off;
418 if (len1 > len) {
419 len1 = len;
422 for (; len1; len1--) {
423 int reg = cwp * 16 + 8 + (off >> 2);
424 union {
425 uint32_t v;
426 uint8_t c[4];
427 } u;
428 u.v = cpu_to_be32(env->regbase[reg]);
429 *buf++ = u.c[off & 3];
430 addr++;
431 len--;
432 off++;
435 if (len == 0) {
436 return 0;
440 return cpu_memory_rw_debug(env, addr, buf, len, is_write);
443 #endif /* !defined(CONFIG_USER_ONLY) */
445 #else /* !TARGET_SPARC64 */
447 // 41 bit physical address space
448 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
450 return x & 0x1ffffffffffULL;
454 * UltraSparc IIi I/DMMUs
457 // Returns true if TTE tag is valid and matches virtual address value in context
458 // requires virtual address mask value calculated from TTE entry size
459 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
460 uint64_t address, uint64_t context,
461 target_phys_addr_t *physical)
463 uint64_t mask;
465 switch (TTE_PGSIZE(tlb->tte)) {
466 default:
467 case 0x0: // 8k
468 mask = 0xffffffffffffe000ULL;
469 break;
470 case 0x1: // 64k
471 mask = 0xffffffffffff0000ULL;
472 break;
473 case 0x2: // 512k
474 mask = 0xfffffffffff80000ULL;
475 break;
476 case 0x3: // 4M
477 mask = 0xffffffffffc00000ULL;
478 break;
481 // valid, context match, virtual address match?
482 if (TTE_IS_VALID(tlb->tte) &&
483 (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
484 && compare_masked(address, tlb->tag, mask))
486 // decode physical address
487 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
488 return 1;
491 return 0;
494 static int get_physical_address_data(CPUState *env,
495 target_phys_addr_t *physical, int *prot,
496 target_ulong address, int rw, int mmu_idx)
498 unsigned int i;
499 uint64_t context;
500 uint64_t sfsr = 0;
502 int is_user = (mmu_idx == MMU_USER_IDX ||
503 mmu_idx == MMU_USER_SECONDARY_IDX);
505 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
506 *physical = ultrasparc_truncate_physical(address);
507 *prot = PAGE_READ | PAGE_WRITE;
508 return 0;
511 switch(mmu_idx) {
512 case MMU_USER_IDX:
513 case MMU_KERNEL_IDX:
514 context = env->dmmu.mmu_primary_context & 0x1fff;
515 sfsr |= SFSR_CT_PRIMARY;
516 break;
517 case MMU_USER_SECONDARY_IDX:
518 case MMU_KERNEL_SECONDARY_IDX:
519 context = env->dmmu.mmu_secondary_context & 0x1fff;
520 sfsr |= SFSR_CT_SECONDARY;
521 break;
522 case MMU_NUCLEUS_IDX:
523 sfsr |= SFSR_CT_NUCLEUS;
524 /* FALLTHRU */
525 default:
526 context = 0;
527 break;
530 if (rw == 1) {
531 sfsr |= SFSR_WRITE_BIT;
532 } else if (rw == 4) {
533 sfsr |= SFSR_NF_BIT;
536 for (i = 0; i < 64; i++) {
537 // ctx match, vaddr match, valid?
538 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
539 int do_fault = 0;
541 // access ok?
542 /* multiple bits in SFSR.FT may be set on TT_DFAULT */
543 if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
544 do_fault = 1;
545 sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
547 DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
548 " mmu_idx=%d tl=%d\n",
549 address, context, mmu_idx, env->tl);
551 if (rw == 4) {
552 if (TTE_IS_SIDEEFFECT(env->dtlb[i].tte)) {
553 do_fault = 1;
554 sfsr |= SFSR_FT_NF_E_BIT;
556 } else {
557 if (TTE_IS_NFO(env->dtlb[i].tte)) {
558 do_fault = 1;
559 sfsr |= SFSR_FT_NFO_BIT;
563 if (do_fault) {
564 /* faults above are reported with TT_DFAULT. */
565 env->exception_index = TT_DFAULT;
566 } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
567 do_fault = 1;
568 env->exception_index = TT_DPROT;
570 DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
571 " mmu_idx=%d tl=%d\n",
572 address, context, mmu_idx, env->tl);
575 if (!do_fault) {
576 *prot = PAGE_READ;
577 if (TTE_IS_W_OK(env->dtlb[i].tte)) {
578 *prot |= PAGE_WRITE;
581 TTE_SET_USED(env->dtlb[i].tte);
583 return 0;
586 if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
587 sfsr |= SFSR_OW_BIT; /* overflow (not read before
588 another fault) */
591 if (env->pstate & PS_PRIV) {
592 sfsr |= SFSR_PR_BIT;
595 /* FIXME: ASI field in SFSR must be set */
596 env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
598 env->dmmu.sfar = address; /* Fault address register */
600 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
602 return 1;
606 DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
607 address, context);
610 * On MMU misses:
611 * - UltraSPARC IIi: SFSR and SFAR unmodified
612 * - JPS1: SFAR updated and some fields of SFSR updated
614 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
615 env->exception_index = TT_DMISS;
616 return 1;
619 static int get_physical_address_code(CPUState *env,
620 target_phys_addr_t *physical, int *prot,
621 target_ulong address, int mmu_idx)
623 unsigned int i;
624 uint64_t context;
626 int is_user = (mmu_idx == MMU_USER_IDX ||
627 mmu_idx == MMU_USER_SECONDARY_IDX);
629 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
630 /* IMMU disabled */
631 *physical = ultrasparc_truncate_physical(address);
632 *prot = PAGE_EXEC;
633 return 0;
636 if (env->tl == 0) {
637 /* PRIMARY context */
638 context = env->dmmu.mmu_primary_context & 0x1fff;
639 } else {
640 /* NUCLEUS context */
641 context = 0;
644 for (i = 0; i < 64; i++) {
645 // ctx match, vaddr match, valid?
646 if (ultrasparc_tag_match(&env->itlb[i],
647 address, context, physical)) {
648 // access ok?
649 if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
650 /* Fault status register */
651 if (env->immu.sfsr & SFSR_VALID_BIT) {
652 env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
653 another fault) */
654 } else {
655 env->immu.sfsr = 0;
657 if (env->pstate & PS_PRIV) {
658 env->immu.sfsr |= SFSR_PR_BIT;
660 if (env->tl > 0) {
661 env->immu.sfsr |= SFSR_CT_NUCLEUS;
664 /* FIXME: ASI field in SFSR must be set */
665 env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
666 env->exception_index = TT_TFAULT;
668 env->immu.tag_access = (address & ~0x1fffULL) | context;
670 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
671 address, context);
673 return 1;
675 *prot = PAGE_EXEC;
676 TTE_SET_USED(env->itlb[i].tte);
677 return 0;
681 DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
682 address, context);
684 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
685 env->immu.tag_access = (address & ~0x1fffULL) | context;
686 env->exception_index = TT_TMISS;
687 return 1;
690 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
691 int *prot, int *access_index,
692 target_ulong address, int rw, int mmu_idx,
693 target_ulong *page_size)
695 /* ??? We treat everything as a small page, then explicitly flush
696 everything when an entry is evicted. */
697 *page_size = TARGET_PAGE_SIZE;
699 #if defined (DEBUG_MMU)
700 /* safety net to catch wrong softmmu index use from dynamic code */
701 if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
702 DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
703 " primary context=%" PRIx64
704 " secondary context=%" PRIx64
705 " address=%" PRIx64
706 "\n",
707 (rw == 2 ? "CODE" : "DATA"),
708 env->tl, mmu_idx,
709 env->dmmu.mmu_primary_context,
710 env->dmmu.mmu_secondary_context,
711 address);
713 #endif
715 if (rw == 2)
716 return get_physical_address_code(env, physical, prot, address,
717 mmu_idx);
718 else
719 return get_physical_address_data(env, physical, prot, address, rw,
720 mmu_idx);
723 /* Perform address translation */
724 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
725 int mmu_idx)
727 target_ulong virt_addr, vaddr;
728 target_phys_addr_t paddr;
729 target_ulong page_size;
730 int error_code = 0, prot, access_index;
732 error_code = get_physical_address(env, &paddr, &prot, &access_index,
733 address, rw, mmu_idx, &page_size);
734 if (error_code == 0) {
735 virt_addr = address & TARGET_PAGE_MASK;
736 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
737 (TARGET_PAGE_SIZE - 1));
739 DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
740 " vaddr %" PRIx64
741 " mmu_idx=%d"
742 " tl=%d"
743 " primary context=%" PRIx64
744 " secondary context=%" PRIx64
745 "\n",
746 address, paddr, vaddr, mmu_idx, env->tl,
747 env->dmmu.mmu_primary_context,
748 env->dmmu.mmu_secondary_context);
750 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
751 return 0;
753 // XXX
754 return 1;
757 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
759 unsigned int i;
760 const char *mask;
762 (*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
763 PRId64 "\n",
764 env->dmmu.mmu_primary_context,
765 env->dmmu.mmu_secondary_context);
766 if ((env->lsu & DMMU_E) == 0) {
767 (*cpu_fprintf)(f, "DMMU disabled\n");
768 } else {
769 (*cpu_fprintf)(f, "DMMU dump\n");
770 for (i = 0; i < 64; i++) {
771 switch (TTE_PGSIZE(env->dtlb[i].tte)) {
772 default:
773 case 0x0:
774 mask = " 8k";
775 break;
776 case 0x1:
777 mask = " 64k";
778 break;
779 case 0x2:
780 mask = "512k";
781 break;
782 case 0x3:
783 mask = " 4M";
784 break;
786 if (TTE_IS_VALID(env->dtlb[i].tte)) {
787 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
788 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
790 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
791 TTE_PA(env->dtlb[i].tte),
792 mask,
793 TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user",
794 TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO",
795 TTE_IS_LOCKED(env->dtlb[i].tte) ?
796 "locked" : "unlocked",
797 env->dtlb[i].tag & (uint64_t)0x1fffULL,
798 TTE_IS_GLOBAL(env->dtlb[i].tte)?
799 "global" : "local");
803 if ((env->lsu & IMMU_E) == 0) {
804 (*cpu_fprintf)(f, "IMMU disabled\n");
805 } else {
806 (*cpu_fprintf)(f, "IMMU dump\n");
807 for (i = 0; i < 64; i++) {
808 switch (TTE_PGSIZE(env->itlb[i].tte)) {
809 default:
810 case 0x0:
811 mask = " 8k";
812 break;
813 case 0x1:
814 mask = " 64k";
815 break;
816 case 0x2:
817 mask = "512k";
818 break;
819 case 0x3:
820 mask = " 4M";
821 break;
823 if (TTE_IS_VALID(env->itlb[i].tte)) {
824 (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx"
825 ", %s, %s, %s, ctx %" PRId64 " %s\n",
827 env->itlb[i].tag & (uint64_t)~0x1fffULL,
828 TTE_PA(env->itlb[i].tte),
829 mask,
830 TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user",
831 TTE_IS_LOCKED(env->itlb[i].tte) ?
832 "locked" : "unlocked",
833 env->itlb[i].tag & (uint64_t)0x1fffULL,
834 TTE_IS_GLOBAL(env->itlb[i].tte)?
835 "global" : "local");
841 #endif /* TARGET_SPARC64 */
842 #endif /* !CONFIG_USER_ONLY */
845 #if !defined(CONFIG_USER_ONLY)
846 static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
847 target_ulong addr, int rw, int mmu_idx)
849 target_ulong page_size;
850 int prot, access_index;
852 return get_physical_address(env, phys, &prot, &access_index, addr, rw,
853 mmu_idx, &page_size);
856 #if defined(TARGET_SPARC64)
857 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
858 int mmu_idx)
860 target_phys_addr_t phys_addr;
862 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 4, mmu_idx) != 0) {
863 return -1;
865 return phys_addr;
867 #endif
869 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
871 target_phys_addr_t phys_addr;
872 int mmu_idx = cpu_mmu_index(env);
874 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
875 if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
876 return -1;
879 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) {
880 return -1;
882 return phys_addr;
884 #endif
886 #ifdef TARGET_SPARC64
887 #ifdef DEBUG_PCALL
888 static const char * const excp_names[0x80] = {
889 [TT_TFAULT] = "Instruction Access Fault",
890 [TT_TMISS] = "Instruction Access MMU Miss",
891 [TT_CODE_ACCESS] = "Instruction Access Error",
892 [TT_ILL_INSN] = "Illegal Instruction",
893 [TT_PRIV_INSN] = "Privileged Instruction",
894 [TT_NFPU_INSN] = "FPU Disabled",
895 [TT_FP_EXCP] = "FPU Exception",
896 [TT_TOVF] = "Tag Overflow",
897 [TT_CLRWIN] = "Clean Windows",
898 [TT_DIV_ZERO] = "Division By Zero",
899 [TT_DFAULT] = "Data Access Fault",
900 [TT_DMISS] = "Data Access MMU Miss",
901 [TT_DATA_ACCESS] = "Data Access Error",
902 [TT_DPROT] = "Data Protection Error",
903 [TT_UNALIGNED] = "Unaligned Memory Access",
904 [TT_PRIV_ACT] = "Privileged Action",
905 [TT_EXTINT | 0x1] = "External Interrupt 1",
906 [TT_EXTINT | 0x2] = "External Interrupt 2",
907 [TT_EXTINT | 0x3] = "External Interrupt 3",
908 [TT_EXTINT | 0x4] = "External Interrupt 4",
909 [TT_EXTINT | 0x5] = "External Interrupt 5",
910 [TT_EXTINT | 0x6] = "External Interrupt 6",
911 [TT_EXTINT | 0x7] = "External Interrupt 7",
912 [TT_EXTINT | 0x8] = "External Interrupt 8",
913 [TT_EXTINT | 0x9] = "External Interrupt 9",
914 [TT_EXTINT | 0xa] = "External Interrupt 10",
915 [TT_EXTINT | 0xb] = "External Interrupt 11",
916 [TT_EXTINT | 0xc] = "External Interrupt 12",
917 [TT_EXTINT | 0xd] = "External Interrupt 13",
918 [TT_EXTINT | 0xe] = "External Interrupt 14",
919 [TT_EXTINT | 0xf] = "External Interrupt 15",
921 #endif
923 void do_interrupt(CPUState *env)
925 int intno = env->exception_index;
926 trap_state *tsptr;
928 #ifdef DEBUG_PCALL
929 if (qemu_loglevel_mask(CPU_LOG_INT)) {
930 static int count;
931 const char *name;
933 if (intno < 0 || intno >= 0x180) {
934 name = "Unknown";
935 } else if (intno >= 0x100) {
936 name = "Trap Instruction";
937 } else if (intno >= 0xc0) {
938 name = "Window Fill";
939 } else if (intno >= 0x80) {
940 name = "Window Spill";
941 } else {
942 name = excp_names[intno];
943 if (!name) {
944 name = "Unknown";
948 qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
949 " SP=%016" PRIx64 "\n",
950 count, name, intno,
951 env->pc,
952 env->npc, env->regwptr[6]);
953 log_cpu_state(env, 0);
954 #if 0
956 int i;
957 uint8_t *ptr;
959 qemu_log(" code=");
960 ptr = (uint8_t *)env->pc;
961 for (i = 0; i < 16; i++) {
962 qemu_log(" %02x", ldub(ptr + i));
964 qemu_log("\n");
966 #endif
967 count++;
969 #endif
970 #if !defined(CONFIG_USER_ONLY)
971 if (env->tl >= env->maxtl) {
972 cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
973 " Error state", env->exception_index, env->tl, env->maxtl);
974 return;
976 #endif
977 if (env->tl < env->maxtl - 1) {
978 env->tl++;
979 } else {
980 env->pstate |= PS_RED;
981 if (env->tl < env->maxtl) {
982 env->tl++;
985 tsptr = cpu_tsptr(env);
987 tsptr->tstate = (cpu_get_ccr(env) << 32) |
988 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
989 cpu_get_cwp64(env);
990 tsptr->tpc = env->pc;
991 tsptr->tnpc = env->npc;
992 tsptr->tt = intno;
994 switch (intno) {
995 case TT_IVEC:
996 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
997 break;
998 case TT_TFAULT:
999 case TT_DFAULT:
1000 case TT_TMISS ... TT_TMISS + 3:
1001 case TT_DMISS ... TT_DMISS + 3:
1002 case TT_DPROT ... TT_DPROT + 3:
1003 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
1004 break;
1005 default:
1006 cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
1007 break;
1010 if (intno == TT_CLRWIN) {
1011 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
1012 } else if ((intno & 0x1c0) == TT_SPILL) {
1013 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
1014 } else if ((intno & 0x1c0) == TT_FILL) {
1015 cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
1017 env->tbr &= ~0x7fffULL;
1018 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1019 env->pc = env->tbr;
1020 env->npc = env->pc + 4;
1021 env->exception_index = -1;
1023 #else
1024 #ifdef DEBUG_PCALL
1025 static const char * const excp_names[0x80] = {
1026 [TT_TFAULT] = "Instruction Access Fault",
1027 [TT_ILL_INSN] = "Illegal Instruction",
1028 [TT_PRIV_INSN] = "Privileged Instruction",
1029 [TT_NFPU_INSN] = "FPU Disabled",
1030 [TT_WIN_OVF] = "Window Overflow",
1031 [TT_WIN_UNF] = "Window Underflow",
1032 [TT_UNALIGNED] = "Unaligned Memory Access",
1033 [TT_FP_EXCP] = "FPU Exception",
1034 [TT_DFAULT] = "Data Access Fault",
1035 [TT_TOVF] = "Tag Overflow",
1036 [TT_EXTINT | 0x1] = "External Interrupt 1",
1037 [TT_EXTINT | 0x2] = "External Interrupt 2",
1038 [TT_EXTINT | 0x3] = "External Interrupt 3",
1039 [TT_EXTINT | 0x4] = "External Interrupt 4",
1040 [TT_EXTINT | 0x5] = "External Interrupt 5",
1041 [TT_EXTINT | 0x6] = "External Interrupt 6",
1042 [TT_EXTINT | 0x7] = "External Interrupt 7",
1043 [TT_EXTINT | 0x8] = "External Interrupt 8",
1044 [TT_EXTINT | 0x9] = "External Interrupt 9",
1045 [TT_EXTINT | 0xa] = "External Interrupt 10",
1046 [TT_EXTINT | 0xb] = "External Interrupt 11",
1047 [TT_EXTINT | 0xc] = "External Interrupt 12",
1048 [TT_EXTINT | 0xd] = "External Interrupt 13",
1049 [TT_EXTINT | 0xe] = "External Interrupt 14",
1050 [TT_EXTINT | 0xf] = "External Interrupt 15",
1051 [TT_TOVF] = "Tag Overflow",
1052 [TT_CODE_ACCESS] = "Instruction Access Error",
1053 [TT_DATA_ACCESS] = "Data Access Error",
1054 [TT_DIV_ZERO] = "Division By Zero",
1055 [TT_NCP_INSN] = "Coprocessor Disabled",
1057 #endif
1059 void do_interrupt(CPUState *env)
1061 int cwp, intno = env->exception_index;
1063 #ifdef DEBUG_PCALL
1064 if (qemu_loglevel_mask(CPU_LOG_INT)) {
1065 static int count;
1066 const char *name;
1068 if (intno < 0 || intno >= 0x100) {
1069 name = "Unknown";
1070 } else if (intno >= 0x80) {
1071 name = "Trap Instruction";
1072 } else {
1073 name = excp_names[intno];
1074 if (!name) {
1075 name = "Unknown";
1079 qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
1080 count, name, intno,
1081 env->pc,
1082 env->npc, env->regwptr[6]);
1083 log_cpu_state(env, 0);
1084 #if 0
1086 int i;
1087 uint8_t *ptr;
1089 qemu_log(" code=");
1090 ptr = (uint8_t *)env->pc;
1091 for (i = 0; i < 16; i++) {
1092 qemu_log(" %02x", ldub(ptr + i));
1094 qemu_log("\n");
1096 #endif
1097 count++;
1099 #endif
1100 #if !defined(CONFIG_USER_ONLY)
1101 if (env->psret == 0) {
1102 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
1103 env->exception_index);
1104 return;
1106 #endif
1107 env->psret = 0;
1108 cwp = cpu_cwp_dec(env, env->cwp - 1);
1109 cpu_set_cwp(env, cwp);
1110 env->regwptr[9] = env->pc;
1111 env->regwptr[10] = env->npc;
1112 env->psrps = env->psrs;
1113 env->psrs = 1;
1114 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1115 env->pc = env->tbr;
1116 env->npc = env->pc + 4;
1117 env->exception_index = -1;
1119 #if !defined(CONFIG_USER_ONLY)
1120 /* IRQ acknowledgment */
1121 if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
1122 env->qemu_irq_ack(env->irq_manager, intno);
1124 #endif
1126 #endif
1128 void cpu_reset(CPUSPARCState *env)
1130 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1131 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
1132 log_cpu_state(env, 0);
1135 tlb_flush(env, 1);
1136 env->cwp = 0;
1137 #ifndef TARGET_SPARC64
1138 env->wim = 1;
1139 #endif
1140 env->regwptr = env->regbase + (env->cwp * 16);
1141 CC_OP = CC_OP_FLAGS;
1142 #if defined(CONFIG_USER_ONLY)
1143 #ifdef TARGET_SPARC64
1144 env->cleanwin = env->nwindows - 2;
1145 env->cansave = env->nwindows - 2;
1146 env->pstate = PS_RMO | PS_PEF | PS_IE;
1147 env->asi = 0x82; // Primary no-fault
1148 #endif
1149 #else
1150 #if !defined(TARGET_SPARC64)
1151 env->psret = 0;
1152 env->psrs = 1;
1153 env->psrps = 1;
1154 #endif
1155 #ifdef TARGET_SPARC64
1156 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
1157 env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
1158 env->tl = env->maxtl;
1159 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
1160 env->lsu = 0;
1161 #else
1162 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
1163 env->mmuregs[0] |= env->def->mmu_bm;
1164 #endif
1165 env->pc = 0;
1166 env->npc = env->pc + 4;
1167 #endif
1168 env->cache_control = 0;
1171 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
1173 sparc_def_t def1, *def = &def1;
1175 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
1176 return -1;
1178 env->def = g_malloc0(sizeof(*def));
1179 memcpy(env->def, def, sizeof(*def));
1180 #if defined(CONFIG_USER_ONLY)
1181 if ((env->def->features & CPU_FEATURE_FLOAT))
1182 env->def->features |= CPU_FEATURE_FLOAT128;
1183 #endif
1184 env->cpu_model_str = cpu_model;
1185 env->version = def->iu_version;
1186 env->fsr = def->fpu_version;
1187 env->nwindows = def->nwindows;
1188 #if !defined(TARGET_SPARC64)
1189 env->mmuregs[0] |= def->mmu_version;
1190 cpu_sparc_set_id(env, 0);
1191 env->mxccregs[7] |= def->mxcc_version;
1192 #else
1193 env->mmu_version = def->mmu_version;
1194 env->maxtl = def->maxtl;
1195 env->version |= def->maxtl << 8;
1196 env->version |= def->nwindows - 1;
1197 #endif
1198 return 0;
1201 static void cpu_sparc_close(CPUSPARCState *env)
1203 free(env->def);
1204 free(env);
1207 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
1209 CPUSPARCState *env;
1211 env = g_malloc0(sizeof(CPUSPARCState));
1212 cpu_exec_init(env);
1214 gen_intermediate_code_init(env);
1216 if (cpu_sparc_register(env, cpu_model) < 0) {
1217 cpu_sparc_close(env);
1218 return NULL;
1220 qemu_init_vcpu(env);
1222 return env;
1225 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
1227 #if !defined(TARGET_SPARC64)
1228 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
1229 #endif
1232 static const sparc_def_t sparc_defs[] = {
1233 #ifdef TARGET_SPARC64
1235 .name = "Fujitsu Sparc64",
1236 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
1237 .fpu_version = 0x00000000,
1238 .mmu_version = mmu_us_12,
1239 .nwindows = 4,
1240 .maxtl = 4,
1241 .features = CPU_DEFAULT_FEATURES,
1244 .name = "Fujitsu Sparc64 III",
1245 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
1246 .fpu_version = 0x00000000,
1247 .mmu_version = mmu_us_12,
1248 .nwindows = 5,
1249 .maxtl = 4,
1250 .features = CPU_DEFAULT_FEATURES,
1253 .name = "Fujitsu Sparc64 IV",
1254 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
1255 .fpu_version = 0x00000000,
1256 .mmu_version = mmu_us_12,
1257 .nwindows = 8,
1258 .maxtl = 5,
1259 .features = CPU_DEFAULT_FEATURES,
1262 .name = "Fujitsu Sparc64 V",
1263 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
1264 .fpu_version = 0x00000000,
1265 .mmu_version = mmu_us_12,
1266 .nwindows = 8,
1267 .maxtl = 5,
1268 .features = CPU_DEFAULT_FEATURES,
1271 .name = "TI UltraSparc I",
1272 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1273 .fpu_version = 0x00000000,
1274 .mmu_version = mmu_us_12,
1275 .nwindows = 8,
1276 .maxtl = 5,
1277 .features = CPU_DEFAULT_FEATURES,
1280 .name = "TI UltraSparc II",
1281 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
1282 .fpu_version = 0x00000000,
1283 .mmu_version = mmu_us_12,
1284 .nwindows = 8,
1285 .maxtl = 5,
1286 .features = CPU_DEFAULT_FEATURES,
1289 .name = "TI UltraSparc IIi",
1290 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
1291 .fpu_version = 0x00000000,
1292 .mmu_version = mmu_us_12,
1293 .nwindows = 8,
1294 .maxtl = 5,
1295 .features = CPU_DEFAULT_FEATURES,
1298 .name = "TI UltraSparc IIe",
1299 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
1300 .fpu_version = 0x00000000,
1301 .mmu_version = mmu_us_12,
1302 .nwindows = 8,
1303 .maxtl = 5,
1304 .features = CPU_DEFAULT_FEATURES,
1307 .name = "Sun UltraSparc III",
1308 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
1309 .fpu_version = 0x00000000,
1310 .mmu_version = mmu_us_12,
1311 .nwindows = 8,
1312 .maxtl = 5,
1313 .features = CPU_DEFAULT_FEATURES,
1316 .name = "Sun UltraSparc III Cu",
1317 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
1318 .fpu_version = 0x00000000,
1319 .mmu_version = mmu_us_3,
1320 .nwindows = 8,
1321 .maxtl = 5,
1322 .features = CPU_DEFAULT_FEATURES,
1325 .name = "Sun UltraSparc IIIi",
1326 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
1327 .fpu_version = 0x00000000,
1328 .mmu_version = mmu_us_12,
1329 .nwindows = 8,
1330 .maxtl = 5,
1331 .features = CPU_DEFAULT_FEATURES,
1334 .name = "Sun UltraSparc IV",
1335 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
1336 .fpu_version = 0x00000000,
1337 .mmu_version = mmu_us_4,
1338 .nwindows = 8,
1339 .maxtl = 5,
1340 .features = CPU_DEFAULT_FEATURES,
1343 .name = "Sun UltraSparc IV+",
1344 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
1345 .fpu_version = 0x00000000,
1346 .mmu_version = mmu_us_12,
1347 .nwindows = 8,
1348 .maxtl = 5,
1349 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
1352 .name = "Sun UltraSparc IIIi+",
1353 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
1354 .fpu_version = 0x00000000,
1355 .mmu_version = mmu_us_3,
1356 .nwindows = 8,
1357 .maxtl = 5,
1358 .features = CPU_DEFAULT_FEATURES,
1361 .name = "Sun UltraSparc T1",
1362 // defined in sparc_ifu_fdp.v and ctu.h
1363 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
1364 .fpu_version = 0x00000000,
1365 .mmu_version = mmu_sun4v,
1366 .nwindows = 8,
1367 .maxtl = 6,
1368 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1369 | CPU_FEATURE_GL,
1372 .name = "Sun UltraSparc T2",
1373 // defined in tlu_asi_ctl.v and n2_revid_cust.v
1374 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
1375 .fpu_version = 0x00000000,
1376 .mmu_version = mmu_sun4v,
1377 .nwindows = 8,
1378 .maxtl = 6,
1379 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1380 | CPU_FEATURE_GL,
1383 .name = "NEC UltraSparc I",
1384 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1385 .fpu_version = 0x00000000,
1386 .mmu_version = mmu_us_12,
1387 .nwindows = 8,
1388 .maxtl = 5,
1389 .features = CPU_DEFAULT_FEATURES,
1391 #else
1393 .name = "Fujitsu MB86900",
1394 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1395 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1396 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
1397 .mmu_bm = 0x00004000,
1398 .mmu_ctpr_mask = 0x007ffff0,
1399 .mmu_cxr_mask = 0x0000003f,
1400 .mmu_sfsr_mask = 0xffffffff,
1401 .mmu_trcr_mask = 0xffffffff,
1402 .nwindows = 7,
1403 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1406 .name = "Fujitsu MB86904",
1407 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1408 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1409 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1410 .mmu_bm = 0x00004000,
1411 .mmu_ctpr_mask = 0x00ffffc0,
1412 .mmu_cxr_mask = 0x000000ff,
1413 .mmu_sfsr_mask = 0x00016fff,
1414 .mmu_trcr_mask = 0x00ffffff,
1415 .nwindows = 8,
1416 .features = CPU_DEFAULT_FEATURES,
1419 .name = "Fujitsu MB86907",
1420 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1421 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1422 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1423 .mmu_bm = 0x00004000,
1424 .mmu_ctpr_mask = 0xffffffc0,
1425 .mmu_cxr_mask = 0x000000ff,
1426 .mmu_sfsr_mask = 0x00016fff,
1427 .mmu_trcr_mask = 0xffffffff,
1428 .nwindows = 8,
1429 .features = CPU_DEFAULT_FEATURES,
1432 .name = "LSI L64811",
1433 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1434 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1435 .mmu_version = 0x10 << 24,
1436 .mmu_bm = 0x00004000,
1437 .mmu_ctpr_mask = 0x007ffff0,
1438 .mmu_cxr_mask = 0x0000003f,
1439 .mmu_sfsr_mask = 0xffffffff,
1440 .mmu_trcr_mask = 0xffffffff,
1441 .nwindows = 8,
1442 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1443 CPU_FEATURE_FSMULD,
1446 .name = "Cypress CY7C601",
1447 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1448 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1449 .mmu_version = 0x10 << 24,
1450 .mmu_bm = 0x00004000,
1451 .mmu_ctpr_mask = 0x007ffff0,
1452 .mmu_cxr_mask = 0x0000003f,
1453 .mmu_sfsr_mask = 0xffffffff,
1454 .mmu_trcr_mask = 0xffffffff,
1455 .nwindows = 8,
1456 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1457 CPU_FEATURE_FSMULD,
1460 .name = "Cypress CY7C611",
1461 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1462 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1463 .mmu_version = 0x10 << 24,
1464 .mmu_bm = 0x00004000,
1465 .mmu_ctpr_mask = 0x007ffff0,
1466 .mmu_cxr_mask = 0x0000003f,
1467 .mmu_sfsr_mask = 0xffffffff,
1468 .mmu_trcr_mask = 0xffffffff,
1469 .nwindows = 8,
1470 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1471 CPU_FEATURE_FSMULD,
1474 .name = "TI MicroSparc I",
1475 .iu_version = 0x41000000,
1476 .fpu_version = 4 << 17,
1477 .mmu_version = 0x41000000,
1478 .mmu_bm = 0x00004000,
1479 .mmu_ctpr_mask = 0x007ffff0,
1480 .mmu_cxr_mask = 0x0000003f,
1481 .mmu_sfsr_mask = 0x00016fff,
1482 .mmu_trcr_mask = 0x0000003f,
1483 .nwindows = 7,
1484 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1485 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1486 CPU_FEATURE_FMUL,
1489 .name = "TI MicroSparc II",
1490 .iu_version = 0x42000000,
1491 .fpu_version = 4 << 17,
1492 .mmu_version = 0x02000000,
1493 .mmu_bm = 0x00004000,
1494 .mmu_ctpr_mask = 0x00ffffc0,
1495 .mmu_cxr_mask = 0x000000ff,
1496 .mmu_sfsr_mask = 0x00016fff,
1497 .mmu_trcr_mask = 0x00ffffff,
1498 .nwindows = 8,
1499 .features = CPU_DEFAULT_FEATURES,
1502 .name = "TI MicroSparc IIep",
1503 .iu_version = 0x42000000,
1504 .fpu_version = 4 << 17,
1505 .mmu_version = 0x04000000,
1506 .mmu_bm = 0x00004000,
1507 .mmu_ctpr_mask = 0x00ffffc0,
1508 .mmu_cxr_mask = 0x000000ff,
1509 .mmu_sfsr_mask = 0x00016bff,
1510 .mmu_trcr_mask = 0x00ffffff,
1511 .nwindows = 8,
1512 .features = CPU_DEFAULT_FEATURES,
1515 .name = "TI SuperSparc 40", // STP1020NPGA
1516 .iu_version = 0x41000000, // SuperSPARC 2.x
1517 .fpu_version = 0 << 17,
1518 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1519 .mmu_bm = 0x00002000,
1520 .mmu_ctpr_mask = 0xffffffc0,
1521 .mmu_cxr_mask = 0x0000ffff,
1522 .mmu_sfsr_mask = 0xffffffff,
1523 .mmu_trcr_mask = 0xffffffff,
1524 .nwindows = 8,
1525 .features = CPU_DEFAULT_FEATURES,
1528 .name = "TI SuperSparc 50", // STP1020PGA
1529 .iu_version = 0x40000000, // SuperSPARC 3.x
1530 .fpu_version = 0 << 17,
1531 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1532 .mmu_bm = 0x00002000,
1533 .mmu_ctpr_mask = 0xffffffc0,
1534 .mmu_cxr_mask = 0x0000ffff,
1535 .mmu_sfsr_mask = 0xffffffff,
1536 .mmu_trcr_mask = 0xffffffff,
1537 .nwindows = 8,
1538 .features = CPU_DEFAULT_FEATURES,
1541 .name = "TI SuperSparc 51",
1542 .iu_version = 0x40000000, // SuperSPARC 3.x
1543 .fpu_version = 0 << 17,
1544 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1545 .mmu_bm = 0x00002000,
1546 .mmu_ctpr_mask = 0xffffffc0,
1547 .mmu_cxr_mask = 0x0000ffff,
1548 .mmu_sfsr_mask = 0xffffffff,
1549 .mmu_trcr_mask = 0xffffffff,
1550 .mxcc_version = 0x00000104,
1551 .nwindows = 8,
1552 .features = CPU_DEFAULT_FEATURES,
1555 .name = "TI SuperSparc 60", // STP1020APGA
1556 .iu_version = 0x40000000, // SuperSPARC 3.x
1557 .fpu_version = 0 << 17,
1558 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1559 .mmu_bm = 0x00002000,
1560 .mmu_ctpr_mask = 0xffffffc0,
1561 .mmu_cxr_mask = 0x0000ffff,
1562 .mmu_sfsr_mask = 0xffffffff,
1563 .mmu_trcr_mask = 0xffffffff,
1564 .nwindows = 8,
1565 .features = CPU_DEFAULT_FEATURES,
1568 .name = "TI SuperSparc 61",
1569 .iu_version = 0x44000000, // SuperSPARC 3.x
1570 .fpu_version = 0 << 17,
1571 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1572 .mmu_bm = 0x00002000,
1573 .mmu_ctpr_mask = 0xffffffc0,
1574 .mmu_cxr_mask = 0x0000ffff,
1575 .mmu_sfsr_mask = 0xffffffff,
1576 .mmu_trcr_mask = 0xffffffff,
1577 .mxcc_version = 0x00000104,
1578 .nwindows = 8,
1579 .features = CPU_DEFAULT_FEATURES,
1582 .name = "TI SuperSparc II",
1583 .iu_version = 0x40000000, // SuperSPARC II 1.x
1584 .fpu_version = 0 << 17,
1585 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1586 .mmu_bm = 0x00002000,
1587 .mmu_ctpr_mask = 0xffffffc0,
1588 .mmu_cxr_mask = 0x0000ffff,
1589 .mmu_sfsr_mask = 0xffffffff,
1590 .mmu_trcr_mask = 0xffffffff,
1591 .mxcc_version = 0x00000104,
1592 .nwindows = 8,
1593 .features = CPU_DEFAULT_FEATURES,
1596 .name = "Ross RT625",
1597 .iu_version = 0x1e000000,
1598 .fpu_version = 1 << 17,
1599 .mmu_version = 0x1e000000,
1600 .mmu_bm = 0x00004000,
1601 .mmu_ctpr_mask = 0x007ffff0,
1602 .mmu_cxr_mask = 0x0000003f,
1603 .mmu_sfsr_mask = 0xffffffff,
1604 .mmu_trcr_mask = 0xffffffff,
1605 .nwindows = 8,
1606 .features = CPU_DEFAULT_FEATURES,
1609 .name = "Ross RT620",
1610 .iu_version = 0x1f000000,
1611 .fpu_version = 1 << 17,
1612 .mmu_version = 0x1f000000,
1613 .mmu_bm = 0x00004000,
1614 .mmu_ctpr_mask = 0x007ffff0,
1615 .mmu_cxr_mask = 0x0000003f,
1616 .mmu_sfsr_mask = 0xffffffff,
1617 .mmu_trcr_mask = 0xffffffff,
1618 .nwindows = 8,
1619 .features = CPU_DEFAULT_FEATURES,
1622 .name = "BIT B5010",
1623 .iu_version = 0x20000000,
1624 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1625 .mmu_version = 0x20000000,
1626 .mmu_bm = 0x00004000,
1627 .mmu_ctpr_mask = 0x007ffff0,
1628 .mmu_cxr_mask = 0x0000003f,
1629 .mmu_sfsr_mask = 0xffffffff,
1630 .mmu_trcr_mask = 0xffffffff,
1631 .nwindows = 8,
1632 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1633 CPU_FEATURE_FSMULD,
1636 .name = "Matsushita MN10501",
1637 .iu_version = 0x50000000,
1638 .fpu_version = 0 << 17,
1639 .mmu_version = 0x50000000,
1640 .mmu_bm = 0x00004000,
1641 .mmu_ctpr_mask = 0x007ffff0,
1642 .mmu_cxr_mask = 0x0000003f,
1643 .mmu_sfsr_mask = 0xffffffff,
1644 .mmu_trcr_mask = 0xffffffff,
1645 .nwindows = 8,
1646 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1647 CPU_FEATURE_FSMULD,
1650 .name = "Weitek W8601",
1651 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1652 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1653 .mmu_version = 0x10 << 24,
1654 .mmu_bm = 0x00004000,
1655 .mmu_ctpr_mask = 0x007ffff0,
1656 .mmu_cxr_mask = 0x0000003f,
1657 .mmu_sfsr_mask = 0xffffffff,
1658 .mmu_trcr_mask = 0xffffffff,
1659 .nwindows = 8,
1660 .features = CPU_DEFAULT_FEATURES,
1663 .name = "LEON2",
1664 .iu_version = 0xf2000000,
1665 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1666 .mmu_version = 0xf2000000,
1667 .mmu_bm = 0x00004000,
1668 .mmu_ctpr_mask = 0x007ffff0,
1669 .mmu_cxr_mask = 0x0000003f,
1670 .mmu_sfsr_mask = 0xffffffff,
1671 .mmu_trcr_mask = 0xffffffff,
1672 .nwindows = 8,
1673 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
1676 .name = "LEON3",
1677 .iu_version = 0xf3000000,
1678 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1679 .mmu_version = 0xf3000000,
1680 .mmu_bm = 0x00000000,
1681 .mmu_ctpr_mask = 0x007ffff0,
1682 .mmu_cxr_mask = 0x0000003f,
1683 .mmu_sfsr_mask = 0xffffffff,
1684 .mmu_trcr_mask = 0xffffffff,
1685 .nwindows = 8,
1686 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
1687 CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
1689 #endif
1692 static const char * const feature_name[] = {
1693 "float",
1694 "float128",
1695 "swap",
1696 "mul",
1697 "div",
1698 "flush",
1699 "fsqrt",
1700 "fmul",
1701 "vis1",
1702 "vis2",
1703 "fsmuld",
1704 "hypv",
1705 "cmt",
1706 "gl",
1709 static void print_features(FILE *f, fprintf_function cpu_fprintf,
1710 uint32_t features, const char *prefix)
1712 unsigned int i;
1714 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1715 if (feature_name[i] && (features & (1 << i))) {
1716 if (prefix)
1717 (*cpu_fprintf)(f, "%s", prefix);
1718 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1722 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1724 unsigned int i;
1726 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1727 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1728 *features |= 1 << i;
1729 return;
1731 fprintf(stderr, "CPU feature %s not found\n", flagname);
1734 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1736 unsigned int i;
1737 const sparc_def_t *def = NULL;
1738 char *s = strdup(cpu_model);
1739 char *featurestr, *name = strtok(s, ",");
1740 uint32_t plus_features = 0;
1741 uint32_t minus_features = 0;
1742 uint64_t iu_version;
1743 uint32_t fpu_version, mmu_version, nwindows;
1745 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1746 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1747 def = &sparc_defs[i];
1750 if (!def)
1751 goto error;
1752 memcpy(cpu_def, def, sizeof(*def));
1754 featurestr = strtok(NULL, ",");
1755 while (featurestr) {
1756 char *val;
1758 if (featurestr[0] == '+') {
1759 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1760 } else if (featurestr[0] == '-') {
1761 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1762 } else if ((val = strchr(featurestr, '='))) {
1763 *val = 0; val++;
1764 if (!strcmp(featurestr, "iu_version")) {
1765 char *err;
1767 iu_version = strtoll(val, &err, 0);
1768 if (!*val || *err) {
1769 fprintf(stderr, "bad numerical value %s\n", val);
1770 goto error;
1772 cpu_def->iu_version = iu_version;
1773 #ifdef DEBUG_FEATURES
1774 fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
1775 #endif
1776 } else if (!strcmp(featurestr, "fpu_version")) {
1777 char *err;
1779 fpu_version = strtol(val, &err, 0);
1780 if (!*val || *err) {
1781 fprintf(stderr, "bad numerical value %s\n", val);
1782 goto error;
1784 cpu_def->fpu_version = fpu_version;
1785 #ifdef DEBUG_FEATURES
1786 fprintf(stderr, "fpu_version %x\n", fpu_version);
1787 #endif
1788 } else if (!strcmp(featurestr, "mmu_version")) {
1789 char *err;
1791 mmu_version = strtol(val, &err, 0);
1792 if (!*val || *err) {
1793 fprintf(stderr, "bad numerical value %s\n", val);
1794 goto error;
1796 cpu_def->mmu_version = mmu_version;
1797 #ifdef DEBUG_FEATURES
1798 fprintf(stderr, "mmu_version %x\n", mmu_version);
1799 #endif
1800 } else if (!strcmp(featurestr, "nwindows")) {
1801 char *err;
1803 nwindows = strtol(val, &err, 0);
1804 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1805 nwindows < MIN_NWINDOWS) {
1806 fprintf(stderr, "bad numerical value %s\n", val);
1807 goto error;
1809 cpu_def->nwindows = nwindows;
1810 #ifdef DEBUG_FEATURES
1811 fprintf(stderr, "nwindows %d\n", nwindows);
1812 #endif
1813 } else {
1814 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1815 goto error;
1817 } else {
1818 fprintf(stderr, "feature string `%s' not in format "
1819 "(+feature|-feature|feature=xyz)\n", featurestr);
1820 goto error;
1822 featurestr = strtok(NULL, ",");
1824 cpu_def->features |= plus_features;
1825 cpu_def->features &= ~minus_features;
1826 #ifdef DEBUG_FEATURES
1827 print_features(stderr, fprintf, cpu_def->features, NULL);
1828 #endif
1829 free(s);
1830 return 0;
1832 error:
1833 free(s);
1834 return -1;
1837 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
1839 unsigned int i;
1841 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1842 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1843 sparc_defs[i].name,
1844 sparc_defs[i].iu_version,
1845 sparc_defs[i].fpu_version,
1846 sparc_defs[i].mmu_version,
1847 sparc_defs[i].nwindows);
1848 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1849 ~sparc_defs[i].features, "-");
1850 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1851 sparc_defs[i].features, "+");
1852 (*cpu_fprintf)(f, "\n");
1854 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1855 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1856 (*cpu_fprintf)(f, "\n");
1857 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1858 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1859 (*cpu_fprintf)(f, "\n");
1860 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1861 "fpu_version mmu_version nwindows\n");
1864 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
1865 uint32_t cc)
1867 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1868 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1869 cc & PSR_CARRY? 'C' : '-');
1872 #ifdef TARGET_SPARC64
1873 #define REGS_PER_LINE 4
1874 #else
1875 #define REGS_PER_LINE 8
1876 #endif
1878 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1879 int flags)
1881 int i, x;
1883 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1884 env->npc);
1885 cpu_fprintf(f, "General Registers:\n");
1887 for (i = 0; i < 8; i++) {
1888 if (i % REGS_PER_LINE == 0) {
1889 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1891 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1892 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1893 cpu_fprintf(f, "\n");
1896 cpu_fprintf(f, "\nCurrent Register Window:\n");
1897 for (x = 0; x < 3; x++) {
1898 for (i = 0; i < 8; i++) {
1899 if (i % REGS_PER_LINE == 0) {
1900 cpu_fprintf(f, "%%%c%d-%d: ",
1901 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1902 i, i + REGS_PER_LINE - 1);
1904 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1905 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1906 cpu_fprintf(f, "\n");
1910 cpu_fprintf(f, "\nFloating Point Registers:\n");
1911 for (i = 0; i < TARGET_FPREGS; i++) {
1912 if ((i & 3) == 0)
1913 cpu_fprintf(f, "%%f%02d:", i);
1914 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1915 if ((i & 3) == 3)
1916 cpu_fprintf(f, "\n");
1918 #ifdef TARGET_SPARC64
1919 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1920 (unsigned)cpu_get_ccr(env));
1921 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1922 cpu_fprintf(f, " xcc: ");
1923 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1924 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1925 env->psrpil);
1926 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1927 "cleanwin: %d cwp: %d\n",
1928 env->cansave, env->canrestore, env->otherwin, env->wstate,
1929 env->cleanwin, env->nwindows - 1 - env->cwp);
1930 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1931 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1932 #else
1933 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1934 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1935 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1936 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1937 env->wim);
1938 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1939 env->fsr, env->y);
1940 #endif