tcg-i386: Tidy xchg.
[qemu/aliguori-queue.git] / target-sparc / helper.c
blob582de1082c1e1d73029e59d9055419b661ee7810
1 /*
2 * sparc helpers
4 * Copyright (c) 2003-2005 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <signal.h>
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "qemu-common.h"
30 //#define DEBUG_MMU
31 //#define DEBUG_FEATURES
33 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
35 /* Sparc MMU emulation */
37 /* thread support */
39 static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
41 void cpu_lock(void)
43 spin_lock(&global_cpu_lock);
46 void cpu_unlock(void)
48 spin_unlock(&global_cpu_lock);
51 #if defined(CONFIG_USER_ONLY)
53 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
54 int mmu_idx, int is_softmmu)
56 if (rw & 2)
57 env1->exception_index = TT_TFAULT;
58 else
59 env1->exception_index = TT_DFAULT;
60 return 1;
63 #else
65 #ifndef TARGET_SPARC64
67 * Sparc V8 Reference MMU (SRMMU)
69 static const int access_table[8][8] = {
70 { 0, 0, 0, 0, 8, 0, 12, 12 },
71 { 0, 0, 0, 0, 8, 0, 0, 0 },
72 { 8, 8, 0, 0, 0, 8, 12, 12 },
73 { 8, 8, 0, 0, 0, 8, 0, 0 },
74 { 8, 0, 8, 0, 8, 8, 12, 12 },
75 { 8, 0, 8, 0, 8, 0, 8, 0 },
76 { 8, 8, 8, 0, 8, 8, 12, 12 },
77 { 8, 8, 8, 0, 8, 8, 8, 0 }
80 static const int perm_table[2][8] = {
82 PAGE_READ,
83 PAGE_READ | PAGE_WRITE,
84 PAGE_READ | PAGE_EXEC,
85 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
86 PAGE_EXEC,
87 PAGE_READ | PAGE_WRITE,
88 PAGE_READ | PAGE_EXEC,
89 PAGE_READ | PAGE_WRITE | PAGE_EXEC
92 PAGE_READ,
93 PAGE_READ | PAGE_WRITE,
94 PAGE_READ | PAGE_EXEC,
95 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
96 PAGE_EXEC,
97 PAGE_READ,
103 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
104 int *prot, int *access_index,
105 target_ulong address, int rw, int mmu_idx,
106 target_ulong *page_size)
108 int access_perms = 0;
109 target_phys_addr_t pde_ptr;
110 uint32_t pde;
111 int error_code = 0, is_dirty, is_user;
112 unsigned long page_offset;
114 is_user = mmu_idx == MMU_USER_IDX;
116 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
117 *page_size = TARGET_PAGE_SIZE;
118 // Boot mode: instruction fetches are taken from PROM
119 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
120 *physical = env->prom_addr | (address & 0x7ffffULL);
121 *prot = PAGE_READ | PAGE_EXEC;
122 return 0;
124 *physical = address;
125 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
126 return 0;
129 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
130 *physical = 0xffffffffffff0000ULL;
132 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
133 /* Context base + context number */
134 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
135 pde = ldl_phys(pde_ptr);
137 /* Ctx pde */
138 switch (pde & PTE_ENTRYTYPE_MASK) {
139 default:
140 case 0: /* Invalid */
141 return 1 << 2;
142 case 2: /* L0 PTE, maybe should not happen? */
143 case 3: /* Reserved */
144 return 4 << 2;
145 case 1: /* L0 PDE */
146 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
147 pde = ldl_phys(pde_ptr);
149 switch (pde & PTE_ENTRYTYPE_MASK) {
150 default:
151 case 0: /* Invalid */
152 return (1 << 8) | (1 << 2);
153 case 3: /* Reserved */
154 return (1 << 8) | (4 << 2);
155 case 1: /* L1 PDE */
156 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
157 pde = ldl_phys(pde_ptr);
159 switch (pde & PTE_ENTRYTYPE_MASK) {
160 default:
161 case 0: /* Invalid */
162 return (2 << 8) | (1 << 2);
163 case 3: /* Reserved */
164 return (2 << 8) | (4 << 2);
165 case 1: /* L2 PDE */
166 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
167 pde = ldl_phys(pde_ptr);
169 switch (pde & PTE_ENTRYTYPE_MASK) {
170 default:
171 case 0: /* Invalid */
172 return (3 << 8) | (1 << 2);
173 case 1: /* PDE, should not happen */
174 case 3: /* Reserved */
175 return (3 << 8) | (4 << 2);
176 case 2: /* L3 PTE */
177 page_offset = (address & TARGET_PAGE_MASK) &
178 (TARGET_PAGE_SIZE - 1);
180 *page_size = TARGET_PAGE_SIZE;
181 break;
182 case 2: /* L2 PTE */
183 page_offset = address & 0x3ffff;
184 *page_size = 0x40000;
186 break;
187 case 2: /* L1 PTE */
188 page_offset = address & 0xffffff;
189 *page_size = 0x1000000;
193 /* check access */
194 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
195 error_code = access_table[*access_index][access_perms];
196 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
197 return error_code;
199 /* update page modified and dirty bits */
200 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
201 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
202 pde |= PG_ACCESSED_MASK;
203 if (is_dirty)
204 pde |= PG_MODIFIED_MASK;
205 stl_phys_notdirty(pde_ptr, pde);
208 /* the page can be put in the TLB */
209 *prot = perm_table[is_user][access_perms];
210 if (!(pde & PG_MODIFIED_MASK)) {
211 /* only set write access if already dirty... otherwise wait
212 for dirty access */
213 *prot &= ~PAGE_WRITE;
216 /* Even if large ptes, we map only one 4KB page in the cache to
217 avoid filling it too fast */
218 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
219 return error_code;
222 /* Perform address translation */
223 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
224 int mmu_idx, int is_softmmu)
226 target_phys_addr_t paddr;
227 target_ulong vaddr;
228 target_ulong page_size;
229 int error_code = 0, prot, access_index;
231 error_code = get_physical_address(env, &paddr, &prot, &access_index,
232 address, rw, mmu_idx, &page_size);
233 if (error_code == 0) {
234 vaddr = address & TARGET_PAGE_MASK;
235 paddr &= TARGET_PAGE_MASK;
236 #ifdef DEBUG_MMU
237 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
238 TARGET_FMT_lx "\n", address, paddr, vaddr);
239 #endif
240 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
241 return 0;
244 if (env->mmuregs[3]) /* Fault status register */
245 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
246 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
247 env->mmuregs[4] = address; /* Fault address register */
249 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
250 // No fault mode: if a mapping is available, just override
251 // permissions. If no mapping is available, redirect accesses to
252 // neverland. Fake/overridden mappings will be flushed when
253 // switching to normal mode.
254 vaddr = address & TARGET_PAGE_MASK;
255 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
256 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
257 return 0;
258 } else {
259 if (rw & 2)
260 env->exception_index = TT_TFAULT;
261 else
262 env->exception_index = TT_DFAULT;
263 return 1;
267 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
269 target_phys_addr_t pde_ptr;
270 uint32_t pde;
272 /* Context base + context number */
273 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
274 (env->mmuregs[2] << 2);
275 pde = ldl_phys(pde_ptr);
277 switch (pde & PTE_ENTRYTYPE_MASK) {
278 default:
279 case 0: /* Invalid */
280 case 2: /* PTE, maybe should not happen? */
281 case 3: /* Reserved */
282 return 0;
283 case 1: /* L1 PDE */
284 if (mmulev == 3)
285 return pde;
286 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
287 pde = ldl_phys(pde_ptr);
289 switch (pde & PTE_ENTRYTYPE_MASK) {
290 default:
291 case 0: /* Invalid */
292 case 3: /* Reserved */
293 return 0;
294 case 2: /* L1 PTE */
295 return pde;
296 case 1: /* L2 PDE */
297 if (mmulev == 2)
298 return pde;
299 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
300 pde = ldl_phys(pde_ptr);
302 switch (pde & PTE_ENTRYTYPE_MASK) {
303 default:
304 case 0: /* Invalid */
305 case 3: /* Reserved */
306 return 0;
307 case 2: /* L2 PTE */
308 return pde;
309 case 1: /* L3 PDE */
310 if (mmulev == 1)
311 return pde;
312 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
313 pde = ldl_phys(pde_ptr);
315 switch (pde & PTE_ENTRYTYPE_MASK) {
316 default:
317 case 0: /* Invalid */
318 case 1: /* PDE, should not happen */
319 case 3: /* Reserved */
320 return 0;
321 case 2: /* L3 PTE */
322 return pde;
327 return 0;
330 #ifdef DEBUG_MMU
331 void dump_mmu(CPUState *env)
333 target_ulong va, va1, va2;
334 unsigned int n, m, o;
335 target_phys_addr_t pde_ptr, pa;
336 uint32_t pde;
338 printf("MMU dump:\n");
339 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
340 pde = ldl_phys(pde_ptr);
341 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
342 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
343 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
344 pde = mmu_probe(env, va, 2);
345 if (pde) {
346 pa = cpu_get_phys_page_debug(env, va);
347 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
348 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
349 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
350 pde = mmu_probe(env, va1, 1);
351 if (pde) {
352 pa = cpu_get_phys_page_debug(env, va1);
353 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
354 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
355 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
356 pde = mmu_probe(env, va2, 0);
357 if (pde) {
358 pa = cpu_get_phys_page_debug(env, va2);
359 printf(" VA: " TARGET_FMT_lx ", PA: "
360 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
361 va2, pa, pde);
368 printf("MMU dump ends\n");
370 #endif /* DEBUG_MMU */
372 #else /* !TARGET_SPARC64 */
374 // 41 bit physical address space
375 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
377 return x & 0x1ffffffffffULL;
381 * UltraSparc IIi I/DMMUs
384 // Returns true if TTE tag is valid and matches virtual address value in context
385 // requires virtual address mask value calculated from TTE entry size
386 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
387 uint64_t address, uint64_t context,
388 target_phys_addr_t *physical)
390 uint64_t mask;
392 switch ((tlb->tte >> 61) & 3) {
393 default:
394 case 0x0: // 8k
395 mask = 0xffffffffffffe000ULL;
396 break;
397 case 0x1: // 64k
398 mask = 0xffffffffffff0000ULL;
399 break;
400 case 0x2: // 512k
401 mask = 0xfffffffffff80000ULL;
402 break;
403 case 0x3: // 4M
404 mask = 0xffffffffffc00000ULL;
405 break;
408 // valid, context match, virtual address match?
409 if (TTE_IS_VALID(tlb->tte) &&
410 (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
411 && compare_masked(address, tlb->tag, mask))
413 // decode physical address
414 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
415 return 1;
418 return 0;
421 static int get_physical_address_data(CPUState *env,
422 target_phys_addr_t *physical, int *prot,
423 target_ulong address, int rw, int mmu_idx)
425 unsigned int i;
426 uint64_t context;
428 int is_user = (mmu_idx == MMU_USER_IDX ||
429 mmu_idx == MMU_USER_SECONDARY_IDX);
431 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
432 *physical = ultrasparc_truncate_physical(address);
433 *prot = PAGE_READ | PAGE_WRITE;
434 return 0;
437 switch(mmu_idx) {
438 case MMU_USER_IDX:
439 case MMU_KERNEL_IDX:
440 context = env->dmmu.mmu_primary_context & 0x1fff;
441 break;
442 case MMU_USER_SECONDARY_IDX:
443 case MMU_KERNEL_SECONDARY_IDX:
444 context = env->dmmu.mmu_secondary_context & 0x1fff;
445 break;
446 case MMU_NUCLEUS_IDX:
447 default:
448 context = 0;
449 break;
452 for (i = 0; i < 64; i++) {
453 // ctx match, vaddr match, valid?
454 if (ultrasparc_tag_match(&env->dtlb[i],
455 address, context, physical)) {
456 // access ok?
457 if (((env->dtlb[i].tte & 0x4) && is_user) ||
458 (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
459 uint8_t fault_type = 0;
461 if ((env->dtlb[i].tte & 0x4) && is_user) {
462 fault_type |= 1; /* privilege violation */
465 if (env->dmmu.sfsr & 1) /* Fault status register */
466 env->dmmu.sfsr = 2; /* overflow (not read before
467 another fault) */
469 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
471 env->dmmu.sfsr |= (fault_type << 7);
473 env->dmmu.sfar = address; /* Fault address register */
474 env->exception_index = TT_DFAULT;
475 #ifdef DEBUG_MMU
476 printf("DFAULT at 0x%" PRIx64 "\n", address);
477 #endif
478 return 1;
480 *prot = PAGE_READ;
481 if (env->dtlb[i].tte & 0x2)
482 *prot |= PAGE_WRITE;
483 TTE_SET_USED(env->dtlb[i].tte);
484 return 0;
487 #ifdef DEBUG_MMU
488 printf("DMISS at 0x%" PRIx64 "\n", address);
489 #endif
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;
531 #ifdef DEBUG_MMU
532 printf("TFAULT at 0x%" PRIx64 "\n", address);
533 #endif
534 return 1;
536 *prot = PAGE_EXEC;
537 TTE_SET_USED(env->itlb[i].tte);
538 return 0;
541 #ifdef DEBUG_MMU
542 printf("TMISS at 0x%" PRIx64 "\n", address);
543 #endif
544 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
545 env->immu.tag_access = (address & ~0x1fffULL) | context;
546 env->exception_index = TT_TMISS;
547 return 1;
550 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
551 int *prot, int *access_index,
552 target_ulong address, int rw, int mmu_idx,
553 target_ulong *page_size)
555 /* ??? We treat everything as a small page, then explicitly flush
556 everything when an entry is evicted. */
557 *page_size = TARGET_PAGE_SIZE;
558 if (rw == 2)
559 return get_physical_address_code(env, physical, prot, address,
560 mmu_idx);
561 else
562 return get_physical_address_data(env, physical, prot, address, rw,
563 mmu_idx);
566 /* Perform address translation */
567 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
568 int mmu_idx, int is_softmmu)
570 target_ulong virt_addr, vaddr;
571 target_phys_addr_t paddr;
572 target_ulong page_size;
573 int error_code = 0, prot, access_index;
575 error_code = get_physical_address(env, &paddr, &prot, &access_index,
576 address, rw, mmu_idx, &page_size);
577 if (error_code == 0) {
578 virt_addr = address & TARGET_PAGE_MASK;
579 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
580 (TARGET_PAGE_SIZE - 1));
581 #ifdef DEBUG_MMU
582 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
583 "\n", address, paddr, vaddr);
584 #endif
585 tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
586 return 0;
588 // XXX
589 return 1;
592 #ifdef DEBUG_MMU
593 void dump_mmu(CPUState *env)
595 unsigned int i;
596 const char *mask;
598 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
599 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
600 if ((env->lsu & DMMU_E) == 0) {
601 printf("DMMU disabled\n");
602 } else {
603 printf("DMMU dump:\n");
604 for (i = 0; i < 64; i++) {
605 switch ((env->dtlb[i].tte >> 61) & 3) {
606 default:
607 case 0x0:
608 mask = " 8k";
609 break;
610 case 0x1:
611 mask = " 64k";
612 break;
613 case 0x2:
614 mask = "512k";
615 break;
616 case 0x3:
617 mask = " 4M";
618 break;
620 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
621 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
622 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
624 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
625 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
626 mask,
627 env->dtlb[i].tte & 0x4? "priv": "user",
628 env->dtlb[i].tte & 0x2? "RW": "RO",
629 env->dtlb[i].tte & 0x40? "locked": "unlocked",
630 env->dtlb[i].tag & (uint64_t)0x1fffULL,
631 TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
635 if ((env->lsu & IMMU_E) == 0) {
636 printf("IMMU disabled\n");
637 } else {
638 printf("IMMU dump:\n");
639 for (i = 0; i < 64; i++) {
640 switch ((env->itlb[i].tte >> 61) & 3) {
641 default:
642 case 0x0:
643 mask = " 8k";
644 break;
645 case 0x1:
646 mask = " 64k";
647 break;
648 case 0x2:
649 mask = "512k";
650 break;
651 case 0x3:
652 mask = " 4M";
653 break;
655 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
656 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
657 ", %s, %s, %s, ctx %" PRId64 " %s\n",
659 env->itlb[i].tag & (uint64_t)~0x1fffULL,
660 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
661 mask,
662 env->itlb[i].tte & 0x4? "priv": "user",
663 env->itlb[i].tte & 0x40? "locked": "unlocked",
664 env->itlb[i].tag & (uint64_t)0x1fffULL,
665 TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
670 #endif /* DEBUG_MMU */
672 #endif /* TARGET_SPARC64 */
673 #endif /* !CONFIG_USER_ONLY */
676 #if !defined(CONFIG_USER_ONLY)
677 target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
678 int mmu_idx)
680 target_phys_addr_t phys_addr;
681 target_ulong page_size;
682 int prot, access_index;
684 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
685 mmu_idx, &page_size) != 0)
686 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
687 0, mmu_idx, &page_size) != 0)
688 return -1;
689 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
690 return -1;
691 return phys_addr;
694 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
696 return cpu_get_phys_page_nofault(env, addr, MMU_KERNEL_IDX);
698 #endif
700 void cpu_reset(CPUSPARCState *env)
702 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
703 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
704 log_cpu_state(env, 0);
707 tlb_flush(env, 1);
708 env->cwp = 0;
709 #ifndef TARGET_SPARC64
710 env->wim = 1;
711 #endif
712 env->regwptr = env->regbase + (env->cwp * 16);
713 CC_OP = CC_OP_FLAGS;
714 #if defined(CONFIG_USER_ONLY)
715 #ifdef TARGET_SPARC64
716 env->cleanwin = env->nwindows - 2;
717 env->cansave = env->nwindows - 2;
718 env->pstate = PS_RMO | PS_PEF | PS_IE;
719 env->asi = 0x82; // Primary no-fault
720 #endif
721 #else
722 #if !defined(TARGET_SPARC64)
723 env->psret = 0;
724 #endif
725 env->psrs = 1;
726 env->psrps = 1;
727 #ifdef TARGET_SPARC64
728 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
729 env->hpstate = HS_PRIV;
730 env->tl = env->maxtl;
731 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
732 env->lsu = 0;
733 #else
734 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
735 env->mmuregs[0] |= env->def->mmu_bm;
736 #endif
737 env->pc = 0;
738 env->npc = env->pc + 4;
739 #endif
742 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
744 sparc_def_t def1, *def = &def1;
746 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
747 return -1;
749 env->def = qemu_mallocz(sizeof(*def));
750 memcpy(env->def, def, sizeof(*def));
751 #if defined(CONFIG_USER_ONLY)
752 if ((env->def->features & CPU_FEATURE_FLOAT))
753 env->def->features |= CPU_FEATURE_FLOAT128;
754 #endif
755 env->cpu_model_str = cpu_model;
756 env->version = def->iu_version;
757 env->fsr = def->fpu_version;
758 env->nwindows = def->nwindows;
759 #if !defined(TARGET_SPARC64)
760 env->mmuregs[0] |= def->mmu_version;
761 cpu_sparc_set_id(env, 0);
762 env->mxccregs[7] |= def->mxcc_version;
763 #else
764 env->mmu_version = def->mmu_version;
765 env->maxtl = def->maxtl;
766 env->version |= def->maxtl << 8;
767 env->version |= def->nwindows - 1;
768 #endif
769 return 0;
772 static void cpu_sparc_close(CPUSPARCState *env)
774 free(env->def);
775 free(env);
778 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
780 CPUSPARCState *env;
782 env = qemu_mallocz(sizeof(CPUSPARCState));
783 cpu_exec_init(env);
785 gen_intermediate_code_init(env);
787 if (cpu_sparc_register(env, cpu_model) < 0) {
788 cpu_sparc_close(env);
789 return NULL;
791 qemu_init_vcpu(env);
793 return env;
796 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
798 #if !defined(TARGET_SPARC64)
799 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
800 #endif
803 static const sparc_def_t sparc_defs[] = {
804 #ifdef TARGET_SPARC64
806 .name = "Fujitsu Sparc64",
807 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
808 .fpu_version = 0x00000000,
809 .mmu_version = mmu_us_12,
810 .nwindows = 4,
811 .maxtl = 4,
812 .features = CPU_DEFAULT_FEATURES,
815 .name = "Fujitsu Sparc64 III",
816 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
817 .fpu_version = 0x00000000,
818 .mmu_version = mmu_us_12,
819 .nwindows = 5,
820 .maxtl = 4,
821 .features = CPU_DEFAULT_FEATURES,
824 .name = "Fujitsu Sparc64 IV",
825 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
826 .fpu_version = 0x00000000,
827 .mmu_version = mmu_us_12,
828 .nwindows = 8,
829 .maxtl = 5,
830 .features = CPU_DEFAULT_FEATURES,
833 .name = "Fujitsu Sparc64 V",
834 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
835 .fpu_version = 0x00000000,
836 .mmu_version = mmu_us_12,
837 .nwindows = 8,
838 .maxtl = 5,
839 .features = CPU_DEFAULT_FEATURES,
842 .name = "TI UltraSparc I",
843 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
844 .fpu_version = 0x00000000,
845 .mmu_version = mmu_us_12,
846 .nwindows = 8,
847 .maxtl = 5,
848 .features = CPU_DEFAULT_FEATURES,
851 .name = "TI UltraSparc II",
852 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
853 .fpu_version = 0x00000000,
854 .mmu_version = mmu_us_12,
855 .nwindows = 8,
856 .maxtl = 5,
857 .features = CPU_DEFAULT_FEATURES,
860 .name = "TI UltraSparc IIi",
861 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
862 .fpu_version = 0x00000000,
863 .mmu_version = mmu_us_12,
864 .nwindows = 8,
865 .maxtl = 5,
866 .features = CPU_DEFAULT_FEATURES,
869 .name = "TI UltraSparc IIe",
870 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
871 .fpu_version = 0x00000000,
872 .mmu_version = mmu_us_12,
873 .nwindows = 8,
874 .maxtl = 5,
875 .features = CPU_DEFAULT_FEATURES,
878 .name = "Sun UltraSparc III",
879 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
880 .fpu_version = 0x00000000,
881 .mmu_version = mmu_us_12,
882 .nwindows = 8,
883 .maxtl = 5,
884 .features = CPU_DEFAULT_FEATURES,
887 .name = "Sun UltraSparc III Cu",
888 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
889 .fpu_version = 0x00000000,
890 .mmu_version = mmu_us_3,
891 .nwindows = 8,
892 .maxtl = 5,
893 .features = CPU_DEFAULT_FEATURES,
896 .name = "Sun UltraSparc IIIi",
897 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
898 .fpu_version = 0x00000000,
899 .mmu_version = mmu_us_12,
900 .nwindows = 8,
901 .maxtl = 5,
902 .features = CPU_DEFAULT_FEATURES,
905 .name = "Sun UltraSparc IV",
906 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
907 .fpu_version = 0x00000000,
908 .mmu_version = mmu_us_4,
909 .nwindows = 8,
910 .maxtl = 5,
911 .features = CPU_DEFAULT_FEATURES,
914 .name = "Sun UltraSparc IV+",
915 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
916 .fpu_version = 0x00000000,
917 .mmu_version = mmu_us_12,
918 .nwindows = 8,
919 .maxtl = 5,
920 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
923 .name = "Sun UltraSparc IIIi+",
924 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
925 .fpu_version = 0x00000000,
926 .mmu_version = mmu_us_3,
927 .nwindows = 8,
928 .maxtl = 5,
929 .features = CPU_DEFAULT_FEATURES,
932 .name = "Sun UltraSparc T1",
933 // defined in sparc_ifu_fdp.v and ctu.h
934 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
935 .fpu_version = 0x00000000,
936 .mmu_version = mmu_sun4v,
937 .nwindows = 8,
938 .maxtl = 6,
939 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
940 | CPU_FEATURE_GL,
943 .name = "Sun UltraSparc T2",
944 // defined in tlu_asi_ctl.v and n2_revid_cust.v
945 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
946 .fpu_version = 0x00000000,
947 .mmu_version = mmu_sun4v,
948 .nwindows = 8,
949 .maxtl = 6,
950 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
951 | CPU_FEATURE_GL,
954 .name = "NEC UltraSparc I",
955 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
956 .fpu_version = 0x00000000,
957 .mmu_version = mmu_us_12,
958 .nwindows = 8,
959 .maxtl = 5,
960 .features = CPU_DEFAULT_FEATURES,
962 #else
964 .name = "Fujitsu MB86900",
965 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
966 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
967 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
968 .mmu_bm = 0x00004000,
969 .mmu_ctpr_mask = 0x007ffff0,
970 .mmu_cxr_mask = 0x0000003f,
971 .mmu_sfsr_mask = 0xffffffff,
972 .mmu_trcr_mask = 0xffffffff,
973 .nwindows = 7,
974 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
977 .name = "Fujitsu MB86904",
978 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
979 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
980 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
981 .mmu_bm = 0x00004000,
982 .mmu_ctpr_mask = 0x00ffffc0,
983 .mmu_cxr_mask = 0x000000ff,
984 .mmu_sfsr_mask = 0x00016fff,
985 .mmu_trcr_mask = 0x00ffffff,
986 .nwindows = 8,
987 .features = CPU_DEFAULT_FEATURES,
990 .name = "Fujitsu MB86907",
991 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
992 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
993 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
994 .mmu_bm = 0x00004000,
995 .mmu_ctpr_mask = 0xffffffc0,
996 .mmu_cxr_mask = 0x000000ff,
997 .mmu_sfsr_mask = 0x00016fff,
998 .mmu_trcr_mask = 0xffffffff,
999 .nwindows = 8,
1000 .features = CPU_DEFAULT_FEATURES,
1003 .name = "LSI L64811",
1004 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1005 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1006 .mmu_version = 0x10 << 24,
1007 .mmu_bm = 0x00004000,
1008 .mmu_ctpr_mask = 0x007ffff0,
1009 .mmu_cxr_mask = 0x0000003f,
1010 .mmu_sfsr_mask = 0xffffffff,
1011 .mmu_trcr_mask = 0xffffffff,
1012 .nwindows = 8,
1013 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1014 CPU_FEATURE_FSMULD,
1017 .name = "Cypress CY7C601",
1018 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1019 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1020 .mmu_version = 0x10 << 24,
1021 .mmu_bm = 0x00004000,
1022 .mmu_ctpr_mask = 0x007ffff0,
1023 .mmu_cxr_mask = 0x0000003f,
1024 .mmu_sfsr_mask = 0xffffffff,
1025 .mmu_trcr_mask = 0xffffffff,
1026 .nwindows = 8,
1027 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1028 CPU_FEATURE_FSMULD,
1031 .name = "Cypress CY7C611",
1032 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1033 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1034 .mmu_version = 0x10 << 24,
1035 .mmu_bm = 0x00004000,
1036 .mmu_ctpr_mask = 0x007ffff0,
1037 .mmu_cxr_mask = 0x0000003f,
1038 .mmu_sfsr_mask = 0xffffffff,
1039 .mmu_trcr_mask = 0xffffffff,
1040 .nwindows = 8,
1041 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1042 CPU_FEATURE_FSMULD,
1045 .name = "TI MicroSparc I",
1046 .iu_version = 0x41000000,
1047 .fpu_version = 4 << 17,
1048 .mmu_version = 0x41000000,
1049 .mmu_bm = 0x00004000,
1050 .mmu_ctpr_mask = 0x007ffff0,
1051 .mmu_cxr_mask = 0x0000003f,
1052 .mmu_sfsr_mask = 0x00016fff,
1053 .mmu_trcr_mask = 0x0000003f,
1054 .nwindows = 7,
1055 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1056 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1057 CPU_FEATURE_FMUL,
1060 .name = "TI MicroSparc II",
1061 .iu_version = 0x42000000,
1062 .fpu_version = 4 << 17,
1063 .mmu_version = 0x02000000,
1064 .mmu_bm = 0x00004000,
1065 .mmu_ctpr_mask = 0x00ffffc0,
1066 .mmu_cxr_mask = 0x000000ff,
1067 .mmu_sfsr_mask = 0x00016fff,
1068 .mmu_trcr_mask = 0x00ffffff,
1069 .nwindows = 8,
1070 .features = CPU_DEFAULT_FEATURES,
1073 .name = "TI MicroSparc IIep",
1074 .iu_version = 0x42000000,
1075 .fpu_version = 4 << 17,
1076 .mmu_version = 0x04000000,
1077 .mmu_bm = 0x00004000,
1078 .mmu_ctpr_mask = 0x00ffffc0,
1079 .mmu_cxr_mask = 0x000000ff,
1080 .mmu_sfsr_mask = 0x00016bff,
1081 .mmu_trcr_mask = 0x00ffffff,
1082 .nwindows = 8,
1083 .features = CPU_DEFAULT_FEATURES,
1086 .name = "TI SuperSparc 40", // STP1020NPGA
1087 .iu_version = 0x41000000, // SuperSPARC 2.x
1088 .fpu_version = 0 << 17,
1089 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1090 .mmu_bm = 0x00002000,
1091 .mmu_ctpr_mask = 0xffffffc0,
1092 .mmu_cxr_mask = 0x0000ffff,
1093 .mmu_sfsr_mask = 0xffffffff,
1094 .mmu_trcr_mask = 0xffffffff,
1095 .nwindows = 8,
1096 .features = CPU_DEFAULT_FEATURES,
1099 .name = "TI SuperSparc 50", // STP1020PGA
1100 .iu_version = 0x40000000, // SuperSPARC 3.x
1101 .fpu_version = 0 << 17,
1102 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1103 .mmu_bm = 0x00002000,
1104 .mmu_ctpr_mask = 0xffffffc0,
1105 .mmu_cxr_mask = 0x0000ffff,
1106 .mmu_sfsr_mask = 0xffffffff,
1107 .mmu_trcr_mask = 0xffffffff,
1108 .nwindows = 8,
1109 .features = CPU_DEFAULT_FEATURES,
1112 .name = "TI SuperSparc 51",
1113 .iu_version = 0x40000000, // SuperSPARC 3.x
1114 .fpu_version = 0 << 17,
1115 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1116 .mmu_bm = 0x00002000,
1117 .mmu_ctpr_mask = 0xffffffc0,
1118 .mmu_cxr_mask = 0x0000ffff,
1119 .mmu_sfsr_mask = 0xffffffff,
1120 .mmu_trcr_mask = 0xffffffff,
1121 .mxcc_version = 0x00000104,
1122 .nwindows = 8,
1123 .features = CPU_DEFAULT_FEATURES,
1126 .name = "TI SuperSparc 60", // STP1020APGA
1127 .iu_version = 0x40000000, // SuperSPARC 3.x
1128 .fpu_version = 0 << 17,
1129 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1130 .mmu_bm = 0x00002000,
1131 .mmu_ctpr_mask = 0xffffffc0,
1132 .mmu_cxr_mask = 0x0000ffff,
1133 .mmu_sfsr_mask = 0xffffffff,
1134 .mmu_trcr_mask = 0xffffffff,
1135 .nwindows = 8,
1136 .features = CPU_DEFAULT_FEATURES,
1139 .name = "TI SuperSparc 61",
1140 .iu_version = 0x44000000, // SuperSPARC 3.x
1141 .fpu_version = 0 << 17,
1142 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1143 .mmu_bm = 0x00002000,
1144 .mmu_ctpr_mask = 0xffffffc0,
1145 .mmu_cxr_mask = 0x0000ffff,
1146 .mmu_sfsr_mask = 0xffffffff,
1147 .mmu_trcr_mask = 0xffffffff,
1148 .mxcc_version = 0x00000104,
1149 .nwindows = 8,
1150 .features = CPU_DEFAULT_FEATURES,
1153 .name = "TI SuperSparc II",
1154 .iu_version = 0x40000000, // SuperSPARC II 1.x
1155 .fpu_version = 0 << 17,
1156 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1157 .mmu_bm = 0x00002000,
1158 .mmu_ctpr_mask = 0xffffffc0,
1159 .mmu_cxr_mask = 0x0000ffff,
1160 .mmu_sfsr_mask = 0xffffffff,
1161 .mmu_trcr_mask = 0xffffffff,
1162 .mxcc_version = 0x00000104,
1163 .nwindows = 8,
1164 .features = CPU_DEFAULT_FEATURES,
1167 .name = "Ross RT625",
1168 .iu_version = 0x1e000000,
1169 .fpu_version = 1 << 17,
1170 .mmu_version = 0x1e000000,
1171 .mmu_bm = 0x00004000,
1172 .mmu_ctpr_mask = 0x007ffff0,
1173 .mmu_cxr_mask = 0x0000003f,
1174 .mmu_sfsr_mask = 0xffffffff,
1175 .mmu_trcr_mask = 0xffffffff,
1176 .nwindows = 8,
1177 .features = CPU_DEFAULT_FEATURES,
1180 .name = "Ross RT620",
1181 .iu_version = 0x1f000000,
1182 .fpu_version = 1 << 17,
1183 .mmu_version = 0x1f000000,
1184 .mmu_bm = 0x00004000,
1185 .mmu_ctpr_mask = 0x007ffff0,
1186 .mmu_cxr_mask = 0x0000003f,
1187 .mmu_sfsr_mask = 0xffffffff,
1188 .mmu_trcr_mask = 0xffffffff,
1189 .nwindows = 8,
1190 .features = CPU_DEFAULT_FEATURES,
1193 .name = "BIT B5010",
1194 .iu_version = 0x20000000,
1195 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1196 .mmu_version = 0x20000000,
1197 .mmu_bm = 0x00004000,
1198 .mmu_ctpr_mask = 0x007ffff0,
1199 .mmu_cxr_mask = 0x0000003f,
1200 .mmu_sfsr_mask = 0xffffffff,
1201 .mmu_trcr_mask = 0xffffffff,
1202 .nwindows = 8,
1203 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1204 CPU_FEATURE_FSMULD,
1207 .name = "Matsushita MN10501",
1208 .iu_version = 0x50000000,
1209 .fpu_version = 0 << 17,
1210 .mmu_version = 0x50000000,
1211 .mmu_bm = 0x00004000,
1212 .mmu_ctpr_mask = 0x007ffff0,
1213 .mmu_cxr_mask = 0x0000003f,
1214 .mmu_sfsr_mask = 0xffffffff,
1215 .mmu_trcr_mask = 0xffffffff,
1216 .nwindows = 8,
1217 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1218 CPU_FEATURE_FSMULD,
1221 .name = "Weitek W8601",
1222 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1223 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1224 .mmu_version = 0x10 << 24,
1225 .mmu_bm = 0x00004000,
1226 .mmu_ctpr_mask = 0x007ffff0,
1227 .mmu_cxr_mask = 0x0000003f,
1228 .mmu_sfsr_mask = 0xffffffff,
1229 .mmu_trcr_mask = 0xffffffff,
1230 .nwindows = 8,
1231 .features = CPU_DEFAULT_FEATURES,
1234 .name = "LEON2",
1235 .iu_version = 0xf2000000,
1236 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1237 .mmu_version = 0xf2000000,
1238 .mmu_bm = 0x00004000,
1239 .mmu_ctpr_mask = 0x007ffff0,
1240 .mmu_cxr_mask = 0x0000003f,
1241 .mmu_sfsr_mask = 0xffffffff,
1242 .mmu_trcr_mask = 0xffffffff,
1243 .nwindows = 8,
1244 .features = CPU_DEFAULT_FEATURES,
1247 .name = "LEON3",
1248 .iu_version = 0xf3000000,
1249 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1250 .mmu_version = 0xf3000000,
1251 .mmu_bm = 0x00004000,
1252 .mmu_ctpr_mask = 0x007ffff0,
1253 .mmu_cxr_mask = 0x0000003f,
1254 .mmu_sfsr_mask = 0xffffffff,
1255 .mmu_trcr_mask = 0xffffffff,
1256 .nwindows = 8,
1257 .features = CPU_DEFAULT_FEATURES,
1259 #endif
1262 static const char * const feature_name[] = {
1263 "float",
1264 "float128",
1265 "swap",
1266 "mul",
1267 "div",
1268 "flush",
1269 "fsqrt",
1270 "fmul",
1271 "vis1",
1272 "vis2",
1273 "fsmuld",
1274 "hypv",
1275 "cmt",
1276 "gl",
1279 static void print_features(FILE *f,
1280 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1281 uint32_t features, const char *prefix)
1283 unsigned int i;
1285 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1286 if (feature_name[i] && (features & (1 << i))) {
1287 if (prefix)
1288 (*cpu_fprintf)(f, "%s", prefix);
1289 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1293 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1295 unsigned int i;
1297 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1298 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1299 *features |= 1 << i;
1300 return;
1302 fprintf(stderr, "CPU feature %s not found\n", flagname);
1305 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1307 unsigned int i;
1308 const sparc_def_t *def = NULL;
1309 char *s = strdup(cpu_model);
1310 char *featurestr, *name = strtok(s, ",");
1311 uint32_t plus_features = 0;
1312 uint32_t minus_features = 0;
1313 long long iu_version;
1314 uint32_t fpu_version, mmu_version, nwindows;
1316 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1317 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1318 def = &sparc_defs[i];
1321 if (!def)
1322 goto error;
1323 memcpy(cpu_def, def, sizeof(*def));
1325 featurestr = strtok(NULL, ",");
1326 while (featurestr) {
1327 char *val;
1329 if (featurestr[0] == '+') {
1330 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1331 } else if (featurestr[0] == '-') {
1332 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1333 } else if ((val = strchr(featurestr, '='))) {
1334 *val = 0; val++;
1335 if (!strcmp(featurestr, "iu_version")) {
1336 char *err;
1338 iu_version = strtoll(val, &err, 0);
1339 if (!*val || *err) {
1340 fprintf(stderr, "bad numerical value %s\n", val);
1341 goto error;
1343 cpu_def->iu_version = iu_version;
1344 #ifdef DEBUG_FEATURES
1345 fprintf(stderr, "iu_version %llx\n", iu_version);
1346 #endif
1347 } else if (!strcmp(featurestr, "fpu_version")) {
1348 char *err;
1350 fpu_version = strtol(val, &err, 0);
1351 if (!*val || *err) {
1352 fprintf(stderr, "bad numerical value %s\n", val);
1353 goto error;
1355 cpu_def->fpu_version = fpu_version;
1356 #ifdef DEBUG_FEATURES
1357 fprintf(stderr, "fpu_version %x\n", fpu_version);
1358 #endif
1359 } else if (!strcmp(featurestr, "mmu_version")) {
1360 char *err;
1362 mmu_version = strtol(val, &err, 0);
1363 if (!*val || *err) {
1364 fprintf(stderr, "bad numerical value %s\n", val);
1365 goto error;
1367 cpu_def->mmu_version = mmu_version;
1368 #ifdef DEBUG_FEATURES
1369 fprintf(stderr, "mmu_version %x\n", mmu_version);
1370 #endif
1371 } else if (!strcmp(featurestr, "nwindows")) {
1372 char *err;
1374 nwindows = strtol(val, &err, 0);
1375 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1376 nwindows < MIN_NWINDOWS) {
1377 fprintf(stderr, "bad numerical value %s\n", val);
1378 goto error;
1380 cpu_def->nwindows = nwindows;
1381 #ifdef DEBUG_FEATURES
1382 fprintf(stderr, "nwindows %d\n", nwindows);
1383 #endif
1384 } else {
1385 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1386 goto error;
1388 } else {
1389 fprintf(stderr, "feature string `%s' not in format "
1390 "(+feature|-feature|feature=xyz)\n", featurestr);
1391 goto error;
1393 featurestr = strtok(NULL, ",");
1395 cpu_def->features |= plus_features;
1396 cpu_def->features &= ~minus_features;
1397 #ifdef DEBUG_FEATURES
1398 print_features(stderr, fprintf, cpu_def->features, NULL);
1399 #endif
1400 free(s);
1401 return 0;
1403 error:
1404 free(s);
1405 return -1;
1408 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1410 unsigned int i;
1412 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1413 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1414 sparc_defs[i].name,
1415 sparc_defs[i].iu_version,
1416 sparc_defs[i].fpu_version,
1417 sparc_defs[i].mmu_version,
1418 sparc_defs[i].nwindows);
1419 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1420 ~sparc_defs[i].features, "-");
1421 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1422 sparc_defs[i].features, "+");
1423 (*cpu_fprintf)(f, "\n");
1425 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1426 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1427 (*cpu_fprintf)(f, "\n");
1428 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1429 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1430 (*cpu_fprintf)(f, "\n");
1431 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1432 "fpu_version mmu_version nwindows\n");
1435 static void cpu_print_cc(FILE *f,
1436 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1437 uint32_t cc)
1439 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1440 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1441 cc & PSR_CARRY? 'C' : '-');
1444 #ifdef TARGET_SPARC64
1445 #define REGS_PER_LINE 4
1446 #else
1447 #define REGS_PER_LINE 8
1448 #endif
1450 void cpu_dump_state(CPUState *env, FILE *f,
1451 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1452 int flags)
1454 int i, x;
1456 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1457 env->npc);
1458 cpu_fprintf(f, "General Registers:\n");
1460 for (i = 0; i < 8; i++) {
1461 if (i % REGS_PER_LINE == 0) {
1462 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1464 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1465 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1466 cpu_fprintf(f, "\n");
1469 cpu_fprintf(f, "\nCurrent Register Window:\n");
1470 for (x = 0; x < 3; x++) {
1471 for (i = 0; i < 8; i++) {
1472 if (i % REGS_PER_LINE == 0) {
1473 cpu_fprintf(f, "%%%c%d-%d: ",
1474 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1475 i, i + REGS_PER_LINE - 1);
1477 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1478 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1479 cpu_fprintf(f, "\n");
1483 cpu_fprintf(f, "\nFloating Point Registers:\n");
1484 for (i = 0; i < TARGET_FPREGS; i++) {
1485 if ((i & 3) == 0)
1486 cpu_fprintf(f, "%%f%02d:", i);
1487 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1488 if ((i & 3) == 3)
1489 cpu_fprintf(f, "\n");
1491 #ifdef TARGET_SPARC64
1492 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1493 (unsigned)cpu_get_ccr(env));
1494 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
1495 cpu_fprintf(f, " xcc: ");
1496 cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
1497 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1498 env->psrpil);
1499 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1500 "cleanwin: %d cwp: %d\n",
1501 env->cansave, env->canrestore, env->otherwin, env->wstate,
1502 env->cleanwin, env->nwindows - 1 - env->cwp);
1503 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1504 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1505 #else
1506 cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
1507 cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
1508 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1509 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1510 env->wim);
1511 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1512 env->fsr, env->y);
1513 #endif