virtio-net: fix network stall under load
[qemu/ar7.git] / target-sparc / helper.c
blobffe93e3d44dd216f9ed5798c32a05b028733b072
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 int error_code = 0, is_dirty, is_user;
111 unsigned long page_offset;
113 is_user = mmu_idx == MMU_USER_IDX;
115 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
116 // Boot mode: instruction fetches are taken from PROM
117 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
118 *physical = env->prom_addr | (address & 0x7ffffULL);
119 *prot = PAGE_READ | PAGE_EXEC;
120 return 0;
122 *physical = address;
123 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
124 return 0;
127 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
128 *physical = 0xffffffffffff0000ULL;
130 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
131 /* Context base + context number */
132 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
133 pde = ldl_phys(pde_ptr);
135 /* Ctx pde */
136 switch (pde & PTE_ENTRYTYPE_MASK) {
137 default:
138 case 0: /* Invalid */
139 return 1 << 2;
140 case 2: /* L0 PTE, maybe should not happen? */
141 case 3: /* Reserved */
142 return 4 << 2;
143 case 1: /* L0 PDE */
144 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
145 pde = ldl_phys(pde_ptr);
147 switch (pde & PTE_ENTRYTYPE_MASK) {
148 default:
149 case 0: /* Invalid */
150 return (1 << 8) | (1 << 2);
151 case 3: /* Reserved */
152 return (1 << 8) | (4 << 2);
153 case 1: /* L1 PDE */
154 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
155 pde = ldl_phys(pde_ptr);
157 switch (pde & PTE_ENTRYTYPE_MASK) {
158 default:
159 case 0: /* Invalid */
160 return (2 << 8) | (1 << 2);
161 case 3: /* Reserved */
162 return (2 << 8) | (4 << 2);
163 case 1: /* L2 PDE */
164 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
165 pde = ldl_phys(pde_ptr);
167 switch (pde & PTE_ENTRYTYPE_MASK) {
168 default:
169 case 0: /* Invalid */
170 return (3 << 8) | (1 << 2);
171 case 1: /* PDE, should not happen */
172 case 3: /* Reserved */
173 return (3 << 8) | (4 << 2);
174 case 2: /* L3 PTE */
175 page_offset = (address & TARGET_PAGE_MASK) &
176 (TARGET_PAGE_SIZE - 1);
178 break;
179 case 2: /* L2 PTE */
180 page_offset = address & 0x3ffff;
182 break;
183 case 2: /* L1 PTE */
184 page_offset = address & 0xffffff;
188 /* check access */
189 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
190 error_code = access_table[*access_index][access_perms];
191 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
192 return error_code;
194 /* update page modified and dirty bits */
195 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
196 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
197 pde |= PG_ACCESSED_MASK;
198 if (is_dirty)
199 pde |= PG_MODIFIED_MASK;
200 stl_phys_notdirty(pde_ptr, pde);
203 /* the page can be put in the TLB */
204 *prot = perm_table[is_user][access_perms];
205 if (!(pde & PG_MODIFIED_MASK)) {
206 /* only set write access if already dirty... otherwise wait
207 for dirty access */
208 *prot &= ~PAGE_WRITE;
211 /* Even if large ptes, we map only one 4KB page in the cache to
212 avoid filling it too fast */
213 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
214 return error_code;
217 /* Perform address translation */
218 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
219 int mmu_idx, int is_softmmu)
221 target_phys_addr_t paddr;
222 target_ulong vaddr;
223 int error_code = 0, prot, ret = 0, access_index;
225 error_code = get_physical_address(env, &paddr, &prot, &access_index,
226 address, rw, mmu_idx);
227 if (error_code == 0) {
228 vaddr = address & TARGET_PAGE_MASK;
229 paddr &= TARGET_PAGE_MASK;
230 #ifdef DEBUG_MMU
231 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
232 TARGET_FMT_lx "\n", address, paddr, vaddr);
233 #endif
234 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
235 return ret;
238 if (env->mmuregs[3]) /* Fault status register */
239 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
240 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
241 env->mmuregs[4] = address; /* Fault address register */
243 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
244 // No fault mode: if a mapping is available, just override
245 // permissions. If no mapping is available, redirect accesses to
246 // neverland. Fake/overridden mappings will be flushed when
247 // switching to normal mode.
248 vaddr = address & TARGET_PAGE_MASK;
249 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
250 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
251 return ret;
252 } else {
253 if (rw & 2)
254 env->exception_index = TT_TFAULT;
255 else
256 env->exception_index = TT_DFAULT;
257 return 1;
261 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
263 target_phys_addr_t pde_ptr;
264 uint32_t pde;
266 /* Context base + context number */
267 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
268 (env->mmuregs[2] << 2);
269 pde = ldl_phys(pde_ptr);
271 switch (pde & PTE_ENTRYTYPE_MASK) {
272 default:
273 case 0: /* Invalid */
274 case 2: /* PTE, maybe should not happen? */
275 case 3: /* Reserved */
276 return 0;
277 case 1: /* L1 PDE */
278 if (mmulev == 3)
279 return pde;
280 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
281 pde = ldl_phys(pde_ptr);
283 switch (pde & PTE_ENTRYTYPE_MASK) {
284 default:
285 case 0: /* Invalid */
286 case 3: /* Reserved */
287 return 0;
288 case 2: /* L1 PTE */
289 return pde;
290 case 1: /* L2 PDE */
291 if (mmulev == 2)
292 return pde;
293 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
294 pde = ldl_phys(pde_ptr);
296 switch (pde & PTE_ENTRYTYPE_MASK) {
297 default:
298 case 0: /* Invalid */
299 case 3: /* Reserved */
300 return 0;
301 case 2: /* L2 PTE */
302 return pde;
303 case 1: /* L3 PDE */
304 if (mmulev == 1)
305 return pde;
306 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
307 pde = ldl_phys(pde_ptr);
309 switch (pde & PTE_ENTRYTYPE_MASK) {
310 default:
311 case 0: /* Invalid */
312 case 1: /* PDE, should not happen */
313 case 3: /* Reserved */
314 return 0;
315 case 2: /* L3 PTE */
316 return pde;
321 return 0;
324 #ifdef DEBUG_MMU
325 void dump_mmu(CPUState *env)
327 target_ulong va, va1, va2;
328 unsigned int n, m, o;
329 target_phys_addr_t pde_ptr, pa;
330 uint32_t pde;
332 printf("MMU dump:\n");
333 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
334 pde = ldl_phys(pde_ptr);
335 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
336 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
337 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
338 pde = mmu_probe(env, va, 2);
339 if (pde) {
340 pa = cpu_get_phys_page_debug(env, va);
341 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
342 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
343 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
344 pde = mmu_probe(env, va1, 1);
345 if (pde) {
346 pa = cpu_get_phys_page_debug(env, va1);
347 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
348 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
349 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
350 pde = mmu_probe(env, va2, 0);
351 if (pde) {
352 pa = cpu_get_phys_page_debug(env, va2);
353 printf(" VA: " TARGET_FMT_lx ", PA: "
354 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
355 va2, pa, pde);
362 printf("MMU dump ends\n");
364 #endif /* DEBUG_MMU */
366 #else /* !TARGET_SPARC64 */
368 // 41 bit physical address space
369 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
371 return x & 0x1ffffffffffULL;
375 * UltraSparc IIi I/DMMUs
378 static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
380 return (x & mask) == (y & mask);
383 // Returns true if TTE tag is valid and matches virtual address value in context
384 // requires virtual address mask value calculated from TTE entry size
385 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
386 uint64_t address, uint64_t context,
387 target_phys_addr_t *physical,
388 int is_nucleus)
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 ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
411 || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag, 0x1fff))
412 && compare_masked(address, tlb->tag, mask))
414 // decode physical address
415 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
416 return 1;
419 return 0;
422 static int get_physical_address_data(CPUState *env,
423 target_phys_addr_t *physical, int *prot,
424 target_ulong address, int rw, int is_user)
426 unsigned int i;
427 uint64_t context;
428 int is_nucleus;
430 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
431 *physical = ultrasparc_truncate_physical(address);
432 *prot = PAGE_READ | PAGE_WRITE;
433 return 0;
436 context = env->dmmu.mmu_primary_context & 0x1fff;
437 is_nucleus = env->tl > 0;
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,
443 is_nucleus)) {
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;
489 int is_nucleus;
491 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
492 /* IMMU disabled */
493 *physical = ultrasparc_truncate_physical(address);
494 *prot = PAGE_EXEC;
495 return 0;
498 context = env->dmmu.mmu_primary_context & 0x1fff;
499 is_nucleus = env->tl > 0;
501 for (i = 0; i < 64; i++) {
502 // ctx match, vaddr match, valid?
503 if (ultrasparc_tag_match(&env->itlb[i],
504 address, context, physical,
505 is_nucleus)) {
506 // access ok?
507 if ((env->itlb[i].tte & 0x4) && is_user) {
508 if (env->immu.sfsr) /* Fault status register */
509 env->immu.sfsr = 2; /* overflow (not read before
510 another fault) */
511 env->immu.sfsr |= (is_user << 3) | 1;
512 env->exception_index = TT_TFAULT;
513 #ifdef DEBUG_MMU
514 printf("TFAULT at 0x%" PRIx64 "\n", address);
515 #endif
516 return 1;
518 *prot = PAGE_EXEC;
519 TTE_SET_USED(env->itlb[i].tte);
520 return 0;
523 #ifdef DEBUG_MMU
524 printf("TMISS at 0x%" PRIx64 "\n", address);
525 #endif
526 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
527 env->immu.tag_access = (address & ~0x1fffULL) | context;
528 env->exception_index = TT_TMISS;
529 return 1;
532 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
533 int *prot, int *access_index,
534 target_ulong address, int rw, int mmu_idx)
536 int is_user = mmu_idx == MMU_USER_IDX;
538 if (rw == 2)
539 return get_physical_address_code(env, physical, prot, address,
540 is_user);
541 else
542 return get_physical_address_data(env, physical, prot, address, rw,
543 is_user);
546 /* Perform address translation */
547 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
548 int mmu_idx, int is_softmmu)
550 target_ulong virt_addr, vaddr;
551 target_phys_addr_t paddr;
552 int error_code = 0, prot, ret = 0, access_index;
554 error_code = get_physical_address(env, &paddr, &prot, &access_index,
555 address, rw, mmu_idx);
556 if (error_code == 0) {
557 virt_addr = address & TARGET_PAGE_MASK;
558 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
559 (TARGET_PAGE_SIZE - 1));
560 #ifdef DEBUG_MMU
561 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
562 "\n", address, paddr, vaddr);
563 #endif
564 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
565 return ret;
567 // XXX
568 return 1;
571 #ifdef DEBUG_MMU
572 void dump_mmu(CPUState *env)
574 unsigned int i;
575 const char *mask;
577 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
578 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
579 if ((env->lsu & DMMU_E) == 0) {
580 printf("DMMU disabled\n");
581 } else {
582 printf("DMMU dump:\n");
583 for (i = 0; i < 64; i++) {
584 switch ((env->dtlb[i].tte >> 61) & 3) {
585 default:
586 case 0x0:
587 mask = " 8k";
588 break;
589 case 0x1:
590 mask = " 64k";
591 break;
592 case 0x2:
593 mask = "512k";
594 break;
595 case 0x3:
596 mask = " 4M";
597 break;
599 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
600 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
601 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
603 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
604 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
605 mask,
606 env->dtlb[i].tte & 0x4? "priv": "user",
607 env->dtlb[i].tte & 0x2? "RW": "RO",
608 env->dtlb[i].tte & 0x40? "locked": "unlocked",
609 env->dtlb[i].tag & (uint64_t)0x1fffULL,
610 TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
614 if ((env->lsu & IMMU_E) == 0) {
615 printf("IMMU disabled\n");
616 } else {
617 printf("IMMU dump:\n");
618 for (i = 0; i < 64; i++) {
619 switch ((env->itlb[i].tte >> 61) & 3) {
620 default:
621 case 0x0:
622 mask = " 8k";
623 break;
624 case 0x1:
625 mask = " 64k";
626 break;
627 case 0x2:
628 mask = "512k";
629 break;
630 case 0x3:
631 mask = " 4M";
632 break;
634 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
635 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
636 ", %s, %s, %s, ctx %" PRId64 " %s\n",
638 env->itlb[i].tag & (uint64_t)~0x1fffULL,
639 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
640 mask,
641 env->itlb[i].tte & 0x4? "priv": "user",
642 env->itlb[i].tte & 0x40? "locked": "unlocked",
643 env->itlb[i].tag & (uint64_t)0x1fffULL,
644 TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
649 #endif /* DEBUG_MMU */
651 #endif /* TARGET_SPARC64 */
652 #endif /* !CONFIG_USER_ONLY */
655 #if defined(CONFIG_USER_ONLY)
656 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
658 return addr;
661 #else
662 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
664 target_phys_addr_t phys_addr;
665 int prot, access_index;
667 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
668 MMU_KERNEL_IDX) != 0)
669 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
670 0, MMU_KERNEL_IDX) != 0)
671 return -1;
672 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
673 return -1;
674 return phys_addr;
676 #endif
678 void cpu_reset(CPUSPARCState *env)
680 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
681 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
682 log_cpu_state(env, 0);
685 tlb_flush(env, 1);
686 env->cwp = 0;
687 #ifndef TARGET_SPARC64
688 env->wim = 1;
689 #endif
690 env->regwptr = env->regbase + (env->cwp * 16);
691 CC_OP = CC_OP_FLAGS;
692 #if defined(CONFIG_USER_ONLY)
693 #ifdef TARGET_SPARC64
694 env->cleanwin = env->nwindows - 2;
695 env->cansave = env->nwindows - 2;
696 env->pstate = PS_RMO | PS_PEF | PS_IE;
697 env->asi = 0x82; // Primary no-fault
698 #endif
699 #else
700 #if !defined(TARGET_SPARC64)
701 env->psret = 0;
702 #endif
703 env->psrs = 1;
704 env->psrps = 1;
705 #ifdef TARGET_SPARC64
706 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
707 env->hpstate = HS_PRIV;
708 env->tl = env->maxtl;
709 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
710 env->lsu = 0;
711 #else
712 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
713 env->mmuregs[0] |= env->def->mmu_bm;
714 #endif
715 env->pc = 0;
716 env->npc = env->pc + 4;
717 #endif
720 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
722 sparc_def_t def1, *def = &def1;
724 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
725 return -1;
727 env->def = qemu_mallocz(sizeof(*def));
728 memcpy(env->def, def, sizeof(*def));
729 #if defined(CONFIG_USER_ONLY)
730 if ((env->def->features & CPU_FEATURE_FLOAT))
731 env->def->features |= CPU_FEATURE_FLOAT128;
732 #endif
733 env->cpu_model_str = cpu_model;
734 env->version = def->iu_version;
735 env->fsr = def->fpu_version;
736 env->nwindows = def->nwindows;
737 #if !defined(TARGET_SPARC64)
738 env->mmuregs[0] |= def->mmu_version;
739 cpu_sparc_set_id(env, 0);
740 env->mxccregs[7] |= def->mxcc_version;
741 #else
742 env->mmu_version = def->mmu_version;
743 env->maxtl = def->maxtl;
744 env->version |= def->maxtl << 8;
745 env->version |= def->nwindows - 1;
746 #endif
747 return 0;
750 static void cpu_sparc_close(CPUSPARCState *env)
752 free(env->def);
753 free(env);
756 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
758 CPUSPARCState *env;
760 env = qemu_mallocz(sizeof(CPUSPARCState));
761 cpu_exec_init(env);
763 gen_intermediate_code_init(env);
765 if (cpu_sparc_register(env, cpu_model) < 0) {
766 cpu_sparc_close(env);
767 return NULL;
769 qemu_init_vcpu(env);
771 return env;
774 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
776 #if !defined(TARGET_SPARC64)
777 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
778 #endif
781 static const sparc_def_t sparc_defs[] = {
782 #ifdef TARGET_SPARC64
784 .name = "Fujitsu Sparc64",
785 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
786 .fpu_version = 0x00000000,
787 .mmu_version = mmu_us_12,
788 .nwindows = 4,
789 .maxtl = 4,
790 .features = CPU_DEFAULT_FEATURES,
793 .name = "Fujitsu Sparc64 III",
794 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
795 .fpu_version = 0x00000000,
796 .mmu_version = mmu_us_12,
797 .nwindows = 5,
798 .maxtl = 4,
799 .features = CPU_DEFAULT_FEATURES,
802 .name = "Fujitsu Sparc64 IV",
803 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
804 .fpu_version = 0x00000000,
805 .mmu_version = mmu_us_12,
806 .nwindows = 8,
807 .maxtl = 5,
808 .features = CPU_DEFAULT_FEATURES,
811 .name = "Fujitsu Sparc64 V",
812 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
813 .fpu_version = 0x00000000,
814 .mmu_version = mmu_us_12,
815 .nwindows = 8,
816 .maxtl = 5,
817 .features = CPU_DEFAULT_FEATURES,
820 .name = "TI UltraSparc I",
821 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
822 .fpu_version = 0x00000000,
823 .mmu_version = mmu_us_12,
824 .nwindows = 8,
825 .maxtl = 5,
826 .features = CPU_DEFAULT_FEATURES,
829 .name = "TI UltraSparc II",
830 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
831 .fpu_version = 0x00000000,
832 .mmu_version = mmu_us_12,
833 .nwindows = 8,
834 .maxtl = 5,
835 .features = CPU_DEFAULT_FEATURES,
838 .name = "TI UltraSparc IIi",
839 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
840 .fpu_version = 0x00000000,
841 .mmu_version = mmu_us_12,
842 .nwindows = 8,
843 .maxtl = 5,
844 .features = CPU_DEFAULT_FEATURES,
847 .name = "TI UltraSparc IIe",
848 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
849 .fpu_version = 0x00000000,
850 .mmu_version = mmu_us_12,
851 .nwindows = 8,
852 .maxtl = 5,
853 .features = CPU_DEFAULT_FEATURES,
856 .name = "Sun UltraSparc III",
857 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
858 .fpu_version = 0x00000000,
859 .mmu_version = mmu_us_12,
860 .nwindows = 8,
861 .maxtl = 5,
862 .features = CPU_DEFAULT_FEATURES,
865 .name = "Sun UltraSparc III Cu",
866 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
867 .fpu_version = 0x00000000,
868 .mmu_version = mmu_us_3,
869 .nwindows = 8,
870 .maxtl = 5,
871 .features = CPU_DEFAULT_FEATURES,
874 .name = "Sun UltraSparc IIIi",
875 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
876 .fpu_version = 0x00000000,
877 .mmu_version = mmu_us_12,
878 .nwindows = 8,
879 .maxtl = 5,
880 .features = CPU_DEFAULT_FEATURES,
883 .name = "Sun UltraSparc IV",
884 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
885 .fpu_version = 0x00000000,
886 .mmu_version = mmu_us_4,
887 .nwindows = 8,
888 .maxtl = 5,
889 .features = CPU_DEFAULT_FEATURES,
892 .name = "Sun UltraSparc IV+",
893 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
894 .fpu_version = 0x00000000,
895 .mmu_version = mmu_us_12,
896 .nwindows = 8,
897 .maxtl = 5,
898 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
901 .name = "Sun UltraSparc IIIi+",
902 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
903 .fpu_version = 0x00000000,
904 .mmu_version = mmu_us_3,
905 .nwindows = 8,
906 .maxtl = 5,
907 .features = CPU_DEFAULT_FEATURES,
910 .name = "Sun UltraSparc T1",
911 // defined in sparc_ifu_fdp.v and ctu.h
912 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
913 .fpu_version = 0x00000000,
914 .mmu_version = mmu_sun4v,
915 .nwindows = 8,
916 .maxtl = 6,
917 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
918 | CPU_FEATURE_GL,
921 .name = "Sun UltraSparc T2",
922 // defined in tlu_asi_ctl.v and n2_revid_cust.v
923 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
924 .fpu_version = 0x00000000,
925 .mmu_version = mmu_sun4v,
926 .nwindows = 8,
927 .maxtl = 6,
928 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
929 | CPU_FEATURE_GL,
932 .name = "NEC UltraSparc I",
933 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
934 .fpu_version = 0x00000000,
935 .mmu_version = mmu_us_12,
936 .nwindows = 8,
937 .maxtl = 5,
938 .features = CPU_DEFAULT_FEATURES,
940 #else
942 .name = "Fujitsu MB86900",
943 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
944 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
945 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
946 .mmu_bm = 0x00004000,
947 .mmu_ctpr_mask = 0x007ffff0,
948 .mmu_cxr_mask = 0x0000003f,
949 .mmu_sfsr_mask = 0xffffffff,
950 .mmu_trcr_mask = 0xffffffff,
951 .nwindows = 7,
952 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
955 .name = "Fujitsu MB86904",
956 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
957 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
958 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
959 .mmu_bm = 0x00004000,
960 .mmu_ctpr_mask = 0x00ffffc0,
961 .mmu_cxr_mask = 0x000000ff,
962 .mmu_sfsr_mask = 0x00016fff,
963 .mmu_trcr_mask = 0x00ffffff,
964 .nwindows = 8,
965 .features = CPU_DEFAULT_FEATURES,
968 .name = "Fujitsu MB86907",
969 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
970 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
971 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
972 .mmu_bm = 0x00004000,
973 .mmu_ctpr_mask = 0xffffffc0,
974 .mmu_cxr_mask = 0x000000ff,
975 .mmu_sfsr_mask = 0x00016fff,
976 .mmu_trcr_mask = 0xffffffff,
977 .nwindows = 8,
978 .features = CPU_DEFAULT_FEATURES,
981 .name = "LSI L64811",
982 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
983 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
984 .mmu_version = 0x10 << 24,
985 .mmu_bm = 0x00004000,
986 .mmu_ctpr_mask = 0x007ffff0,
987 .mmu_cxr_mask = 0x0000003f,
988 .mmu_sfsr_mask = 0xffffffff,
989 .mmu_trcr_mask = 0xffffffff,
990 .nwindows = 8,
991 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
992 CPU_FEATURE_FSMULD,
995 .name = "Cypress CY7C601",
996 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
997 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
998 .mmu_version = 0x10 << 24,
999 .mmu_bm = 0x00004000,
1000 .mmu_ctpr_mask = 0x007ffff0,
1001 .mmu_cxr_mask = 0x0000003f,
1002 .mmu_sfsr_mask = 0xffffffff,
1003 .mmu_trcr_mask = 0xffffffff,
1004 .nwindows = 8,
1005 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1006 CPU_FEATURE_FSMULD,
1009 .name = "Cypress CY7C611",
1010 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1011 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1012 .mmu_version = 0x10 << 24,
1013 .mmu_bm = 0x00004000,
1014 .mmu_ctpr_mask = 0x007ffff0,
1015 .mmu_cxr_mask = 0x0000003f,
1016 .mmu_sfsr_mask = 0xffffffff,
1017 .mmu_trcr_mask = 0xffffffff,
1018 .nwindows = 8,
1019 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1020 CPU_FEATURE_FSMULD,
1023 .name = "TI MicroSparc I",
1024 .iu_version = 0x41000000,
1025 .fpu_version = 4 << 17,
1026 .mmu_version = 0x41000000,
1027 .mmu_bm = 0x00004000,
1028 .mmu_ctpr_mask = 0x007ffff0,
1029 .mmu_cxr_mask = 0x0000003f,
1030 .mmu_sfsr_mask = 0x00016fff,
1031 .mmu_trcr_mask = 0x0000003f,
1032 .nwindows = 7,
1033 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1034 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1035 CPU_FEATURE_FMUL,
1038 .name = "TI MicroSparc II",
1039 .iu_version = 0x42000000,
1040 .fpu_version = 4 << 17,
1041 .mmu_version = 0x02000000,
1042 .mmu_bm = 0x00004000,
1043 .mmu_ctpr_mask = 0x00ffffc0,
1044 .mmu_cxr_mask = 0x000000ff,
1045 .mmu_sfsr_mask = 0x00016fff,
1046 .mmu_trcr_mask = 0x00ffffff,
1047 .nwindows = 8,
1048 .features = CPU_DEFAULT_FEATURES,
1051 .name = "TI MicroSparc IIep",
1052 .iu_version = 0x42000000,
1053 .fpu_version = 4 << 17,
1054 .mmu_version = 0x04000000,
1055 .mmu_bm = 0x00004000,
1056 .mmu_ctpr_mask = 0x00ffffc0,
1057 .mmu_cxr_mask = 0x000000ff,
1058 .mmu_sfsr_mask = 0x00016bff,
1059 .mmu_trcr_mask = 0x00ffffff,
1060 .nwindows = 8,
1061 .features = CPU_DEFAULT_FEATURES,
1064 .name = "TI SuperSparc 40", // STP1020NPGA
1065 .iu_version = 0x41000000, // SuperSPARC 2.x
1066 .fpu_version = 0 << 17,
1067 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1068 .mmu_bm = 0x00002000,
1069 .mmu_ctpr_mask = 0xffffffc0,
1070 .mmu_cxr_mask = 0x0000ffff,
1071 .mmu_sfsr_mask = 0xffffffff,
1072 .mmu_trcr_mask = 0xffffffff,
1073 .nwindows = 8,
1074 .features = CPU_DEFAULT_FEATURES,
1077 .name = "TI SuperSparc 50", // STP1020PGA
1078 .iu_version = 0x40000000, // SuperSPARC 3.x
1079 .fpu_version = 0 << 17,
1080 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1081 .mmu_bm = 0x00002000,
1082 .mmu_ctpr_mask = 0xffffffc0,
1083 .mmu_cxr_mask = 0x0000ffff,
1084 .mmu_sfsr_mask = 0xffffffff,
1085 .mmu_trcr_mask = 0xffffffff,
1086 .nwindows = 8,
1087 .features = CPU_DEFAULT_FEATURES,
1090 .name = "TI SuperSparc 51",
1091 .iu_version = 0x40000000, // SuperSPARC 3.x
1092 .fpu_version = 0 << 17,
1093 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1094 .mmu_bm = 0x00002000,
1095 .mmu_ctpr_mask = 0xffffffc0,
1096 .mmu_cxr_mask = 0x0000ffff,
1097 .mmu_sfsr_mask = 0xffffffff,
1098 .mmu_trcr_mask = 0xffffffff,
1099 .mxcc_version = 0x00000104,
1100 .nwindows = 8,
1101 .features = CPU_DEFAULT_FEATURES,
1104 .name = "TI SuperSparc 60", // STP1020APGA
1105 .iu_version = 0x40000000, // SuperSPARC 3.x
1106 .fpu_version = 0 << 17,
1107 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1108 .mmu_bm = 0x00002000,
1109 .mmu_ctpr_mask = 0xffffffc0,
1110 .mmu_cxr_mask = 0x0000ffff,
1111 .mmu_sfsr_mask = 0xffffffff,
1112 .mmu_trcr_mask = 0xffffffff,
1113 .nwindows = 8,
1114 .features = CPU_DEFAULT_FEATURES,
1117 .name = "TI SuperSparc 61",
1118 .iu_version = 0x44000000, // SuperSPARC 3.x
1119 .fpu_version = 0 << 17,
1120 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1121 .mmu_bm = 0x00002000,
1122 .mmu_ctpr_mask = 0xffffffc0,
1123 .mmu_cxr_mask = 0x0000ffff,
1124 .mmu_sfsr_mask = 0xffffffff,
1125 .mmu_trcr_mask = 0xffffffff,
1126 .mxcc_version = 0x00000104,
1127 .nwindows = 8,
1128 .features = CPU_DEFAULT_FEATURES,
1131 .name = "TI SuperSparc II",
1132 .iu_version = 0x40000000, // SuperSPARC II 1.x
1133 .fpu_version = 0 << 17,
1134 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1135 .mmu_bm = 0x00002000,
1136 .mmu_ctpr_mask = 0xffffffc0,
1137 .mmu_cxr_mask = 0x0000ffff,
1138 .mmu_sfsr_mask = 0xffffffff,
1139 .mmu_trcr_mask = 0xffffffff,
1140 .mxcc_version = 0x00000104,
1141 .nwindows = 8,
1142 .features = CPU_DEFAULT_FEATURES,
1145 .name = "Ross RT625",
1146 .iu_version = 0x1e000000,
1147 .fpu_version = 1 << 17,
1148 .mmu_version = 0x1e000000,
1149 .mmu_bm = 0x00004000,
1150 .mmu_ctpr_mask = 0x007ffff0,
1151 .mmu_cxr_mask = 0x0000003f,
1152 .mmu_sfsr_mask = 0xffffffff,
1153 .mmu_trcr_mask = 0xffffffff,
1154 .nwindows = 8,
1155 .features = CPU_DEFAULT_FEATURES,
1158 .name = "Ross RT620",
1159 .iu_version = 0x1f000000,
1160 .fpu_version = 1 << 17,
1161 .mmu_version = 0x1f000000,
1162 .mmu_bm = 0x00004000,
1163 .mmu_ctpr_mask = 0x007ffff0,
1164 .mmu_cxr_mask = 0x0000003f,
1165 .mmu_sfsr_mask = 0xffffffff,
1166 .mmu_trcr_mask = 0xffffffff,
1167 .nwindows = 8,
1168 .features = CPU_DEFAULT_FEATURES,
1171 .name = "BIT B5010",
1172 .iu_version = 0x20000000,
1173 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1174 .mmu_version = 0x20000000,
1175 .mmu_bm = 0x00004000,
1176 .mmu_ctpr_mask = 0x007ffff0,
1177 .mmu_cxr_mask = 0x0000003f,
1178 .mmu_sfsr_mask = 0xffffffff,
1179 .mmu_trcr_mask = 0xffffffff,
1180 .nwindows = 8,
1181 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1182 CPU_FEATURE_FSMULD,
1185 .name = "Matsushita MN10501",
1186 .iu_version = 0x50000000,
1187 .fpu_version = 0 << 17,
1188 .mmu_version = 0x50000000,
1189 .mmu_bm = 0x00004000,
1190 .mmu_ctpr_mask = 0x007ffff0,
1191 .mmu_cxr_mask = 0x0000003f,
1192 .mmu_sfsr_mask = 0xffffffff,
1193 .mmu_trcr_mask = 0xffffffff,
1194 .nwindows = 8,
1195 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1196 CPU_FEATURE_FSMULD,
1199 .name = "Weitek W8601",
1200 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1201 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1202 .mmu_version = 0x10 << 24,
1203 .mmu_bm = 0x00004000,
1204 .mmu_ctpr_mask = 0x007ffff0,
1205 .mmu_cxr_mask = 0x0000003f,
1206 .mmu_sfsr_mask = 0xffffffff,
1207 .mmu_trcr_mask = 0xffffffff,
1208 .nwindows = 8,
1209 .features = CPU_DEFAULT_FEATURES,
1212 .name = "LEON2",
1213 .iu_version = 0xf2000000,
1214 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1215 .mmu_version = 0xf2000000,
1216 .mmu_bm = 0x00004000,
1217 .mmu_ctpr_mask = 0x007ffff0,
1218 .mmu_cxr_mask = 0x0000003f,
1219 .mmu_sfsr_mask = 0xffffffff,
1220 .mmu_trcr_mask = 0xffffffff,
1221 .nwindows = 8,
1222 .features = CPU_DEFAULT_FEATURES,
1225 .name = "LEON3",
1226 .iu_version = 0xf3000000,
1227 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1228 .mmu_version = 0xf3000000,
1229 .mmu_bm = 0x00004000,
1230 .mmu_ctpr_mask = 0x007ffff0,
1231 .mmu_cxr_mask = 0x0000003f,
1232 .mmu_sfsr_mask = 0xffffffff,
1233 .mmu_trcr_mask = 0xffffffff,
1234 .nwindows = 8,
1235 .features = CPU_DEFAULT_FEATURES,
1237 #endif
1240 static const char * const feature_name[] = {
1241 "float",
1242 "float128",
1243 "swap",
1244 "mul",
1245 "div",
1246 "flush",
1247 "fsqrt",
1248 "fmul",
1249 "vis1",
1250 "vis2",
1251 "fsmuld",
1252 "hypv",
1253 "cmt",
1254 "gl",
1257 static void print_features(FILE *f,
1258 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1259 uint32_t features, const char *prefix)
1261 unsigned int i;
1263 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1264 if (feature_name[i] && (features & (1 << i))) {
1265 if (prefix)
1266 (*cpu_fprintf)(f, "%s", prefix);
1267 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1271 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1273 unsigned int i;
1275 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1276 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1277 *features |= 1 << i;
1278 return;
1280 fprintf(stderr, "CPU feature %s not found\n", flagname);
1283 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1285 unsigned int i;
1286 const sparc_def_t *def = NULL;
1287 char *s = strdup(cpu_model);
1288 char *featurestr, *name = strtok(s, ",");
1289 uint32_t plus_features = 0;
1290 uint32_t minus_features = 0;
1291 long long iu_version;
1292 uint32_t fpu_version, mmu_version, nwindows;
1294 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1295 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1296 def = &sparc_defs[i];
1299 if (!def)
1300 goto error;
1301 memcpy(cpu_def, def, sizeof(*def));
1303 featurestr = strtok(NULL, ",");
1304 while (featurestr) {
1305 char *val;
1307 if (featurestr[0] == '+') {
1308 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1309 } else if (featurestr[0] == '-') {
1310 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1311 } else if ((val = strchr(featurestr, '='))) {
1312 *val = 0; val++;
1313 if (!strcmp(featurestr, "iu_version")) {
1314 char *err;
1316 iu_version = strtoll(val, &err, 0);
1317 if (!*val || *err) {
1318 fprintf(stderr, "bad numerical value %s\n", val);
1319 goto error;
1321 cpu_def->iu_version = iu_version;
1322 #ifdef DEBUG_FEATURES
1323 fprintf(stderr, "iu_version %llx\n", iu_version);
1324 #endif
1325 } else if (!strcmp(featurestr, "fpu_version")) {
1326 char *err;
1328 fpu_version = strtol(val, &err, 0);
1329 if (!*val || *err) {
1330 fprintf(stderr, "bad numerical value %s\n", val);
1331 goto error;
1333 cpu_def->fpu_version = fpu_version;
1334 #ifdef DEBUG_FEATURES
1335 fprintf(stderr, "fpu_version %x\n", fpu_version);
1336 #endif
1337 } else if (!strcmp(featurestr, "mmu_version")) {
1338 char *err;
1340 mmu_version = strtol(val, &err, 0);
1341 if (!*val || *err) {
1342 fprintf(stderr, "bad numerical value %s\n", val);
1343 goto error;
1345 cpu_def->mmu_version = mmu_version;
1346 #ifdef DEBUG_FEATURES
1347 fprintf(stderr, "mmu_version %x\n", mmu_version);
1348 #endif
1349 } else if (!strcmp(featurestr, "nwindows")) {
1350 char *err;
1352 nwindows = strtol(val, &err, 0);
1353 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1354 nwindows < MIN_NWINDOWS) {
1355 fprintf(stderr, "bad numerical value %s\n", val);
1356 goto error;
1358 cpu_def->nwindows = nwindows;
1359 #ifdef DEBUG_FEATURES
1360 fprintf(stderr, "nwindows %d\n", nwindows);
1361 #endif
1362 } else {
1363 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1364 goto error;
1366 } else {
1367 fprintf(stderr, "feature string `%s' not in format "
1368 "(+feature|-feature|feature=xyz)\n", featurestr);
1369 goto error;
1371 featurestr = strtok(NULL, ",");
1373 cpu_def->features |= plus_features;
1374 cpu_def->features &= ~minus_features;
1375 #ifdef DEBUG_FEATURES
1376 print_features(stderr, fprintf, cpu_def->features, NULL);
1377 #endif
1378 free(s);
1379 return 0;
1381 error:
1382 free(s);
1383 return -1;
1386 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1388 unsigned int i;
1390 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1391 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1392 sparc_defs[i].name,
1393 sparc_defs[i].iu_version,
1394 sparc_defs[i].fpu_version,
1395 sparc_defs[i].mmu_version,
1396 sparc_defs[i].nwindows);
1397 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1398 ~sparc_defs[i].features, "-");
1399 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1400 sparc_defs[i].features, "+");
1401 (*cpu_fprintf)(f, "\n");
1403 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1404 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1405 (*cpu_fprintf)(f, "\n");
1406 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1407 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1408 (*cpu_fprintf)(f, "\n");
1409 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1410 "fpu_version mmu_version nwindows\n");
1413 static void cpu_print_cc(FILE *f,
1414 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1415 uint32_t cc)
1417 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1418 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1419 cc & PSR_CARRY? 'C' : '-');
1422 #ifdef TARGET_SPARC64
1423 #define REGS_PER_LINE 4
1424 #else
1425 #define REGS_PER_LINE 8
1426 #endif
1428 void cpu_dump_state(CPUState *env, FILE *f,
1429 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1430 int flags)
1432 int i, x;
1434 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1435 env->npc);
1436 cpu_fprintf(f, "General Registers:\n");
1438 for (i = 0; i < 8; i++) {
1439 if (i % REGS_PER_LINE == 0) {
1440 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1442 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1443 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1444 cpu_fprintf(f, "\n");
1447 cpu_fprintf(f, "\nCurrent Register Window:\n");
1448 for (x = 0; x < 3; x++) {
1449 for (i = 0; i < 8; i++) {
1450 if (i % REGS_PER_LINE == 0) {
1451 cpu_fprintf(f, "%%%c%d-%d: ",
1452 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1453 i, i + REGS_PER_LINE - 1);
1455 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1456 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1457 cpu_fprintf(f, "\n");
1461 cpu_fprintf(f, "\nFloating Point Registers:\n");
1462 for (i = 0; i < TARGET_FPREGS; i++) {
1463 if ((i & 3) == 0)
1464 cpu_fprintf(f, "%%f%02d:", i);
1465 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1466 if ((i & 3) == 3)
1467 cpu_fprintf(f, "\n");
1469 #ifdef TARGET_SPARC64
1470 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1471 GET_CCR(env));
1472 cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << PSR_CARRY_SHIFT);
1473 cpu_fprintf(f, " xcc: ");
1474 cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << (PSR_CARRY_SHIFT - 4));
1475 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1476 env->psrpil);
1477 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1478 "cleanwin: %d cwp: %d\n",
1479 env->cansave, env->canrestore, env->otherwin, env->wstate,
1480 env->cleanwin, env->nwindows - 1 - env->cwp);
1481 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1482 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1483 #else
1484 cpu_fprintf(f, "psr: %08x (icc: ", GET_PSR(env));
1485 cpu_print_cc(f, cpu_fprintf, GET_PSR(env));
1486 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1487 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1488 env->wim);
1489 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1490 env->fsr, env->y);
1491 #endif