Merge remote branch 'mst/for_anthony' into staging
[qemu/aliguori-queue.git] / target-sparc / helper.c
bloba06923a8c1a30e8fde28b541a67975e66f469292
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)
107 int access_perms = 0;
108 target_phys_addr_t pde_ptr;
109 uint32_t pde;
110 target_ulong virt_addr;
111 int error_code = 0, is_dirty, is_user;
112 unsigned long page_offset;
114 is_user = mmu_idx == MMU_USER_IDX;
115 virt_addr = address & TARGET_PAGE_MASK;
117 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
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 virt_addr = address & TARGET_PAGE_MASK;
178 page_offset = (address & TARGET_PAGE_MASK) &
179 (TARGET_PAGE_SIZE - 1);
181 break;
182 case 2: /* L2 PTE */
183 virt_addr = address & ~0x3ffff;
184 page_offset = address & 0x3ffff;
186 break;
187 case 2: /* L1 PTE */
188 virt_addr = address & ~0xffffff;
189 page_offset = address & 0xffffff;
193 /* update page modified and dirty bits */
194 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
195 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
196 pde |= PG_ACCESSED_MASK;
197 if (is_dirty)
198 pde |= PG_MODIFIED_MASK;
199 stl_phys_notdirty(pde_ptr, pde);
201 /* check access */
202 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
203 error_code = access_table[*access_index][access_perms];
204 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
205 return error_code;
207 /* the page can be put in the TLB */
208 *prot = perm_table[is_user][access_perms];
209 if (!(pde & PG_MODIFIED_MASK)) {
210 /* only set write access if already dirty... otherwise wait
211 for dirty access */
212 *prot &= ~PAGE_WRITE;
215 /* Even if large ptes, we map only one 4KB page in the cache to
216 avoid filling it too fast */
217 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
218 return error_code;
221 /* Perform address translation */
222 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
223 int mmu_idx, int is_softmmu)
225 target_phys_addr_t paddr;
226 target_ulong vaddr;
227 int error_code = 0, prot, ret = 0, access_index;
229 error_code = get_physical_address(env, &paddr, &prot, &access_index,
230 address, rw, mmu_idx);
231 if (error_code == 0) {
232 vaddr = address & TARGET_PAGE_MASK;
233 paddr &= TARGET_PAGE_MASK;
234 #ifdef DEBUG_MMU
235 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
236 TARGET_FMT_lx "\n", address, paddr, vaddr);
237 #endif
238 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
239 return ret;
242 if (env->mmuregs[3]) /* Fault status register */
243 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
244 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
245 env->mmuregs[4] = address; /* Fault address register */
247 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
248 // No fault mode: if a mapping is available, just override
249 // permissions. If no mapping is available, redirect accesses to
250 // neverland. Fake/overridden mappings will be flushed when
251 // switching to normal mode.
252 vaddr = address & TARGET_PAGE_MASK;
253 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
254 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
255 return ret;
256 } else {
257 if (rw & 2)
258 env->exception_index = TT_TFAULT;
259 else
260 env->exception_index = TT_DFAULT;
261 return 1;
265 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
267 target_phys_addr_t pde_ptr;
268 uint32_t pde;
270 /* Context base + context number */
271 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
272 (env->mmuregs[2] << 2);
273 pde = ldl_phys(pde_ptr);
275 switch (pde & PTE_ENTRYTYPE_MASK) {
276 default:
277 case 0: /* Invalid */
278 case 2: /* PTE, maybe should not happen? */
279 case 3: /* Reserved */
280 return 0;
281 case 1: /* L1 PDE */
282 if (mmulev == 3)
283 return pde;
284 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
285 pde = ldl_phys(pde_ptr);
287 switch (pde & PTE_ENTRYTYPE_MASK) {
288 default:
289 case 0: /* Invalid */
290 case 3: /* Reserved */
291 return 0;
292 case 2: /* L1 PTE */
293 return pde;
294 case 1: /* L2 PDE */
295 if (mmulev == 2)
296 return pde;
297 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
298 pde = ldl_phys(pde_ptr);
300 switch (pde & PTE_ENTRYTYPE_MASK) {
301 default:
302 case 0: /* Invalid */
303 case 3: /* Reserved */
304 return 0;
305 case 2: /* L2 PTE */
306 return pde;
307 case 1: /* L3 PDE */
308 if (mmulev == 1)
309 return pde;
310 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
311 pde = ldl_phys(pde_ptr);
313 switch (pde & PTE_ENTRYTYPE_MASK) {
314 default:
315 case 0: /* Invalid */
316 case 1: /* PDE, should not happen */
317 case 3: /* Reserved */
318 return 0;
319 case 2: /* L3 PTE */
320 return pde;
325 return 0;
328 #ifdef DEBUG_MMU
329 void dump_mmu(CPUState *env)
331 target_ulong va, va1, va2;
332 unsigned int n, m, o;
333 target_phys_addr_t pde_ptr, pa;
334 uint32_t pde;
336 printf("MMU dump:\n");
337 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
338 pde = ldl_phys(pde_ptr);
339 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
340 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
341 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
342 pde = mmu_probe(env, va, 2);
343 if (pde) {
344 pa = cpu_get_phys_page_debug(env, va);
345 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
346 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
347 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
348 pde = mmu_probe(env, va1, 1);
349 if (pde) {
350 pa = cpu_get_phys_page_debug(env, va1);
351 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
352 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
353 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
354 pde = mmu_probe(env, va2, 0);
355 if (pde) {
356 pa = cpu_get_phys_page_debug(env, va2);
357 printf(" VA: " TARGET_FMT_lx ", PA: "
358 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
359 va2, pa, pde);
366 printf("MMU dump ends\n");
368 #endif /* DEBUG_MMU */
370 #else /* !TARGET_SPARC64 */
372 // 41 bit physical address space
373 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
375 return x & 0x1ffffffffffULL;
379 * UltraSparc IIi I/DMMUs
382 static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
384 return (x & mask) == (y & mask);
387 // Returns true if TTE tag is valid and matches virtual address value in context
388 // requires virtual address mask value calculated from TTE entry size
389 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
390 uint64_t address, uint64_t context,
391 target_phys_addr_t *physical,
392 int is_nucleus)
394 uint64_t mask;
396 switch ((tlb->tte >> 61) & 3) {
397 default:
398 case 0x0: // 8k
399 mask = 0xffffffffffffe000ULL;
400 break;
401 case 0x1: // 64k
402 mask = 0xffffffffffff0000ULL;
403 break;
404 case 0x2: // 512k
405 mask = 0xfffffffffff80000ULL;
406 break;
407 case 0x3: // 4M
408 mask = 0xffffffffffc00000ULL;
409 break;
412 // valid, context match, virtual address match?
413 if (TTE_IS_VALID(tlb->tte) &&
414 ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
415 || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag, 0x1fff))
416 && compare_masked(address, tlb->tag, mask))
418 // decode physical address
419 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
420 return 1;
423 return 0;
426 static int get_physical_address_data(CPUState *env,
427 target_phys_addr_t *physical, int *prot,
428 target_ulong address, int rw, int is_user)
430 unsigned int i;
431 uint64_t context;
432 int is_nucleus;
434 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
435 *physical = ultrasparc_truncate_physical(address);
436 *prot = PAGE_READ | PAGE_WRITE;
437 return 0;
440 context = env->dmmu.mmu_primary_context & 0x1fff;
441 is_nucleus = env->tl > 0;
443 for (i = 0; i < 64; i++) {
444 // ctx match, vaddr match, valid?
445 if (ultrasparc_tag_match(&env->dtlb[i],
446 address, context, physical,
447 is_nucleus)) {
448 // access ok?
449 if (((env->dtlb[i].tte & 0x4) && is_user) ||
450 (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
451 uint8_t fault_type = 0;
453 if ((env->dtlb[i].tte & 0x4) && is_user) {
454 fault_type |= 1; /* privilege violation */
457 if (env->dmmu.sfsr & 1) /* Fault status register */
458 env->dmmu.sfsr = 2; /* overflow (not read before
459 another fault) */
461 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
463 env->dmmu.sfsr |= (fault_type << 7);
465 env->dmmu.sfar = address; /* Fault address register */
466 env->exception_index = TT_DFAULT;
467 #ifdef DEBUG_MMU
468 printf("DFAULT at 0x%" PRIx64 "\n", address);
469 #endif
470 return 1;
472 *prot = PAGE_READ;
473 if (env->dtlb[i].tte & 0x2)
474 *prot |= PAGE_WRITE;
475 TTE_SET_USED(env->dtlb[i].tte);
476 return 0;
479 #ifdef DEBUG_MMU
480 printf("DMISS at 0x%" PRIx64 "\n", address);
481 #endif
482 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
483 env->exception_index = TT_DMISS;
484 return 1;
487 static int get_physical_address_code(CPUState *env,
488 target_phys_addr_t *physical, int *prot,
489 target_ulong address, int is_user)
491 unsigned int i;
492 uint64_t context;
493 int is_nucleus;
495 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
496 /* IMMU disabled */
497 *physical = ultrasparc_truncate_physical(address);
498 *prot = PAGE_EXEC;
499 return 0;
502 context = env->dmmu.mmu_primary_context & 0x1fff;
503 is_nucleus = env->tl > 0;
505 for (i = 0; i < 64; i++) {
506 // ctx match, vaddr match, valid?
507 if (ultrasparc_tag_match(&env->itlb[i],
508 address, context, physical,
509 is_nucleus)) {
510 // access ok?
511 if ((env->itlb[i].tte & 0x4) && is_user) {
512 if (env->immu.sfsr) /* Fault status register */
513 env->immu.sfsr = 2; /* overflow (not read before
514 another fault) */
515 env->immu.sfsr |= (is_user << 3) | 1;
516 env->exception_index = TT_TFAULT;
517 #ifdef DEBUG_MMU
518 printf("TFAULT at 0x%" PRIx64 "\n", address);
519 #endif
520 return 1;
522 *prot = PAGE_EXEC;
523 TTE_SET_USED(env->itlb[i].tte);
524 return 0;
527 #ifdef DEBUG_MMU
528 printf("TMISS at 0x%" PRIx64 "\n", address);
529 #endif
530 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
531 env->immu.tag_access = (address & ~0x1fffULL) | context;
532 env->exception_index = TT_TMISS;
533 return 1;
536 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
537 int *prot, int *access_index,
538 target_ulong address, int rw, int mmu_idx)
540 int is_user = mmu_idx == MMU_USER_IDX;
542 if (rw == 2)
543 return get_physical_address_code(env, physical, prot, address,
544 is_user);
545 else
546 return get_physical_address_data(env, physical, prot, address, rw,
547 is_user);
550 /* Perform address translation */
551 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
552 int mmu_idx, int is_softmmu)
554 target_ulong virt_addr, vaddr;
555 target_phys_addr_t paddr;
556 int error_code = 0, prot, ret = 0, access_index;
558 error_code = get_physical_address(env, &paddr, &prot, &access_index,
559 address, rw, mmu_idx);
560 if (error_code == 0) {
561 virt_addr = address & TARGET_PAGE_MASK;
562 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
563 (TARGET_PAGE_SIZE - 1));
564 #ifdef DEBUG_MMU
565 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
566 "\n", address, paddr, vaddr);
567 #endif
568 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
569 return ret;
571 // XXX
572 return 1;
575 #ifdef DEBUG_MMU
576 void dump_mmu(CPUState *env)
578 unsigned int i;
579 const char *mask;
581 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
582 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
583 if ((env->lsu & DMMU_E) == 0) {
584 printf("DMMU disabled\n");
585 } else {
586 printf("DMMU dump:\n");
587 for (i = 0; i < 64; i++) {
588 switch ((env->dtlb[i].tte >> 61) & 3) {
589 default:
590 case 0x0:
591 mask = " 8k";
592 break;
593 case 0x1:
594 mask = " 64k";
595 break;
596 case 0x2:
597 mask = "512k";
598 break;
599 case 0x3:
600 mask = " 4M";
601 break;
603 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
604 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
605 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
607 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
608 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
609 mask,
610 env->dtlb[i].tte & 0x4? "priv": "user",
611 env->dtlb[i].tte & 0x2? "RW": "RO",
612 env->dtlb[i].tte & 0x40? "locked": "unlocked",
613 env->dtlb[i].tag & (uint64_t)0x1fffULL,
614 TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
618 if ((env->lsu & IMMU_E) == 0) {
619 printf("IMMU disabled\n");
620 } else {
621 printf("IMMU dump:\n");
622 for (i = 0; i < 64; i++) {
623 switch ((env->itlb[i].tte >> 61) & 3) {
624 default:
625 case 0x0:
626 mask = " 8k";
627 break;
628 case 0x1:
629 mask = " 64k";
630 break;
631 case 0x2:
632 mask = "512k";
633 break;
634 case 0x3:
635 mask = " 4M";
636 break;
638 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
639 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
640 ", %s, %s, %s, ctx %" PRId64 " %s\n",
642 env->itlb[i].tag & (uint64_t)~0x1fffULL,
643 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
644 mask,
645 env->itlb[i].tte & 0x4? "priv": "user",
646 env->itlb[i].tte & 0x40? "locked": "unlocked",
647 env->itlb[i].tag & (uint64_t)0x1fffULL,
648 TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
653 #endif /* DEBUG_MMU */
655 #endif /* TARGET_SPARC64 */
656 #endif /* !CONFIG_USER_ONLY */
659 #if defined(CONFIG_USER_ONLY)
660 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
662 return addr;
665 #else
666 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
668 target_phys_addr_t phys_addr;
669 int prot, access_index;
671 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
672 MMU_KERNEL_IDX) != 0)
673 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
674 0, MMU_KERNEL_IDX) != 0)
675 return -1;
676 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
677 return -1;
678 return phys_addr;
680 #endif
682 void cpu_reset(CPUSPARCState *env)
684 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
685 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
686 log_cpu_state(env, 0);
689 tlb_flush(env, 1);
690 env->cwp = 0;
691 #ifndef TARGET_SPARC64
692 env->wim = 1;
693 #endif
694 env->regwptr = env->regbase + (env->cwp * 16);
695 CC_OP = CC_OP_FLAGS;
696 #if defined(CONFIG_USER_ONLY)
697 #ifdef TARGET_SPARC64
698 env->cleanwin = env->nwindows - 2;
699 env->cansave = env->nwindows - 2;
700 env->pstate = PS_RMO | PS_PEF | PS_IE;
701 env->asi = 0x82; // Primary no-fault
702 #endif
703 #else
704 #if !defined(TARGET_SPARC64)
705 env->psret = 0;
706 #endif
707 env->psrs = 1;
708 env->psrps = 1;
709 #ifdef TARGET_SPARC64
710 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
711 env->hpstate = HS_PRIV;
712 env->tl = env->maxtl;
713 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
714 env->lsu = 0;
715 #else
716 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
717 env->mmuregs[0] |= env->def->mmu_bm;
718 #endif
719 env->pc = 0;
720 env->npc = env->pc + 4;
721 #endif
724 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
726 sparc_def_t def1, *def = &def1;
728 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
729 return -1;
731 env->def = qemu_mallocz(sizeof(*def));
732 memcpy(env->def, def, sizeof(*def));
733 #if defined(CONFIG_USER_ONLY)
734 if ((env->def->features & CPU_FEATURE_FLOAT))
735 env->def->features |= CPU_FEATURE_FLOAT128;
736 #endif
737 env->cpu_model_str = cpu_model;
738 env->version = def->iu_version;
739 env->fsr = def->fpu_version;
740 env->nwindows = def->nwindows;
741 #if !defined(TARGET_SPARC64)
742 env->mmuregs[0] |= def->mmu_version;
743 cpu_sparc_set_id(env, 0);
744 env->mxccregs[7] |= def->mxcc_version;
745 #else
746 env->mmu_version = def->mmu_version;
747 env->maxtl = def->maxtl;
748 env->version |= def->maxtl << 8;
749 env->version |= def->nwindows - 1;
750 #endif
751 return 0;
754 static void cpu_sparc_close(CPUSPARCState *env)
756 free(env->def);
757 free(env);
760 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
762 CPUSPARCState *env;
764 env = qemu_mallocz(sizeof(CPUSPARCState));
765 cpu_exec_init(env);
767 gen_intermediate_code_init(env);
769 if (cpu_sparc_register(env, cpu_model) < 0) {
770 cpu_sparc_close(env);
771 return NULL;
773 qemu_init_vcpu(env);
775 return env;
778 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
780 #if !defined(TARGET_SPARC64)
781 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
782 #endif
785 static const sparc_def_t sparc_defs[] = {
786 #ifdef TARGET_SPARC64
788 .name = "Fujitsu Sparc64",
789 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
790 .fpu_version = 0x00000000,
791 .mmu_version = mmu_us_12,
792 .nwindows = 4,
793 .maxtl = 4,
794 .features = CPU_DEFAULT_FEATURES,
797 .name = "Fujitsu Sparc64 III",
798 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
799 .fpu_version = 0x00000000,
800 .mmu_version = mmu_us_12,
801 .nwindows = 5,
802 .maxtl = 4,
803 .features = CPU_DEFAULT_FEATURES,
806 .name = "Fujitsu Sparc64 IV",
807 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
808 .fpu_version = 0x00000000,
809 .mmu_version = mmu_us_12,
810 .nwindows = 8,
811 .maxtl = 5,
812 .features = CPU_DEFAULT_FEATURES,
815 .name = "Fujitsu Sparc64 V",
816 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
817 .fpu_version = 0x00000000,
818 .mmu_version = mmu_us_12,
819 .nwindows = 8,
820 .maxtl = 5,
821 .features = CPU_DEFAULT_FEATURES,
824 .name = "TI UltraSparc I",
825 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
826 .fpu_version = 0x00000000,
827 .mmu_version = mmu_us_12,
828 .nwindows = 8,
829 .maxtl = 5,
830 .features = CPU_DEFAULT_FEATURES,
833 .name = "TI UltraSparc II",
834 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 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 IIi",
843 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 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 IIe",
852 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
853 .fpu_version = 0x00000000,
854 .mmu_version = mmu_us_12,
855 .nwindows = 8,
856 .maxtl = 5,
857 .features = CPU_DEFAULT_FEATURES,
860 .name = "Sun UltraSparc III",
861 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
862 .fpu_version = 0x00000000,
863 .mmu_version = mmu_us_12,
864 .nwindows = 8,
865 .maxtl = 5,
866 .features = CPU_DEFAULT_FEATURES,
869 .name = "Sun UltraSparc III Cu",
870 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
871 .fpu_version = 0x00000000,
872 .mmu_version = mmu_us_3,
873 .nwindows = 8,
874 .maxtl = 5,
875 .features = CPU_DEFAULT_FEATURES,
878 .name = "Sun UltraSparc IIIi",
879 .iu_version = ((0x3eULL << 48) | (0x16ULL << 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 IV",
888 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
889 .fpu_version = 0x00000000,
890 .mmu_version = mmu_us_4,
891 .nwindows = 8,
892 .maxtl = 5,
893 .features = CPU_DEFAULT_FEATURES,
896 .name = "Sun UltraSparc IV+",
897 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
898 .fpu_version = 0x00000000,
899 .mmu_version = mmu_us_12,
900 .nwindows = 8,
901 .maxtl = 5,
902 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
905 .name = "Sun UltraSparc IIIi+",
906 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
907 .fpu_version = 0x00000000,
908 .mmu_version = mmu_us_3,
909 .nwindows = 8,
910 .maxtl = 5,
911 .features = CPU_DEFAULT_FEATURES,
914 .name = "Sun UltraSparc T1",
915 // defined in sparc_ifu_fdp.v and ctu.h
916 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
917 .fpu_version = 0x00000000,
918 .mmu_version = mmu_sun4v,
919 .nwindows = 8,
920 .maxtl = 6,
921 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
922 | CPU_FEATURE_GL,
925 .name = "Sun UltraSparc T2",
926 // defined in tlu_asi_ctl.v and n2_revid_cust.v
927 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
928 .fpu_version = 0x00000000,
929 .mmu_version = mmu_sun4v,
930 .nwindows = 8,
931 .maxtl = 6,
932 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
933 | CPU_FEATURE_GL,
936 .name = "NEC UltraSparc I",
937 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
938 .fpu_version = 0x00000000,
939 .mmu_version = mmu_us_12,
940 .nwindows = 8,
941 .maxtl = 5,
942 .features = CPU_DEFAULT_FEATURES,
944 #else
946 .name = "Fujitsu MB86900",
947 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
948 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
949 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
950 .mmu_bm = 0x00004000,
951 .mmu_ctpr_mask = 0x007ffff0,
952 .mmu_cxr_mask = 0x0000003f,
953 .mmu_sfsr_mask = 0xffffffff,
954 .mmu_trcr_mask = 0xffffffff,
955 .nwindows = 7,
956 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
959 .name = "Fujitsu MB86904",
960 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
961 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
962 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
963 .mmu_bm = 0x00004000,
964 .mmu_ctpr_mask = 0x00ffffc0,
965 .mmu_cxr_mask = 0x000000ff,
966 .mmu_sfsr_mask = 0x00016fff,
967 .mmu_trcr_mask = 0x00ffffff,
968 .nwindows = 8,
969 .features = CPU_DEFAULT_FEATURES,
972 .name = "Fujitsu MB86907",
973 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
974 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
975 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
976 .mmu_bm = 0x00004000,
977 .mmu_ctpr_mask = 0xffffffc0,
978 .mmu_cxr_mask = 0x000000ff,
979 .mmu_sfsr_mask = 0x00016fff,
980 .mmu_trcr_mask = 0xffffffff,
981 .nwindows = 8,
982 .features = CPU_DEFAULT_FEATURES,
985 .name = "LSI L64811",
986 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
987 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
988 .mmu_version = 0x10 << 24,
989 .mmu_bm = 0x00004000,
990 .mmu_ctpr_mask = 0x007ffff0,
991 .mmu_cxr_mask = 0x0000003f,
992 .mmu_sfsr_mask = 0xffffffff,
993 .mmu_trcr_mask = 0xffffffff,
994 .nwindows = 8,
995 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
996 CPU_FEATURE_FSMULD,
999 .name = "Cypress CY7C601",
1000 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1001 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1002 .mmu_version = 0x10 << 24,
1003 .mmu_bm = 0x00004000,
1004 .mmu_ctpr_mask = 0x007ffff0,
1005 .mmu_cxr_mask = 0x0000003f,
1006 .mmu_sfsr_mask = 0xffffffff,
1007 .mmu_trcr_mask = 0xffffffff,
1008 .nwindows = 8,
1009 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1010 CPU_FEATURE_FSMULD,
1013 .name = "Cypress CY7C611",
1014 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1015 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1016 .mmu_version = 0x10 << 24,
1017 .mmu_bm = 0x00004000,
1018 .mmu_ctpr_mask = 0x007ffff0,
1019 .mmu_cxr_mask = 0x0000003f,
1020 .mmu_sfsr_mask = 0xffffffff,
1021 .mmu_trcr_mask = 0xffffffff,
1022 .nwindows = 8,
1023 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1024 CPU_FEATURE_FSMULD,
1027 .name = "TI MicroSparc I",
1028 .iu_version = 0x41000000,
1029 .fpu_version = 4 << 17,
1030 .mmu_version = 0x41000000,
1031 .mmu_bm = 0x00004000,
1032 .mmu_ctpr_mask = 0x007ffff0,
1033 .mmu_cxr_mask = 0x0000003f,
1034 .mmu_sfsr_mask = 0x00016fff,
1035 .mmu_trcr_mask = 0x0000003f,
1036 .nwindows = 7,
1037 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1038 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1039 CPU_FEATURE_FMUL,
1042 .name = "TI MicroSparc II",
1043 .iu_version = 0x42000000,
1044 .fpu_version = 4 << 17,
1045 .mmu_version = 0x02000000,
1046 .mmu_bm = 0x00004000,
1047 .mmu_ctpr_mask = 0x00ffffc0,
1048 .mmu_cxr_mask = 0x000000ff,
1049 .mmu_sfsr_mask = 0x00016fff,
1050 .mmu_trcr_mask = 0x00ffffff,
1051 .nwindows = 8,
1052 .features = CPU_DEFAULT_FEATURES,
1055 .name = "TI MicroSparc IIep",
1056 .iu_version = 0x42000000,
1057 .fpu_version = 4 << 17,
1058 .mmu_version = 0x04000000,
1059 .mmu_bm = 0x00004000,
1060 .mmu_ctpr_mask = 0x00ffffc0,
1061 .mmu_cxr_mask = 0x000000ff,
1062 .mmu_sfsr_mask = 0x00016bff,
1063 .mmu_trcr_mask = 0x00ffffff,
1064 .nwindows = 8,
1065 .features = CPU_DEFAULT_FEATURES,
1068 .name = "TI SuperSparc 40", // STP1020NPGA
1069 .iu_version = 0x41000000, // SuperSPARC 2.x
1070 .fpu_version = 0 << 17,
1071 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1072 .mmu_bm = 0x00002000,
1073 .mmu_ctpr_mask = 0xffffffc0,
1074 .mmu_cxr_mask = 0x0000ffff,
1075 .mmu_sfsr_mask = 0xffffffff,
1076 .mmu_trcr_mask = 0xffffffff,
1077 .nwindows = 8,
1078 .features = CPU_DEFAULT_FEATURES,
1081 .name = "TI SuperSparc 50", // STP1020PGA
1082 .iu_version = 0x40000000, // SuperSPARC 3.x
1083 .fpu_version = 0 << 17,
1084 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1085 .mmu_bm = 0x00002000,
1086 .mmu_ctpr_mask = 0xffffffc0,
1087 .mmu_cxr_mask = 0x0000ffff,
1088 .mmu_sfsr_mask = 0xffffffff,
1089 .mmu_trcr_mask = 0xffffffff,
1090 .nwindows = 8,
1091 .features = CPU_DEFAULT_FEATURES,
1094 .name = "TI SuperSparc 51",
1095 .iu_version = 0x40000000, // SuperSPARC 3.x
1096 .fpu_version = 0 << 17,
1097 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1098 .mmu_bm = 0x00002000,
1099 .mmu_ctpr_mask = 0xffffffc0,
1100 .mmu_cxr_mask = 0x0000ffff,
1101 .mmu_sfsr_mask = 0xffffffff,
1102 .mmu_trcr_mask = 0xffffffff,
1103 .mxcc_version = 0x00000104,
1104 .nwindows = 8,
1105 .features = CPU_DEFAULT_FEATURES,
1108 .name = "TI SuperSparc 60", // STP1020APGA
1109 .iu_version = 0x40000000, // SuperSPARC 3.x
1110 .fpu_version = 0 << 17,
1111 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1112 .mmu_bm = 0x00002000,
1113 .mmu_ctpr_mask = 0xffffffc0,
1114 .mmu_cxr_mask = 0x0000ffff,
1115 .mmu_sfsr_mask = 0xffffffff,
1116 .mmu_trcr_mask = 0xffffffff,
1117 .nwindows = 8,
1118 .features = CPU_DEFAULT_FEATURES,
1121 .name = "TI SuperSparc 61",
1122 .iu_version = 0x44000000, // SuperSPARC 3.x
1123 .fpu_version = 0 << 17,
1124 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1125 .mmu_bm = 0x00002000,
1126 .mmu_ctpr_mask = 0xffffffc0,
1127 .mmu_cxr_mask = 0x0000ffff,
1128 .mmu_sfsr_mask = 0xffffffff,
1129 .mmu_trcr_mask = 0xffffffff,
1130 .mxcc_version = 0x00000104,
1131 .nwindows = 8,
1132 .features = CPU_DEFAULT_FEATURES,
1135 .name = "TI SuperSparc II",
1136 .iu_version = 0x40000000, // SuperSPARC II 1.x
1137 .fpu_version = 0 << 17,
1138 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1139 .mmu_bm = 0x00002000,
1140 .mmu_ctpr_mask = 0xffffffc0,
1141 .mmu_cxr_mask = 0x0000ffff,
1142 .mmu_sfsr_mask = 0xffffffff,
1143 .mmu_trcr_mask = 0xffffffff,
1144 .mxcc_version = 0x00000104,
1145 .nwindows = 8,
1146 .features = CPU_DEFAULT_FEATURES,
1149 .name = "Ross RT625",
1150 .iu_version = 0x1e000000,
1151 .fpu_version = 1 << 17,
1152 .mmu_version = 0x1e000000,
1153 .mmu_bm = 0x00004000,
1154 .mmu_ctpr_mask = 0x007ffff0,
1155 .mmu_cxr_mask = 0x0000003f,
1156 .mmu_sfsr_mask = 0xffffffff,
1157 .mmu_trcr_mask = 0xffffffff,
1158 .nwindows = 8,
1159 .features = CPU_DEFAULT_FEATURES,
1162 .name = "Ross RT620",
1163 .iu_version = 0x1f000000,
1164 .fpu_version = 1 << 17,
1165 .mmu_version = 0x1f000000,
1166 .mmu_bm = 0x00004000,
1167 .mmu_ctpr_mask = 0x007ffff0,
1168 .mmu_cxr_mask = 0x0000003f,
1169 .mmu_sfsr_mask = 0xffffffff,
1170 .mmu_trcr_mask = 0xffffffff,
1171 .nwindows = 8,
1172 .features = CPU_DEFAULT_FEATURES,
1175 .name = "BIT B5010",
1176 .iu_version = 0x20000000,
1177 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1178 .mmu_version = 0x20000000,
1179 .mmu_bm = 0x00004000,
1180 .mmu_ctpr_mask = 0x007ffff0,
1181 .mmu_cxr_mask = 0x0000003f,
1182 .mmu_sfsr_mask = 0xffffffff,
1183 .mmu_trcr_mask = 0xffffffff,
1184 .nwindows = 8,
1185 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1186 CPU_FEATURE_FSMULD,
1189 .name = "Matsushita MN10501",
1190 .iu_version = 0x50000000,
1191 .fpu_version = 0 << 17,
1192 .mmu_version = 0x50000000,
1193 .mmu_bm = 0x00004000,
1194 .mmu_ctpr_mask = 0x007ffff0,
1195 .mmu_cxr_mask = 0x0000003f,
1196 .mmu_sfsr_mask = 0xffffffff,
1197 .mmu_trcr_mask = 0xffffffff,
1198 .nwindows = 8,
1199 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1200 CPU_FEATURE_FSMULD,
1203 .name = "Weitek W8601",
1204 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1205 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1206 .mmu_version = 0x10 << 24,
1207 .mmu_bm = 0x00004000,
1208 .mmu_ctpr_mask = 0x007ffff0,
1209 .mmu_cxr_mask = 0x0000003f,
1210 .mmu_sfsr_mask = 0xffffffff,
1211 .mmu_trcr_mask = 0xffffffff,
1212 .nwindows = 8,
1213 .features = CPU_DEFAULT_FEATURES,
1216 .name = "LEON2",
1217 .iu_version = 0xf2000000,
1218 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1219 .mmu_version = 0xf2000000,
1220 .mmu_bm = 0x00004000,
1221 .mmu_ctpr_mask = 0x007ffff0,
1222 .mmu_cxr_mask = 0x0000003f,
1223 .mmu_sfsr_mask = 0xffffffff,
1224 .mmu_trcr_mask = 0xffffffff,
1225 .nwindows = 8,
1226 .features = CPU_DEFAULT_FEATURES,
1229 .name = "LEON3",
1230 .iu_version = 0xf3000000,
1231 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1232 .mmu_version = 0xf3000000,
1233 .mmu_bm = 0x00004000,
1234 .mmu_ctpr_mask = 0x007ffff0,
1235 .mmu_cxr_mask = 0x0000003f,
1236 .mmu_sfsr_mask = 0xffffffff,
1237 .mmu_trcr_mask = 0xffffffff,
1238 .nwindows = 8,
1239 .features = CPU_DEFAULT_FEATURES,
1241 #endif
1244 static const char * const feature_name[] = {
1245 "float",
1246 "float128",
1247 "swap",
1248 "mul",
1249 "div",
1250 "flush",
1251 "fsqrt",
1252 "fmul",
1253 "vis1",
1254 "vis2",
1255 "fsmuld",
1256 "hypv",
1257 "cmt",
1258 "gl",
1261 static void print_features(FILE *f,
1262 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1263 uint32_t features, const char *prefix)
1265 unsigned int i;
1267 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1268 if (feature_name[i] && (features & (1 << i))) {
1269 if (prefix)
1270 (*cpu_fprintf)(f, "%s", prefix);
1271 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1275 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1277 unsigned int i;
1279 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1280 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1281 *features |= 1 << i;
1282 return;
1284 fprintf(stderr, "CPU feature %s not found\n", flagname);
1287 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1289 unsigned int i;
1290 const sparc_def_t *def = NULL;
1291 char *s = strdup(cpu_model);
1292 char *featurestr, *name = strtok(s, ",");
1293 uint32_t plus_features = 0;
1294 uint32_t minus_features = 0;
1295 long long iu_version;
1296 uint32_t fpu_version, mmu_version, nwindows;
1298 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1299 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1300 def = &sparc_defs[i];
1303 if (!def)
1304 goto error;
1305 memcpy(cpu_def, def, sizeof(*def));
1307 featurestr = strtok(NULL, ",");
1308 while (featurestr) {
1309 char *val;
1311 if (featurestr[0] == '+') {
1312 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1313 } else if (featurestr[0] == '-') {
1314 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1315 } else if ((val = strchr(featurestr, '='))) {
1316 *val = 0; val++;
1317 if (!strcmp(featurestr, "iu_version")) {
1318 char *err;
1320 iu_version = strtoll(val, &err, 0);
1321 if (!*val || *err) {
1322 fprintf(stderr, "bad numerical value %s\n", val);
1323 goto error;
1325 cpu_def->iu_version = iu_version;
1326 #ifdef DEBUG_FEATURES
1327 fprintf(stderr, "iu_version %llx\n", iu_version);
1328 #endif
1329 } else if (!strcmp(featurestr, "fpu_version")) {
1330 char *err;
1332 fpu_version = strtol(val, &err, 0);
1333 if (!*val || *err) {
1334 fprintf(stderr, "bad numerical value %s\n", val);
1335 goto error;
1337 cpu_def->fpu_version = fpu_version;
1338 #ifdef DEBUG_FEATURES
1339 fprintf(stderr, "fpu_version %x\n", fpu_version);
1340 #endif
1341 } else if (!strcmp(featurestr, "mmu_version")) {
1342 char *err;
1344 mmu_version = strtol(val, &err, 0);
1345 if (!*val || *err) {
1346 fprintf(stderr, "bad numerical value %s\n", val);
1347 goto error;
1349 cpu_def->mmu_version = mmu_version;
1350 #ifdef DEBUG_FEATURES
1351 fprintf(stderr, "mmu_version %x\n", mmu_version);
1352 #endif
1353 } else if (!strcmp(featurestr, "nwindows")) {
1354 char *err;
1356 nwindows = strtol(val, &err, 0);
1357 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1358 nwindows < MIN_NWINDOWS) {
1359 fprintf(stderr, "bad numerical value %s\n", val);
1360 goto error;
1362 cpu_def->nwindows = nwindows;
1363 #ifdef DEBUG_FEATURES
1364 fprintf(stderr, "nwindows %d\n", nwindows);
1365 #endif
1366 } else {
1367 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1368 goto error;
1370 } else {
1371 fprintf(stderr, "feature string `%s' not in format "
1372 "(+feature|-feature|feature=xyz)\n", featurestr);
1373 goto error;
1375 featurestr = strtok(NULL, ",");
1377 cpu_def->features |= plus_features;
1378 cpu_def->features &= ~minus_features;
1379 #ifdef DEBUG_FEATURES
1380 print_features(stderr, fprintf, cpu_def->features, NULL);
1381 #endif
1382 free(s);
1383 return 0;
1385 error:
1386 free(s);
1387 return -1;
1390 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1392 unsigned int i;
1394 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1395 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1396 sparc_defs[i].name,
1397 sparc_defs[i].iu_version,
1398 sparc_defs[i].fpu_version,
1399 sparc_defs[i].mmu_version,
1400 sparc_defs[i].nwindows);
1401 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1402 ~sparc_defs[i].features, "-");
1403 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1404 sparc_defs[i].features, "+");
1405 (*cpu_fprintf)(f, "\n");
1407 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1408 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1409 (*cpu_fprintf)(f, "\n");
1410 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1411 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1412 (*cpu_fprintf)(f, "\n");
1413 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1414 "fpu_version mmu_version nwindows\n");
1417 void cpu_dump_state(CPUState *env, FILE *f,
1418 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1419 int flags)
1421 int i, x;
1423 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1424 env->npc);
1425 cpu_fprintf(f, "General Registers:\n");
1426 for (i = 0; i < 4; i++)
1427 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1428 cpu_fprintf(f, "\n");
1429 for (; i < 8; i++)
1430 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1431 cpu_fprintf(f, "\nCurrent Register Window:\n");
1432 for (x = 0; x < 3; x++) {
1433 for (i = 0; i < 4; i++)
1434 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1435 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1436 env->regwptr[i + x * 8]);
1437 cpu_fprintf(f, "\n");
1438 for (; i < 8; i++)
1439 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1440 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1441 env->regwptr[i + x * 8]);
1442 cpu_fprintf(f, "\n");
1444 cpu_fprintf(f, "\nFloating Point Registers:\n");
1445 for (i = 0; i < 32; i++) {
1446 if ((i & 3) == 0)
1447 cpu_fprintf(f, "%%f%02d:", i);
1448 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1449 if ((i & 3) == 3)
1450 cpu_fprintf(f, "\n");
1452 #ifdef TARGET_SPARC64
1453 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1454 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1455 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1456 "cleanwin %d cwp %d\n",
1457 env->cansave, env->canrestore, env->otherwin, env->wstate,
1458 env->cleanwin, env->nwindows - 1 - env->cwp);
1459 #else
1461 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1463 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1464 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1465 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1466 env->psrs?'S':'-', env->psrps?'P':'-',
1467 env->psret?'E':'-', env->wim);
1468 #endif
1469 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);