qdev: integrate reset
[armpft.git] / target-sparc / helper.c
blob920432cb195ef8e53b30916ab9aa471ed8776884
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)
393 uint64_t mask;
395 switch ((tlb->tte >> 61) & 3) {
396 default:
397 case 0x0: // 8k
398 mask = 0xffffffffffffe000ULL;
399 break;
400 case 0x1: // 64k
401 mask = 0xffffffffffff0000ULL;
402 break;
403 case 0x2: // 512k
404 mask = 0xfffffffffff80000ULL;
405 break;
406 case 0x3: // 4M
407 mask = 0xffffffffffc00000ULL;
408 break;
411 // valid, context match, virtual address match?
412 if (TTE_IS_VALID(tlb->tte) &&
413 compare_masked(context, tlb->tag, 0x1fff) &&
414 compare_masked(address, tlb->tag, mask))
416 // decode physical address
417 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
418 return 1;
421 return 0;
424 static int get_physical_address_data(CPUState *env,
425 target_phys_addr_t *physical, int *prot,
426 target_ulong address, int rw, int is_user)
428 unsigned int i;
429 uint64_t context;
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 context = env->dmmu.mmu_primary_context & 0x1fff;
439 for (i = 0; i < 64; i++) {
440 // ctx match, vaddr match, valid?
441 if (ultrasparc_tag_match(&env->dtlb[i],
442 address, context, physical)
444 // access ok?
445 if (((env->dtlb[i].tte & 0x4) && is_user) ||
446 (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
447 uint8_t fault_type = 0;
449 if ((env->dtlb[i].tte & 0x4) && is_user) {
450 fault_type |= 1; /* privilege violation */
453 if (env->dmmu.sfsr & 1) /* Fault status register */
454 env->dmmu.sfsr = 2; /* overflow (not read before
455 another fault) */
457 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
459 env->dmmu.sfsr |= (fault_type << 7);
461 env->dmmu.sfar = address; /* Fault address register */
462 env->exception_index = TT_DFAULT;
463 #ifdef DEBUG_MMU
464 printf("DFAULT at 0x%" PRIx64 "\n", address);
465 #endif
466 return 1;
468 *prot = PAGE_READ;
469 if (env->dtlb[i].tte & 0x2)
470 *prot |= PAGE_WRITE;
471 TTE_SET_USED(env->dtlb[i].tte);
472 return 0;
475 #ifdef DEBUG_MMU
476 printf("DMISS at 0x%" PRIx64 "\n", address);
477 #endif
478 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
479 env->exception_index = TT_DMISS;
480 return 1;
483 static int get_physical_address_code(CPUState *env,
484 target_phys_addr_t *physical, int *prot,
485 target_ulong address, int is_user)
487 unsigned int i;
488 uint64_t context;
490 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
491 /* IMMU disabled */
492 *physical = ultrasparc_truncate_physical(address);
493 *prot = PAGE_EXEC;
494 return 0;
497 context = env->dmmu.mmu_primary_context & 0x1fff;
499 for (i = 0; i < 64; i++) {
500 // ctx match, vaddr match, valid?
501 if (ultrasparc_tag_match(&env->itlb[i],
502 address, context, physical)
504 // access ok?
505 if ((env->itlb[i].tte & 0x4) && is_user) {
506 if (env->immu.sfsr) /* Fault status register */
507 env->immu.sfsr = 2; /* overflow (not read before
508 another fault) */
509 env->immu.sfsr |= (is_user << 3) | 1;
510 env->exception_index = TT_TFAULT;
511 #ifdef DEBUG_MMU
512 printf("TFAULT at 0x%" PRIx64 "\n", address);
513 #endif
514 return 1;
516 *prot = PAGE_EXEC;
517 TTE_SET_USED(env->itlb[i].tte);
518 return 0;
521 #ifdef DEBUG_MMU
522 printf("TMISS at 0x%" PRIx64 "\n", address);
523 #endif
524 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
525 env->immu.tag_access = (address & ~0x1fffULL) | context;
526 env->exception_index = TT_TMISS;
527 return 1;
530 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
531 int *prot, int *access_index,
532 target_ulong address, int rw, int mmu_idx)
534 int is_user = mmu_idx == MMU_USER_IDX;
536 if (rw == 2)
537 return get_physical_address_code(env, physical, prot, address,
538 is_user);
539 else
540 return get_physical_address_data(env, physical, prot, address, rw,
541 is_user);
544 /* Perform address translation */
545 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
546 int mmu_idx, int is_softmmu)
548 target_ulong virt_addr, vaddr;
549 target_phys_addr_t paddr;
550 int error_code = 0, prot, ret = 0, access_index;
552 error_code = get_physical_address(env, &paddr, &prot, &access_index,
553 address, rw, mmu_idx);
554 if (error_code == 0) {
555 virt_addr = address & TARGET_PAGE_MASK;
556 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
557 (TARGET_PAGE_SIZE - 1));
558 #ifdef DEBUG_MMU
559 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
560 "\n", address, paddr, vaddr);
561 #endif
562 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
563 return ret;
565 // XXX
566 return 1;
569 #ifdef DEBUG_MMU
570 void dump_mmu(CPUState *env)
572 unsigned int i;
573 const char *mask;
575 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
576 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
577 if ((env->lsu & DMMU_E) == 0) {
578 printf("DMMU disabled\n");
579 } else {
580 printf("DMMU dump:\n");
581 for (i = 0; i < 64; i++) {
582 switch ((env->dtlb_tte[i] >> 61) & 3) {
583 default:
584 case 0x0:
585 mask = " 8k";
586 break;
587 case 0x1:
588 mask = " 64k";
589 break;
590 case 0x2:
591 mask = "512k";
592 break;
593 case 0x3:
594 mask = " 4M";
595 break;
597 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
598 printf("[%02u] VA: " PRIx64 ", PA: " PRIx64
599 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
601 env->dtlb_tag[i] & (uint64_t)~0x1fffULL,
602 env->dtlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
603 mask,
604 env->dtlb_tte[i] & 0x4? "priv": "user",
605 env->dtlb_tte[i] & 0x2? "RW": "RO",
606 env->dtlb_tte[i] & 0x40? "locked": "unlocked",
607 env->dtlb_tag[i] & (uint64_t)0x1fffULL);
611 if ((env->lsu & IMMU_E) == 0) {
612 printf("IMMU disabled\n");
613 } else {
614 printf("IMMU dump:\n");
615 for (i = 0; i < 64; i++) {
616 switch ((env->itlb_tte[i] >> 61) & 3) {
617 default:
618 case 0x0:
619 mask = " 8k";
620 break;
621 case 0x1:
622 mask = " 64k";
623 break;
624 case 0x2:
625 mask = "512k";
626 break;
627 case 0x3:
628 mask = " 4M";
629 break;
631 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
632 printf("[%02u] VA: " PRIx64 ", PA: " PRIx64
633 ", %s, %s, %s, ctx %" PRId64 "\n",
635 env->itlb[i].tag & (uint64_t)~0x1fffULL,
636 env->itlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
637 mask,
638 env->itlb_tte[i] & 0x4? "priv": "user",
639 env->itlb_tte[i] & 0x40? "locked": "unlocked",
640 env->itlb[i].tag & (uint64_t)0x1fffULL);
645 #endif /* DEBUG_MMU */
647 #endif /* TARGET_SPARC64 */
648 #endif /* !CONFIG_USER_ONLY */
651 #if defined(CONFIG_USER_ONLY)
652 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
654 return addr;
657 #else
658 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
660 target_phys_addr_t phys_addr;
661 int prot, access_index;
663 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
664 MMU_KERNEL_IDX) != 0)
665 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
666 0, MMU_KERNEL_IDX) != 0)
667 return -1;
668 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
669 return -1;
670 return phys_addr;
672 #endif
674 void cpu_reset(CPUSPARCState *env)
676 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
677 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
678 log_cpu_state(env, 0);
681 tlb_flush(env, 1);
682 env->cwp = 0;
683 #ifndef TARGET_SPARC64
684 env->wim = 1;
685 #endif
686 env->regwptr = env->regbase + (env->cwp * 16);
687 CC_OP = CC_OP_FLAGS;
688 #if defined(CONFIG_USER_ONLY)
689 #ifdef TARGET_SPARC64
690 env->cleanwin = env->nwindows - 2;
691 env->cansave = env->nwindows - 2;
692 env->pstate = PS_RMO | PS_PEF | PS_IE;
693 env->asi = 0x82; // Primary no-fault
694 #endif
695 #else
696 #if !defined(TARGET_SPARC64)
697 env->psret = 0;
698 #endif
699 env->psrs = 1;
700 env->psrps = 1;
701 #ifdef TARGET_SPARC64
702 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
703 env->hpstate = HS_PRIV;
704 env->tl = env->maxtl;
705 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
706 env->lsu = 0;
707 #else
708 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
709 env->mmuregs[0] |= env->def->mmu_bm;
710 #endif
711 env->pc = 0;
712 env->npc = env->pc + 4;
713 #endif
716 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
718 sparc_def_t def1, *def = &def1;
720 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
721 return -1;
723 env->def = qemu_mallocz(sizeof(*def));
724 memcpy(env->def, def, sizeof(*def));
725 #if defined(CONFIG_USER_ONLY)
726 if ((env->def->features & CPU_FEATURE_FLOAT))
727 env->def->features |= CPU_FEATURE_FLOAT128;
728 #endif
729 env->cpu_model_str = cpu_model;
730 env->version = def->iu_version;
731 env->fsr = def->fpu_version;
732 env->nwindows = def->nwindows;
733 #if !defined(TARGET_SPARC64)
734 env->mmuregs[0] |= def->mmu_version;
735 cpu_sparc_set_id(env, 0);
736 env->mxccregs[7] |= def->mxcc_version;
737 #else
738 env->mmu_version = def->mmu_version;
739 env->maxtl = def->maxtl;
740 env->version |= def->maxtl << 8;
741 env->version |= def->nwindows - 1;
742 #endif
743 return 0;
746 static void cpu_sparc_close(CPUSPARCState *env)
748 free(env->def);
749 free(env);
752 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
754 CPUSPARCState *env;
756 env = qemu_mallocz(sizeof(CPUSPARCState));
757 cpu_exec_init(env);
759 gen_intermediate_code_init(env);
761 if (cpu_sparc_register(env, cpu_model) < 0) {
762 cpu_sparc_close(env);
763 return NULL;
765 cpu_reset(env);
766 qemu_init_vcpu(env);
768 return env;
771 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
773 #if !defined(TARGET_SPARC64)
774 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
775 #endif
778 static const sparc_def_t sparc_defs[] = {
779 #ifdef TARGET_SPARC64
781 .name = "Fujitsu Sparc64",
782 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
783 .fpu_version = 0x00000000,
784 .mmu_version = mmu_us_12,
785 .nwindows = 4,
786 .maxtl = 4,
787 .features = CPU_DEFAULT_FEATURES,
790 .name = "Fujitsu Sparc64 III",
791 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
792 .fpu_version = 0x00000000,
793 .mmu_version = mmu_us_12,
794 .nwindows = 5,
795 .maxtl = 4,
796 .features = CPU_DEFAULT_FEATURES,
799 .name = "Fujitsu Sparc64 IV",
800 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
801 .fpu_version = 0x00000000,
802 .mmu_version = mmu_us_12,
803 .nwindows = 8,
804 .maxtl = 5,
805 .features = CPU_DEFAULT_FEATURES,
808 .name = "Fujitsu Sparc64 V",
809 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
810 .fpu_version = 0x00000000,
811 .mmu_version = mmu_us_12,
812 .nwindows = 8,
813 .maxtl = 5,
814 .features = CPU_DEFAULT_FEATURES,
817 .name = "TI UltraSparc I",
818 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
819 .fpu_version = 0x00000000,
820 .mmu_version = mmu_us_12,
821 .nwindows = 8,
822 .maxtl = 5,
823 .features = CPU_DEFAULT_FEATURES,
826 .name = "TI UltraSparc II",
827 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
828 .fpu_version = 0x00000000,
829 .mmu_version = mmu_us_12,
830 .nwindows = 8,
831 .maxtl = 5,
832 .features = CPU_DEFAULT_FEATURES,
835 .name = "TI UltraSparc IIi",
836 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
837 .fpu_version = 0x00000000,
838 .mmu_version = mmu_us_12,
839 .nwindows = 8,
840 .maxtl = 5,
841 .features = CPU_DEFAULT_FEATURES,
844 .name = "TI UltraSparc IIe",
845 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
846 .fpu_version = 0x00000000,
847 .mmu_version = mmu_us_12,
848 .nwindows = 8,
849 .maxtl = 5,
850 .features = CPU_DEFAULT_FEATURES,
853 .name = "Sun UltraSparc III",
854 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
855 .fpu_version = 0x00000000,
856 .mmu_version = mmu_us_12,
857 .nwindows = 8,
858 .maxtl = 5,
859 .features = CPU_DEFAULT_FEATURES,
862 .name = "Sun UltraSparc III Cu",
863 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
864 .fpu_version = 0x00000000,
865 .mmu_version = mmu_us_3,
866 .nwindows = 8,
867 .maxtl = 5,
868 .features = CPU_DEFAULT_FEATURES,
871 .name = "Sun UltraSparc IIIi",
872 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
873 .fpu_version = 0x00000000,
874 .mmu_version = mmu_us_12,
875 .nwindows = 8,
876 .maxtl = 5,
877 .features = CPU_DEFAULT_FEATURES,
880 .name = "Sun UltraSparc IV",
881 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
882 .fpu_version = 0x00000000,
883 .mmu_version = mmu_us_4,
884 .nwindows = 8,
885 .maxtl = 5,
886 .features = CPU_DEFAULT_FEATURES,
889 .name = "Sun UltraSparc IV+",
890 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
891 .fpu_version = 0x00000000,
892 .mmu_version = mmu_us_12,
893 .nwindows = 8,
894 .maxtl = 5,
895 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
898 .name = "Sun UltraSparc IIIi+",
899 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
900 .fpu_version = 0x00000000,
901 .mmu_version = mmu_us_3,
902 .nwindows = 8,
903 .maxtl = 5,
904 .features = CPU_DEFAULT_FEATURES,
907 .name = "Sun UltraSparc T1",
908 // defined in sparc_ifu_fdp.v and ctu.h
909 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
910 .fpu_version = 0x00000000,
911 .mmu_version = mmu_sun4v,
912 .nwindows = 8,
913 .maxtl = 6,
914 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
915 | CPU_FEATURE_GL,
918 .name = "Sun UltraSparc T2",
919 // defined in tlu_asi_ctl.v and n2_revid_cust.v
920 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
921 .fpu_version = 0x00000000,
922 .mmu_version = mmu_sun4v,
923 .nwindows = 8,
924 .maxtl = 6,
925 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
926 | CPU_FEATURE_GL,
929 .name = "NEC UltraSparc I",
930 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
931 .fpu_version = 0x00000000,
932 .mmu_version = mmu_us_12,
933 .nwindows = 8,
934 .maxtl = 5,
935 .features = CPU_DEFAULT_FEATURES,
937 #else
939 .name = "Fujitsu MB86900",
940 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
941 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
942 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
943 .mmu_bm = 0x00004000,
944 .mmu_ctpr_mask = 0x007ffff0,
945 .mmu_cxr_mask = 0x0000003f,
946 .mmu_sfsr_mask = 0xffffffff,
947 .mmu_trcr_mask = 0xffffffff,
948 .nwindows = 7,
949 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
952 .name = "Fujitsu MB86904",
953 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
954 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
955 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
956 .mmu_bm = 0x00004000,
957 .mmu_ctpr_mask = 0x00ffffc0,
958 .mmu_cxr_mask = 0x000000ff,
959 .mmu_sfsr_mask = 0x00016fff,
960 .mmu_trcr_mask = 0x00ffffff,
961 .nwindows = 8,
962 .features = CPU_DEFAULT_FEATURES,
965 .name = "Fujitsu MB86907",
966 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
967 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
968 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
969 .mmu_bm = 0x00004000,
970 .mmu_ctpr_mask = 0xffffffc0,
971 .mmu_cxr_mask = 0x000000ff,
972 .mmu_sfsr_mask = 0x00016fff,
973 .mmu_trcr_mask = 0xffffffff,
974 .nwindows = 8,
975 .features = CPU_DEFAULT_FEATURES,
978 .name = "LSI L64811",
979 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
980 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
981 .mmu_version = 0x10 << 24,
982 .mmu_bm = 0x00004000,
983 .mmu_ctpr_mask = 0x007ffff0,
984 .mmu_cxr_mask = 0x0000003f,
985 .mmu_sfsr_mask = 0xffffffff,
986 .mmu_trcr_mask = 0xffffffff,
987 .nwindows = 8,
988 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
989 CPU_FEATURE_FSMULD,
992 .name = "Cypress CY7C601",
993 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
994 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
995 .mmu_version = 0x10 << 24,
996 .mmu_bm = 0x00004000,
997 .mmu_ctpr_mask = 0x007ffff0,
998 .mmu_cxr_mask = 0x0000003f,
999 .mmu_sfsr_mask = 0xffffffff,
1000 .mmu_trcr_mask = 0xffffffff,
1001 .nwindows = 8,
1002 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1003 CPU_FEATURE_FSMULD,
1006 .name = "Cypress CY7C611",
1007 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1008 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1009 .mmu_version = 0x10 << 24,
1010 .mmu_bm = 0x00004000,
1011 .mmu_ctpr_mask = 0x007ffff0,
1012 .mmu_cxr_mask = 0x0000003f,
1013 .mmu_sfsr_mask = 0xffffffff,
1014 .mmu_trcr_mask = 0xffffffff,
1015 .nwindows = 8,
1016 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1017 CPU_FEATURE_FSMULD,
1020 .name = "TI MicroSparc I",
1021 .iu_version = 0x41000000,
1022 .fpu_version = 4 << 17,
1023 .mmu_version = 0x41000000,
1024 .mmu_bm = 0x00004000,
1025 .mmu_ctpr_mask = 0x007ffff0,
1026 .mmu_cxr_mask = 0x0000003f,
1027 .mmu_sfsr_mask = 0x00016fff,
1028 .mmu_trcr_mask = 0x0000003f,
1029 .nwindows = 7,
1030 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1031 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1032 CPU_FEATURE_FMUL,
1035 .name = "TI MicroSparc II",
1036 .iu_version = 0x42000000,
1037 .fpu_version = 4 << 17,
1038 .mmu_version = 0x02000000,
1039 .mmu_bm = 0x00004000,
1040 .mmu_ctpr_mask = 0x00ffffc0,
1041 .mmu_cxr_mask = 0x000000ff,
1042 .mmu_sfsr_mask = 0x00016fff,
1043 .mmu_trcr_mask = 0x00ffffff,
1044 .nwindows = 8,
1045 .features = CPU_DEFAULT_FEATURES,
1048 .name = "TI MicroSparc IIep",
1049 .iu_version = 0x42000000,
1050 .fpu_version = 4 << 17,
1051 .mmu_version = 0x04000000,
1052 .mmu_bm = 0x00004000,
1053 .mmu_ctpr_mask = 0x00ffffc0,
1054 .mmu_cxr_mask = 0x000000ff,
1055 .mmu_sfsr_mask = 0x00016bff,
1056 .mmu_trcr_mask = 0x00ffffff,
1057 .nwindows = 8,
1058 .features = CPU_DEFAULT_FEATURES,
1061 .name = "TI SuperSparc 40", // STP1020NPGA
1062 .iu_version = 0x41000000, // SuperSPARC 2.x
1063 .fpu_version = 0 << 17,
1064 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1065 .mmu_bm = 0x00002000,
1066 .mmu_ctpr_mask = 0xffffffc0,
1067 .mmu_cxr_mask = 0x0000ffff,
1068 .mmu_sfsr_mask = 0xffffffff,
1069 .mmu_trcr_mask = 0xffffffff,
1070 .nwindows = 8,
1071 .features = CPU_DEFAULT_FEATURES,
1074 .name = "TI SuperSparc 50", // STP1020PGA
1075 .iu_version = 0x40000000, // SuperSPARC 3.x
1076 .fpu_version = 0 << 17,
1077 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1078 .mmu_bm = 0x00002000,
1079 .mmu_ctpr_mask = 0xffffffc0,
1080 .mmu_cxr_mask = 0x0000ffff,
1081 .mmu_sfsr_mask = 0xffffffff,
1082 .mmu_trcr_mask = 0xffffffff,
1083 .nwindows = 8,
1084 .features = CPU_DEFAULT_FEATURES,
1087 .name = "TI SuperSparc 51",
1088 .iu_version = 0x40000000, // SuperSPARC 3.x
1089 .fpu_version = 0 << 17,
1090 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1091 .mmu_bm = 0x00002000,
1092 .mmu_ctpr_mask = 0xffffffc0,
1093 .mmu_cxr_mask = 0x0000ffff,
1094 .mmu_sfsr_mask = 0xffffffff,
1095 .mmu_trcr_mask = 0xffffffff,
1096 .mxcc_version = 0x00000104,
1097 .nwindows = 8,
1098 .features = CPU_DEFAULT_FEATURES,
1101 .name = "TI SuperSparc 60", // STP1020APGA
1102 .iu_version = 0x40000000, // SuperSPARC 3.x
1103 .fpu_version = 0 << 17,
1104 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1105 .mmu_bm = 0x00002000,
1106 .mmu_ctpr_mask = 0xffffffc0,
1107 .mmu_cxr_mask = 0x0000ffff,
1108 .mmu_sfsr_mask = 0xffffffff,
1109 .mmu_trcr_mask = 0xffffffff,
1110 .nwindows = 8,
1111 .features = CPU_DEFAULT_FEATURES,
1114 .name = "TI SuperSparc 61",
1115 .iu_version = 0x44000000, // SuperSPARC 3.x
1116 .fpu_version = 0 << 17,
1117 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1118 .mmu_bm = 0x00002000,
1119 .mmu_ctpr_mask = 0xffffffc0,
1120 .mmu_cxr_mask = 0x0000ffff,
1121 .mmu_sfsr_mask = 0xffffffff,
1122 .mmu_trcr_mask = 0xffffffff,
1123 .mxcc_version = 0x00000104,
1124 .nwindows = 8,
1125 .features = CPU_DEFAULT_FEATURES,
1128 .name = "TI SuperSparc II",
1129 .iu_version = 0x40000000, // SuperSPARC II 1.x
1130 .fpu_version = 0 << 17,
1131 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1132 .mmu_bm = 0x00002000,
1133 .mmu_ctpr_mask = 0xffffffc0,
1134 .mmu_cxr_mask = 0x0000ffff,
1135 .mmu_sfsr_mask = 0xffffffff,
1136 .mmu_trcr_mask = 0xffffffff,
1137 .mxcc_version = 0x00000104,
1138 .nwindows = 8,
1139 .features = CPU_DEFAULT_FEATURES,
1142 .name = "Ross RT625",
1143 .iu_version = 0x1e000000,
1144 .fpu_version = 1 << 17,
1145 .mmu_version = 0x1e000000,
1146 .mmu_bm = 0x00004000,
1147 .mmu_ctpr_mask = 0x007ffff0,
1148 .mmu_cxr_mask = 0x0000003f,
1149 .mmu_sfsr_mask = 0xffffffff,
1150 .mmu_trcr_mask = 0xffffffff,
1151 .nwindows = 8,
1152 .features = CPU_DEFAULT_FEATURES,
1155 .name = "Ross RT620",
1156 .iu_version = 0x1f000000,
1157 .fpu_version = 1 << 17,
1158 .mmu_version = 0x1f000000,
1159 .mmu_bm = 0x00004000,
1160 .mmu_ctpr_mask = 0x007ffff0,
1161 .mmu_cxr_mask = 0x0000003f,
1162 .mmu_sfsr_mask = 0xffffffff,
1163 .mmu_trcr_mask = 0xffffffff,
1164 .nwindows = 8,
1165 .features = CPU_DEFAULT_FEATURES,
1168 .name = "BIT B5010",
1169 .iu_version = 0x20000000,
1170 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1171 .mmu_version = 0x20000000,
1172 .mmu_bm = 0x00004000,
1173 .mmu_ctpr_mask = 0x007ffff0,
1174 .mmu_cxr_mask = 0x0000003f,
1175 .mmu_sfsr_mask = 0xffffffff,
1176 .mmu_trcr_mask = 0xffffffff,
1177 .nwindows = 8,
1178 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1179 CPU_FEATURE_FSMULD,
1182 .name = "Matsushita MN10501",
1183 .iu_version = 0x50000000,
1184 .fpu_version = 0 << 17,
1185 .mmu_version = 0x50000000,
1186 .mmu_bm = 0x00004000,
1187 .mmu_ctpr_mask = 0x007ffff0,
1188 .mmu_cxr_mask = 0x0000003f,
1189 .mmu_sfsr_mask = 0xffffffff,
1190 .mmu_trcr_mask = 0xffffffff,
1191 .nwindows = 8,
1192 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1193 CPU_FEATURE_FSMULD,
1196 .name = "Weitek W8601",
1197 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1198 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1199 .mmu_version = 0x10 << 24,
1200 .mmu_bm = 0x00004000,
1201 .mmu_ctpr_mask = 0x007ffff0,
1202 .mmu_cxr_mask = 0x0000003f,
1203 .mmu_sfsr_mask = 0xffffffff,
1204 .mmu_trcr_mask = 0xffffffff,
1205 .nwindows = 8,
1206 .features = CPU_DEFAULT_FEATURES,
1209 .name = "LEON2",
1210 .iu_version = 0xf2000000,
1211 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1212 .mmu_version = 0xf2000000,
1213 .mmu_bm = 0x00004000,
1214 .mmu_ctpr_mask = 0x007ffff0,
1215 .mmu_cxr_mask = 0x0000003f,
1216 .mmu_sfsr_mask = 0xffffffff,
1217 .mmu_trcr_mask = 0xffffffff,
1218 .nwindows = 8,
1219 .features = CPU_DEFAULT_FEATURES,
1222 .name = "LEON3",
1223 .iu_version = 0xf3000000,
1224 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1225 .mmu_version = 0xf3000000,
1226 .mmu_bm = 0x00004000,
1227 .mmu_ctpr_mask = 0x007ffff0,
1228 .mmu_cxr_mask = 0x0000003f,
1229 .mmu_sfsr_mask = 0xffffffff,
1230 .mmu_trcr_mask = 0xffffffff,
1231 .nwindows = 8,
1232 .features = CPU_DEFAULT_FEATURES,
1234 #endif
1237 static const char * const feature_name[] = {
1238 "float",
1239 "float128",
1240 "swap",
1241 "mul",
1242 "div",
1243 "flush",
1244 "fsqrt",
1245 "fmul",
1246 "vis1",
1247 "vis2",
1248 "fsmuld",
1249 "hypv",
1250 "cmt",
1251 "gl",
1254 static void print_features(FILE *f,
1255 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1256 uint32_t features, const char *prefix)
1258 unsigned int i;
1260 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1261 if (feature_name[i] && (features & (1 << i))) {
1262 if (prefix)
1263 (*cpu_fprintf)(f, "%s", prefix);
1264 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1268 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1270 unsigned int i;
1272 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1273 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1274 *features |= 1 << i;
1275 return;
1277 fprintf(stderr, "CPU feature %s not found\n", flagname);
1280 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1282 unsigned int i;
1283 const sparc_def_t *def = NULL;
1284 char *s = strdup(cpu_model);
1285 char *featurestr, *name = strtok(s, ",");
1286 uint32_t plus_features = 0;
1287 uint32_t minus_features = 0;
1288 long long iu_version;
1289 uint32_t fpu_version, mmu_version, nwindows;
1291 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1292 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1293 def = &sparc_defs[i];
1296 if (!def)
1297 goto error;
1298 memcpy(cpu_def, def, sizeof(*def));
1300 featurestr = strtok(NULL, ",");
1301 while (featurestr) {
1302 char *val;
1304 if (featurestr[0] == '+') {
1305 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1306 } else if (featurestr[0] == '-') {
1307 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1308 } else if ((val = strchr(featurestr, '='))) {
1309 *val = 0; val++;
1310 if (!strcmp(featurestr, "iu_version")) {
1311 char *err;
1313 iu_version = strtoll(val, &err, 0);
1314 if (!*val || *err) {
1315 fprintf(stderr, "bad numerical value %s\n", val);
1316 goto error;
1318 cpu_def->iu_version = iu_version;
1319 #ifdef DEBUG_FEATURES
1320 fprintf(stderr, "iu_version %llx\n", iu_version);
1321 #endif
1322 } else if (!strcmp(featurestr, "fpu_version")) {
1323 char *err;
1325 fpu_version = strtol(val, &err, 0);
1326 if (!*val || *err) {
1327 fprintf(stderr, "bad numerical value %s\n", val);
1328 goto error;
1330 cpu_def->fpu_version = fpu_version;
1331 #ifdef DEBUG_FEATURES
1332 fprintf(stderr, "fpu_version %x\n", fpu_version);
1333 #endif
1334 } else if (!strcmp(featurestr, "mmu_version")) {
1335 char *err;
1337 mmu_version = strtol(val, &err, 0);
1338 if (!*val || *err) {
1339 fprintf(stderr, "bad numerical value %s\n", val);
1340 goto error;
1342 cpu_def->mmu_version = mmu_version;
1343 #ifdef DEBUG_FEATURES
1344 fprintf(stderr, "mmu_version %x\n", mmu_version);
1345 #endif
1346 } else if (!strcmp(featurestr, "nwindows")) {
1347 char *err;
1349 nwindows = strtol(val, &err, 0);
1350 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1351 nwindows < MIN_NWINDOWS) {
1352 fprintf(stderr, "bad numerical value %s\n", val);
1353 goto error;
1355 cpu_def->nwindows = nwindows;
1356 #ifdef DEBUG_FEATURES
1357 fprintf(stderr, "nwindows %d\n", nwindows);
1358 #endif
1359 } else {
1360 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1361 goto error;
1363 } else {
1364 fprintf(stderr, "feature string `%s' not in format "
1365 "(+feature|-feature|feature=xyz)\n", featurestr);
1366 goto error;
1368 featurestr = strtok(NULL, ",");
1370 cpu_def->features |= plus_features;
1371 cpu_def->features &= ~minus_features;
1372 #ifdef DEBUG_FEATURES
1373 print_features(stderr, fprintf, cpu_def->features, NULL);
1374 #endif
1375 free(s);
1376 return 0;
1378 error:
1379 free(s);
1380 return -1;
1383 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1385 unsigned int i;
1387 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1388 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1389 sparc_defs[i].name,
1390 sparc_defs[i].iu_version,
1391 sparc_defs[i].fpu_version,
1392 sparc_defs[i].mmu_version,
1393 sparc_defs[i].nwindows);
1394 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1395 ~sparc_defs[i].features, "-");
1396 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1397 sparc_defs[i].features, "+");
1398 (*cpu_fprintf)(f, "\n");
1400 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1401 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1402 (*cpu_fprintf)(f, "\n");
1403 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1404 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1405 (*cpu_fprintf)(f, "\n");
1406 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1407 "fpu_version mmu_version nwindows\n");
1410 void cpu_dump_state(CPUState *env, FILE *f,
1411 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1412 int flags)
1414 int i, x;
1416 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1417 env->npc);
1418 cpu_fprintf(f, "General Registers:\n");
1419 for (i = 0; i < 4; i++)
1420 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1421 cpu_fprintf(f, "\n");
1422 for (; i < 8; i++)
1423 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1424 cpu_fprintf(f, "\nCurrent Register Window:\n");
1425 for (x = 0; x < 3; x++) {
1426 for (i = 0; i < 4; i++)
1427 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1428 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1429 env->regwptr[i + x * 8]);
1430 cpu_fprintf(f, "\n");
1431 for (; i < 8; i++)
1432 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1433 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1434 env->regwptr[i + x * 8]);
1435 cpu_fprintf(f, "\n");
1437 cpu_fprintf(f, "\nFloating Point Registers:\n");
1438 for (i = 0; i < 32; i++) {
1439 if ((i & 3) == 0)
1440 cpu_fprintf(f, "%%f%02d:", i);
1441 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1442 if ((i & 3) == 3)
1443 cpu_fprintf(f, "\n");
1445 #ifdef TARGET_SPARC64
1446 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1447 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1448 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1449 "cleanwin %d cwp %d\n",
1450 env->cansave, env->canrestore, env->otherwin, env->wstate,
1451 env->cleanwin, env->nwindows - 1 - env->cwp);
1452 #else
1454 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1456 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1457 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1458 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1459 env->psrs?'S':'-', env->psrps?'P':'-',
1460 env->psret?'E':'-', env->wim);
1461 #endif
1462 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);