New API for asynchronous monitor commands
[qemu.git] / target-sparc / helper.c
blobb5b4e7ca7401e82c48e3d4153f650a9431db5df7
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 /* update page modified and dirty bits */
189 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
190 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
191 pde |= PG_ACCESSED_MASK;
192 if (is_dirty)
193 pde |= PG_MODIFIED_MASK;
194 stl_phys_notdirty(pde_ptr, pde);
196 /* check access */
197 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
198 error_code = access_table[*access_index][access_perms];
199 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
200 return error_code;
202 /* the page can be put in the TLB */
203 *prot = perm_table[is_user][access_perms];
204 if (!(pde & PG_MODIFIED_MASK)) {
205 /* only set write access if already dirty... otherwise wait
206 for dirty access */
207 *prot &= ~PAGE_WRITE;
210 /* Even if large ptes, we map only one 4KB page in the cache to
211 avoid filling it too fast */
212 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
213 return error_code;
216 /* Perform address translation */
217 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
218 int mmu_idx, int is_softmmu)
220 target_phys_addr_t paddr;
221 target_ulong vaddr;
222 int error_code = 0, prot, ret = 0, access_index;
224 error_code = get_physical_address(env, &paddr, &prot, &access_index,
225 address, rw, mmu_idx);
226 if (error_code == 0) {
227 vaddr = address & TARGET_PAGE_MASK;
228 paddr &= TARGET_PAGE_MASK;
229 #ifdef DEBUG_MMU
230 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
231 TARGET_FMT_lx "\n", address, paddr, vaddr);
232 #endif
233 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
234 return ret;
237 if (env->mmuregs[3]) /* Fault status register */
238 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
239 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
240 env->mmuregs[4] = address; /* Fault address register */
242 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
243 // No fault mode: if a mapping is available, just override
244 // permissions. If no mapping is available, redirect accesses to
245 // neverland. Fake/overridden mappings will be flushed when
246 // switching to normal mode.
247 vaddr = address & TARGET_PAGE_MASK;
248 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
249 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
250 return ret;
251 } else {
252 if (rw & 2)
253 env->exception_index = TT_TFAULT;
254 else
255 env->exception_index = TT_DFAULT;
256 return 1;
260 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
262 target_phys_addr_t pde_ptr;
263 uint32_t pde;
265 /* Context base + context number */
266 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
267 (env->mmuregs[2] << 2);
268 pde = ldl_phys(pde_ptr);
270 switch (pde & PTE_ENTRYTYPE_MASK) {
271 default:
272 case 0: /* Invalid */
273 case 2: /* PTE, maybe should not happen? */
274 case 3: /* Reserved */
275 return 0;
276 case 1: /* L1 PDE */
277 if (mmulev == 3)
278 return pde;
279 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
280 pde = ldl_phys(pde_ptr);
282 switch (pde & PTE_ENTRYTYPE_MASK) {
283 default:
284 case 0: /* Invalid */
285 case 3: /* Reserved */
286 return 0;
287 case 2: /* L1 PTE */
288 return pde;
289 case 1: /* L2 PDE */
290 if (mmulev == 2)
291 return pde;
292 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
293 pde = ldl_phys(pde_ptr);
295 switch (pde & PTE_ENTRYTYPE_MASK) {
296 default:
297 case 0: /* Invalid */
298 case 3: /* Reserved */
299 return 0;
300 case 2: /* L2 PTE */
301 return pde;
302 case 1: /* L3 PDE */
303 if (mmulev == 1)
304 return pde;
305 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
306 pde = ldl_phys(pde_ptr);
308 switch (pde & PTE_ENTRYTYPE_MASK) {
309 default:
310 case 0: /* Invalid */
311 case 1: /* PDE, should not happen */
312 case 3: /* Reserved */
313 return 0;
314 case 2: /* L3 PTE */
315 return pde;
320 return 0;
323 #ifdef DEBUG_MMU
324 void dump_mmu(CPUState *env)
326 target_ulong va, va1, va2;
327 unsigned int n, m, o;
328 target_phys_addr_t pde_ptr, pa;
329 uint32_t pde;
331 printf("MMU dump:\n");
332 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
333 pde = ldl_phys(pde_ptr);
334 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
335 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
336 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
337 pde = mmu_probe(env, va, 2);
338 if (pde) {
339 pa = cpu_get_phys_page_debug(env, va);
340 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
341 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
342 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
343 pde = mmu_probe(env, va1, 1);
344 if (pde) {
345 pa = cpu_get_phys_page_debug(env, va1);
346 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
347 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
348 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
349 pde = mmu_probe(env, va2, 0);
350 if (pde) {
351 pa = cpu_get_phys_page_debug(env, va2);
352 printf(" VA: " TARGET_FMT_lx ", PA: "
353 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
354 va2, pa, pde);
361 printf("MMU dump ends\n");
363 #endif /* DEBUG_MMU */
365 #else /* !TARGET_SPARC64 */
367 // 41 bit physical address space
368 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
370 return x & 0x1ffffffffffULL;
374 * UltraSparc IIi I/DMMUs
377 static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
379 return (x & mask) == (y & mask);
382 // Returns true if TTE tag is valid and matches virtual address value in context
383 // requires virtual address mask value calculated from TTE entry size
384 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
385 uint64_t address, uint64_t context,
386 target_phys_addr_t *physical,
387 int is_nucleus)
389 uint64_t mask;
391 switch ((tlb->tte >> 61) & 3) {
392 default:
393 case 0x0: // 8k
394 mask = 0xffffffffffffe000ULL;
395 break;
396 case 0x1: // 64k
397 mask = 0xffffffffffff0000ULL;
398 break;
399 case 0x2: // 512k
400 mask = 0xfffffffffff80000ULL;
401 break;
402 case 0x3: // 4M
403 mask = 0xffffffffffc00000ULL;
404 break;
407 // valid, context match, virtual address match?
408 if (TTE_IS_VALID(tlb->tte) &&
409 ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
410 || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag, 0x1fff))
411 && compare_masked(address, tlb->tag, mask))
413 // decode physical address
414 *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
415 return 1;
418 return 0;
421 static int get_physical_address_data(CPUState *env,
422 target_phys_addr_t *physical, int *prot,
423 target_ulong address, int rw, int is_user)
425 unsigned int i;
426 uint64_t context;
427 int is_nucleus;
429 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
430 *physical = ultrasparc_truncate_physical(address);
431 *prot = PAGE_READ | PAGE_WRITE;
432 return 0;
435 context = env->dmmu.mmu_primary_context & 0x1fff;
436 is_nucleus = env->tl > 0;
438 for (i = 0; i < 64; i++) {
439 // ctx match, vaddr match, valid?
440 if (ultrasparc_tag_match(&env->dtlb[i],
441 address, context, physical,
442 is_nucleus)) {
443 // access ok?
444 if (((env->dtlb[i].tte & 0x4) && is_user) ||
445 (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
446 uint8_t fault_type = 0;
448 if ((env->dtlb[i].tte & 0x4) && is_user) {
449 fault_type |= 1; /* privilege violation */
452 if (env->dmmu.sfsr & 1) /* Fault status register */
453 env->dmmu.sfsr = 2; /* overflow (not read before
454 another fault) */
456 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
458 env->dmmu.sfsr |= (fault_type << 7);
460 env->dmmu.sfar = address; /* Fault address register */
461 env->exception_index = TT_DFAULT;
462 #ifdef DEBUG_MMU
463 printf("DFAULT at 0x%" PRIx64 "\n", address);
464 #endif
465 return 1;
467 *prot = PAGE_READ;
468 if (env->dtlb[i].tte & 0x2)
469 *prot |= PAGE_WRITE;
470 TTE_SET_USED(env->dtlb[i].tte);
471 return 0;
474 #ifdef DEBUG_MMU
475 printf("DMISS at 0x%" PRIx64 "\n", address);
476 #endif
477 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
478 env->exception_index = TT_DMISS;
479 return 1;
482 static int get_physical_address_code(CPUState *env,
483 target_phys_addr_t *physical, int *prot,
484 target_ulong address, int is_user)
486 unsigned int i;
487 uint64_t context;
488 int is_nucleus;
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;
498 is_nucleus = env->tl > 0;
500 for (i = 0; i < 64; i++) {
501 // ctx match, vaddr match, valid?
502 if (ultrasparc_tag_match(&env->itlb[i],
503 address, context, physical,
504 is_nucleus)) {
505 // access ok?
506 if ((env->itlb[i].tte & 0x4) && is_user) {
507 if (env->immu.sfsr) /* Fault status register */
508 env->immu.sfsr = 2; /* overflow (not read before
509 another fault) */
510 env->immu.sfsr |= (is_user << 3) | 1;
511 env->exception_index = TT_TFAULT;
512 #ifdef DEBUG_MMU
513 printf("TFAULT at 0x%" PRIx64 "\n", address);
514 #endif
515 return 1;
517 *prot = PAGE_EXEC;
518 TTE_SET_USED(env->itlb[i].tte);
519 return 0;
522 #ifdef DEBUG_MMU
523 printf("TMISS at 0x%" PRIx64 "\n", address);
524 #endif
525 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
526 env->immu.tag_access = (address & ~0x1fffULL) | context;
527 env->exception_index = TT_TMISS;
528 return 1;
531 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
532 int *prot, int *access_index,
533 target_ulong address, int rw, int mmu_idx)
535 int is_user = mmu_idx == MMU_USER_IDX;
537 if (rw == 2)
538 return get_physical_address_code(env, physical, prot, address,
539 is_user);
540 else
541 return get_physical_address_data(env, physical, prot, address, rw,
542 is_user);
545 /* Perform address translation */
546 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
547 int mmu_idx, int is_softmmu)
549 target_ulong virt_addr, vaddr;
550 target_phys_addr_t paddr;
551 int error_code = 0, prot, ret = 0, access_index;
553 error_code = get_physical_address(env, &paddr, &prot, &access_index,
554 address, rw, mmu_idx);
555 if (error_code == 0) {
556 virt_addr = address & TARGET_PAGE_MASK;
557 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
558 (TARGET_PAGE_SIZE - 1));
559 #ifdef DEBUG_MMU
560 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
561 "\n", address, paddr, vaddr);
562 #endif
563 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
564 return ret;
566 // XXX
567 return 1;
570 #ifdef DEBUG_MMU
571 void dump_mmu(CPUState *env)
573 unsigned int i;
574 const char *mask;
576 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
577 env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
578 if ((env->lsu & DMMU_E) == 0) {
579 printf("DMMU disabled\n");
580 } else {
581 printf("DMMU dump:\n");
582 for (i = 0; i < 64; i++) {
583 switch ((env->dtlb[i].tte >> 61) & 3) {
584 default:
585 case 0x0:
586 mask = " 8k";
587 break;
588 case 0x1:
589 mask = " 64k";
590 break;
591 case 0x2:
592 mask = "512k";
593 break;
594 case 0x3:
595 mask = " 4M";
596 break;
598 if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
599 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
600 ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
602 env->dtlb[i].tag & (uint64_t)~0x1fffULL,
603 env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
604 mask,
605 env->dtlb[i].tte & 0x4? "priv": "user",
606 env->dtlb[i].tte & 0x2? "RW": "RO",
607 env->dtlb[i].tte & 0x40? "locked": "unlocked",
608 env->dtlb[i].tag & (uint64_t)0x1fffULL,
609 TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
613 if ((env->lsu & IMMU_E) == 0) {
614 printf("IMMU disabled\n");
615 } else {
616 printf("IMMU dump:\n");
617 for (i = 0; i < 64; i++) {
618 switch ((env->itlb[i].tte >> 61) & 3) {
619 default:
620 case 0x0:
621 mask = " 8k";
622 break;
623 case 0x1:
624 mask = " 64k";
625 break;
626 case 0x2:
627 mask = "512k";
628 break;
629 case 0x3:
630 mask = " 4M";
631 break;
633 if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
634 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
635 ", %s, %s, %s, ctx %" PRId64 " %s\n",
637 env->itlb[i].tag & (uint64_t)~0x1fffULL,
638 env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
639 mask,
640 env->itlb[i].tte & 0x4? "priv": "user",
641 env->itlb[i].tte & 0x40? "locked": "unlocked",
642 env->itlb[i].tag & (uint64_t)0x1fffULL,
643 TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
648 #endif /* DEBUG_MMU */
650 #endif /* TARGET_SPARC64 */
651 #endif /* !CONFIG_USER_ONLY */
654 #if defined(CONFIG_USER_ONLY)
655 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
657 return addr;
660 #else
661 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
663 target_phys_addr_t phys_addr;
664 int prot, access_index;
666 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
667 MMU_KERNEL_IDX) != 0)
668 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
669 0, MMU_KERNEL_IDX) != 0)
670 return -1;
671 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
672 return -1;
673 return phys_addr;
675 #endif
677 void cpu_reset(CPUSPARCState *env)
679 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
680 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
681 log_cpu_state(env, 0);
684 tlb_flush(env, 1);
685 env->cwp = 0;
686 #ifndef TARGET_SPARC64
687 env->wim = 1;
688 #endif
689 env->regwptr = env->regbase + (env->cwp * 16);
690 CC_OP = CC_OP_FLAGS;
691 #if defined(CONFIG_USER_ONLY)
692 #ifdef TARGET_SPARC64
693 env->cleanwin = env->nwindows - 2;
694 env->cansave = env->nwindows - 2;
695 env->pstate = PS_RMO | PS_PEF | PS_IE;
696 env->asi = 0x82; // Primary no-fault
697 #endif
698 #else
699 #if !defined(TARGET_SPARC64)
700 env->psret = 0;
701 #endif
702 env->psrs = 1;
703 env->psrps = 1;
704 #ifdef TARGET_SPARC64
705 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
706 env->hpstate = HS_PRIV;
707 env->tl = env->maxtl;
708 cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
709 env->lsu = 0;
710 #else
711 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
712 env->mmuregs[0] |= env->def->mmu_bm;
713 #endif
714 env->pc = 0;
715 env->npc = env->pc + 4;
716 #endif
719 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
721 sparc_def_t def1, *def = &def1;
723 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
724 return -1;
726 env->def = qemu_mallocz(sizeof(*def));
727 memcpy(env->def, def, sizeof(*def));
728 #if defined(CONFIG_USER_ONLY)
729 if ((env->def->features & CPU_FEATURE_FLOAT))
730 env->def->features |= CPU_FEATURE_FLOAT128;
731 #endif
732 env->cpu_model_str = cpu_model;
733 env->version = def->iu_version;
734 env->fsr = def->fpu_version;
735 env->nwindows = def->nwindows;
736 #if !defined(TARGET_SPARC64)
737 env->mmuregs[0] |= def->mmu_version;
738 cpu_sparc_set_id(env, 0);
739 env->mxccregs[7] |= def->mxcc_version;
740 #else
741 env->mmu_version = def->mmu_version;
742 env->maxtl = def->maxtl;
743 env->version |= def->maxtl << 8;
744 env->version |= def->nwindows - 1;
745 #endif
746 return 0;
749 static void cpu_sparc_close(CPUSPARCState *env)
751 free(env->def);
752 free(env);
755 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
757 CPUSPARCState *env;
759 env = qemu_mallocz(sizeof(CPUSPARCState));
760 cpu_exec_init(env);
762 gen_intermediate_code_init(env);
764 if (cpu_sparc_register(env, cpu_model) < 0) {
765 cpu_sparc_close(env);
766 return NULL;
768 qemu_init_vcpu(env);
770 return env;
773 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
775 #if !defined(TARGET_SPARC64)
776 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
777 #endif
780 static const sparc_def_t sparc_defs[] = {
781 #ifdef TARGET_SPARC64
783 .name = "Fujitsu Sparc64",
784 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
785 .fpu_version = 0x00000000,
786 .mmu_version = mmu_us_12,
787 .nwindows = 4,
788 .maxtl = 4,
789 .features = CPU_DEFAULT_FEATURES,
792 .name = "Fujitsu Sparc64 III",
793 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
794 .fpu_version = 0x00000000,
795 .mmu_version = mmu_us_12,
796 .nwindows = 5,
797 .maxtl = 4,
798 .features = CPU_DEFAULT_FEATURES,
801 .name = "Fujitsu Sparc64 IV",
802 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
803 .fpu_version = 0x00000000,
804 .mmu_version = mmu_us_12,
805 .nwindows = 8,
806 .maxtl = 5,
807 .features = CPU_DEFAULT_FEATURES,
810 .name = "Fujitsu Sparc64 V",
811 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
812 .fpu_version = 0x00000000,
813 .mmu_version = mmu_us_12,
814 .nwindows = 8,
815 .maxtl = 5,
816 .features = CPU_DEFAULT_FEATURES,
819 .name = "TI UltraSparc I",
820 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
821 .fpu_version = 0x00000000,
822 .mmu_version = mmu_us_12,
823 .nwindows = 8,
824 .maxtl = 5,
825 .features = CPU_DEFAULT_FEATURES,
828 .name = "TI UltraSparc II",
829 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
830 .fpu_version = 0x00000000,
831 .mmu_version = mmu_us_12,
832 .nwindows = 8,
833 .maxtl = 5,
834 .features = CPU_DEFAULT_FEATURES,
837 .name = "TI UltraSparc IIi",
838 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
839 .fpu_version = 0x00000000,
840 .mmu_version = mmu_us_12,
841 .nwindows = 8,
842 .maxtl = 5,
843 .features = CPU_DEFAULT_FEATURES,
846 .name = "TI UltraSparc IIe",
847 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
848 .fpu_version = 0x00000000,
849 .mmu_version = mmu_us_12,
850 .nwindows = 8,
851 .maxtl = 5,
852 .features = CPU_DEFAULT_FEATURES,
855 .name = "Sun UltraSparc III",
856 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
857 .fpu_version = 0x00000000,
858 .mmu_version = mmu_us_12,
859 .nwindows = 8,
860 .maxtl = 5,
861 .features = CPU_DEFAULT_FEATURES,
864 .name = "Sun UltraSparc III Cu",
865 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
866 .fpu_version = 0x00000000,
867 .mmu_version = mmu_us_3,
868 .nwindows = 8,
869 .maxtl = 5,
870 .features = CPU_DEFAULT_FEATURES,
873 .name = "Sun UltraSparc IIIi",
874 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
875 .fpu_version = 0x00000000,
876 .mmu_version = mmu_us_12,
877 .nwindows = 8,
878 .maxtl = 5,
879 .features = CPU_DEFAULT_FEATURES,
882 .name = "Sun UltraSparc IV",
883 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
884 .fpu_version = 0x00000000,
885 .mmu_version = mmu_us_4,
886 .nwindows = 8,
887 .maxtl = 5,
888 .features = CPU_DEFAULT_FEATURES,
891 .name = "Sun UltraSparc IV+",
892 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
893 .fpu_version = 0x00000000,
894 .mmu_version = mmu_us_12,
895 .nwindows = 8,
896 .maxtl = 5,
897 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
900 .name = "Sun UltraSparc IIIi+",
901 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
902 .fpu_version = 0x00000000,
903 .mmu_version = mmu_us_3,
904 .nwindows = 8,
905 .maxtl = 5,
906 .features = CPU_DEFAULT_FEATURES,
909 .name = "Sun UltraSparc T1",
910 // defined in sparc_ifu_fdp.v and ctu.h
911 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
912 .fpu_version = 0x00000000,
913 .mmu_version = mmu_sun4v,
914 .nwindows = 8,
915 .maxtl = 6,
916 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
917 | CPU_FEATURE_GL,
920 .name = "Sun UltraSparc T2",
921 // defined in tlu_asi_ctl.v and n2_revid_cust.v
922 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
923 .fpu_version = 0x00000000,
924 .mmu_version = mmu_sun4v,
925 .nwindows = 8,
926 .maxtl = 6,
927 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
928 | CPU_FEATURE_GL,
931 .name = "NEC UltraSparc I",
932 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
933 .fpu_version = 0x00000000,
934 .mmu_version = mmu_us_12,
935 .nwindows = 8,
936 .maxtl = 5,
937 .features = CPU_DEFAULT_FEATURES,
939 #else
941 .name = "Fujitsu MB86900",
942 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
943 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
944 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
945 .mmu_bm = 0x00004000,
946 .mmu_ctpr_mask = 0x007ffff0,
947 .mmu_cxr_mask = 0x0000003f,
948 .mmu_sfsr_mask = 0xffffffff,
949 .mmu_trcr_mask = 0xffffffff,
950 .nwindows = 7,
951 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
954 .name = "Fujitsu MB86904",
955 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
956 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
957 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
958 .mmu_bm = 0x00004000,
959 .mmu_ctpr_mask = 0x00ffffc0,
960 .mmu_cxr_mask = 0x000000ff,
961 .mmu_sfsr_mask = 0x00016fff,
962 .mmu_trcr_mask = 0x00ffffff,
963 .nwindows = 8,
964 .features = CPU_DEFAULT_FEATURES,
967 .name = "Fujitsu MB86907",
968 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
969 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
970 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
971 .mmu_bm = 0x00004000,
972 .mmu_ctpr_mask = 0xffffffc0,
973 .mmu_cxr_mask = 0x000000ff,
974 .mmu_sfsr_mask = 0x00016fff,
975 .mmu_trcr_mask = 0xffffffff,
976 .nwindows = 8,
977 .features = CPU_DEFAULT_FEATURES,
980 .name = "LSI L64811",
981 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
982 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
983 .mmu_version = 0x10 << 24,
984 .mmu_bm = 0x00004000,
985 .mmu_ctpr_mask = 0x007ffff0,
986 .mmu_cxr_mask = 0x0000003f,
987 .mmu_sfsr_mask = 0xffffffff,
988 .mmu_trcr_mask = 0xffffffff,
989 .nwindows = 8,
990 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
991 CPU_FEATURE_FSMULD,
994 .name = "Cypress CY7C601",
995 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
996 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
997 .mmu_version = 0x10 << 24,
998 .mmu_bm = 0x00004000,
999 .mmu_ctpr_mask = 0x007ffff0,
1000 .mmu_cxr_mask = 0x0000003f,
1001 .mmu_sfsr_mask = 0xffffffff,
1002 .mmu_trcr_mask = 0xffffffff,
1003 .nwindows = 8,
1004 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1005 CPU_FEATURE_FSMULD,
1008 .name = "Cypress CY7C611",
1009 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1010 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1011 .mmu_version = 0x10 << 24,
1012 .mmu_bm = 0x00004000,
1013 .mmu_ctpr_mask = 0x007ffff0,
1014 .mmu_cxr_mask = 0x0000003f,
1015 .mmu_sfsr_mask = 0xffffffff,
1016 .mmu_trcr_mask = 0xffffffff,
1017 .nwindows = 8,
1018 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1019 CPU_FEATURE_FSMULD,
1022 .name = "TI MicroSparc I",
1023 .iu_version = 0x41000000,
1024 .fpu_version = 4 << 17,
1025 .mmu_version = 0x41000000,
1026 .mmu_bm = 0x00004000,
1027 .mmu_ctpr_mask = 0x007ffff0,
1028 .mmu_cxr_mask = 0x0000003f,
1029 .mmu_sfsr_mask = 0x00016fff,
1030 .mmu_trcr_mask = 0x0000003f,
1031 .nwindows = 7,
1032 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1033 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1034 CPU_FEATURE_FMUL,
1037 .name = "TI MicroSparc II",
1038 .iu_version = 0x42000000,
1039 .fpu_version = 4 << 17,
1040 .mmu_version = 0x02000000,
1041 .mmu_bm = 0x00004000,
1042 .mmu_ctpr_mask = 0x00ffffc0,
1043 .mmu_cxr_mask = 0x000000ff,
1044 .mmu_sfsr_mask = 0x00016fff,
1045 .mmu_trcr_mask = 0x00ffffff,
1046 .nwindows = 8,
1047 .features = CPU_DEFAULT_FEATURES,
1050 .name = "TI MicroSparc IIep",
1051 .iu_version = 0x42000000,
1052 .fpu_version = 4 << 17,
1053 .mmu_version = 0x04000000,
1054 .mmu_bm = 0x00004000,
1055 .mmu_ctpr_mask = 0x00ffffc0,
1056 .mmu_cxr_mask = 0x000000ff,
1057 .mmu_sfsr_mask = 0x00016bff,
1058 .mmu_trcr_mask = 0x00ffffff,
1059 .nwindows = 8,
1060 .features = CPU_DEFAULT_FEATURES,
1063 .name = "TI SuperSparc 40", // STP1020NPGA
1064 .iu_version = 0x41000000, // SuperSPARC 2.x
1065 .fpu_version = 0 << 17,
1066 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1067 .mmu_bm = 0x00002000,
1068 .mmu_ctpr_mask = 0xffffffc0,
1069 .mmu_cxr_mask = 0x0000ffff,
1070 .mmu_sfsr_mask = 0xffffffff,
1071 .mmu_trcr_mask = 0xffffffff,
1072 .nwindows = 8,
1073 .features = CPU_DEFAULT_FEATURES,
1076 .name = "TI SuperSparc 50", // STP1020PGA
1077 .iu_version = 0x40000000, // SuperSPARC 3.x
1078 .fpu_version = 0 << 17,
1079 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1080 .mmu_bm = 0x00002000,
1081 .mmu_ctpr_mask = 0xffffffc0,
1082 .mmu_cxr_mask = 0x0000ffff,
1083 .mmu_sfsr_mask = 0xffffffff,
1084 .mmu_trcr_mask = 0xffffffff,
1085 .nwindows = 8,
1086 .features = CPU_DEFAULT_FEATURES,
1089 .name = "TI SuperSparc 51",
1090 .iu_version = 0x40000000, // SuperSPARC 3.x
1091 .fpu_version = 0 << 17,
1092 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1093 .mmu_bm = 0x00002000,
1094 .mmu_ctpr_mask = 0xffffffc0,
1095 .mmu_cxr_mask = 0x0000ffff,
1096 .mmu_sfsr_mask = 0xffffffff,
1097 .mmu_trcr_mask = 0xffffffff,
1098 .mxcc_version = 0x00000104,
1099 .nwindows = 8,
1100 .features = CPU_DEFAULT_FEATURES,
1103 .name = "TI SuperSparc 60", // STP1020APGA
1104 .iu_version = 0x40000000, // SuperSPARC 3.x
1105 .fpu_version = 0 << 17,
1106 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1107 .mmu_bm = 0x00002000,
1108 .mmu_ctpr_mask = 0xffffffc0,
1109 .mmu_cxr_mask = 0x0000ffff,
1110 .mmu_sfsr_mask = 0xffffffff,
1111 .mmu_trcr_mask = 0xffffffff,
1112 .nwindows = 8,
1113 .features = CPU_DEFAULT_FEATURES,
1116 .name = "TI SuperSparc 61",
1117 .iu_version = 0x44000000, // SuperSPARC 3.x
1118 .fpu_version = 0 << 17,
1119 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1120 .mmu_bm = 0x00002000,
1121 .mmu_ctpr_mask = 0xffffffc0,
1122 .mmu_cxr_mask = 0x0000ffff,
1123 .mmu_sfsr_mask = 0xffffffff,
1124 .mmu_trcr_mask = 0xffffffff,
1125 .mxcc_version = 0x00000104,
1126 .nwindows = 8,
1127 .features = CPU_DEFAULT_FEATURES,
1130 .name = "TI SuperSparc II",
1131 .iu_version = 0x40000000, // SuperSPARC II 1.x
1132 .fpu_version = 0 << 17,
1133 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1134 .mmu_bm = 0x00002000,
1135 .mmu_ctpr_mask = 0xffffffc0,
1136 .mmu_cxr_mask = 0x0000ffff,
1137 .mmu_sfsr_mask = 0xffffffff,
1138 .mmu_trcr_mask = 0xffffffff,
1139 .mxcc_version = 0x00000104,
1140 .nwindows = 8,
1141 .features = CPU_DEFAULT_FEATURES,
1144 .name = "Ross RT625",
1145 .iu_version = 0x1e000000,
1146 .fpu_version = 1 << 17,
1147 .mmu_version = 0x1e000000,
1148 .mmu_bm = 0x00004000,
1149 .mmu_ctpr_mask = 0x007ffff0,
1150 .mmu_cxr_mask = 0x0000003f,
1151 .mmu_sfsr_mask = 0xffffffff,
1152 .mmu_trcr_mask = 0xffffffff,
1153 .nwindows = 8,
1154 .features = CPU_DEFAULT_FEATURES,
1157 .name = "Ross RT620",
1158 .iu_version = 0x1f000000,
1159 .fpu_version = 1 << 17,
1160 .mmu_version = 0x1f000000,
1161 .mmu_bm = 0x00004000,
1162 .mmu_ctpr_mask = 0x007ffff0,
1163 .mmu_cxr_mask = 0x0000003f,
1164 .mmu_sfsr_mask = 0xffffffff,
1165 .mmu_trcr_mask = 0xffffffff,
1166 .nwindows = 8,
1167 .features = CPU_DEFAULT_FEATURES,
1170 .name = "BIT B5010",
1171 .iu_version = 0x20000000,
1172 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1173 .mmu_version = 0x20000000,
1174 .mmu_bm = 0x00004000,
1175 .mmu_ctpr_mask = 0x007ffff0,
1176 .mmu_cxr_mask = 0x0000003f,
1177 .mmu_sfsr_mask = 0xffffffff,
1178 .mmu_trcr_mask = 0xffffffff,
1179 .nwindows = 8,
1180 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1181 CPU_FEATURE_FSMULD,
1184 .name = "Matsushita MN10501",
1185 .iu_version = 0x50000000,
1186 .fpu_version = 0 << 17,
1187 .mmu_version = 0x50000000,
1188 .mmu_bm = 0x00004000,
1189 .mmu_ctpr_mask = 0x007ffff0,
1190 .mmu_cxr_mask = 0x0000003f,
1191 .mmu_sfsr_mask = 0xffffffff,
1192 .mmu_trcr_mask = 0xffffffff,
1193 .nwindows = 8,
1194 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1195 CPU_FEATURE_FSMULD,
1198 .name = "Weitek W8601",
1199 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1200 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1201 .mmu_version = 0x10 << 24,
1202 .mmu_bm = 0x00004000,
1203 .mmu_ctpr_mask = 0x007ffff0,
1204 .mmu_cxr_mask = 0x0000003f,
1205 .mmu_sfsr_mask = 0xffffffff,
1206 .mmu_trcr_mask = 0xffffffff,
1207 .nwindows = 8,
1208 .features = CPU_DEFAULT_FEATURES,
1211 .name = "LEON2",
1212 .iu_version = 0xf2000000,
1213 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1214 .mmu_version = 0xf2000000,
1215 .mmu_bm = 0x00004000,
1216 .mmu_ctpr_mask = 0x007ffff0,
1217 .mmu_cxr_mask = 0x0000003f,
1218 .mmu_sfsr_mask = 0xffffffff,
1219 .mmu_trcr_mask = 0xffffffff,
1220 .nwindows = 8,
1221 .features = CPU_DEFAULT_FEATURES,
1224 .name = "LEON3",
1225 .iu_version = 0xf3000000,
1226 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1227 .mmu_version = 0xf3000000,
1228 .mmu_bm = 0x00004000,
1229 .mmu_ctpr_mask = 0x007ffff0,
1230 .mmu_cxr_mask = 0x0000003f,
1231 .mmu_sfsr_mask = 0xffffffff,
1232 .mmu_trcr_mask = 0xffffffff,
1233 .nwindows = 8,
1234 .features = CPU_DEFAULT_FEATURES,
1236 #endif
1239 static const char * const feature_name[] = {
1240 "float",
1241 "float128",
1242 "swap",
1243 "mul",
1244 "div",
1245 "flush",
1246 "fsqrt",
1247 "fmul",
1248 "vis1",
1249 "vis2",
1250 "fsmuld",
1251 "hypv",
1252 "cmt",
1253 "gl",
1256 static void print_features(FILE *f,
1257 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1258 uint32_t features, const char *prefix)
1260 unsigned int i;
1262 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1263 if (feature_name[i] && (features & (1 << i))) {
1264 if (prefix)
1265 (*cpu_fprintf)(f, "%s", prefix);
1266 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1270 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1272 unsigned int i;
1274 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1275 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1276 *features |= 1 << i;
1277 return;
1279 fprintf(stderr, "CPU feature %s not found\n", flagname);
1282 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1284 unsigned int i;
1285 const sparc_def_t *def = NULL;
1286 char *s = strdup(cpu_model);
1287 char *featurestr, *name = strtok(s, ",");
1288 uint32_t plus_features = 0;
1289 uint32_t minus_features = 0;
1290 long long iu_version;
1291 uint32_t fpu_version, mmu_version, nwindows;
1293 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1294 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1295 def = &sparc_defs[i];
1298 if (!def)
1299 goto error;
1300 memcpy(cpu_def, def, sizeof(*def));
1302 featurestr = strtok(NULL, ",");
1303 while (featurestr) {
1304 char *val;
1306 if (featurestr[0] == '+') {
1307 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1308 } else if (featurestr[0] == '-') {
1309 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1310 } else if ((val = strchr(featurestr, '='))) {
1311 *val = 0; val++;
1312 if (!strcmp(featurestr, "iu_version")) {
1313 char *err;
1315 iu_version = strtoll(val, &err, 0);
1316 if (!*val || *err) {
1317 fprintf(stderr, "bad numerical value %s\n", val);
1318 goto error;
1320 cpu_def->iu_version = iu_version;
1321 #ifdef DEBUG_FEATURES
1322 fprintf(stderr, "iu_version %llx\n", iu_version);
1323 #endif
1324 } else if (!strcmp(featurestr, "fpu_version")) {
1325 char *err;
1327 fpu_version = strtol(val, &err, 0);
1328 if (!*val || *err) {
1329 fprintf(stderr, "bad numerical value %s\n", val);
1330 goto error;
1332 cpu_def->fpu_version = fpu_version;
1333 #ifdef DEBUG_FEATURES
1334 fprintf(stderr, "fpu_version %x\n", fpu_version);
1335 #endif
1336 } else if (!strcmp(featurestr, "mmu_version")) {
1337 char *err;
1339 mmu_version = strtol(val, &err, 0);
1340 if (!*val || *err) {
1341 fprintf(stderr, "bad numerical value %s\n", val);
1342 goto error;
1344 cpu_def->mmu_version = mmu_version;
1345 #ifdef DEBUG_FEATURES
1346 fprintf(stderr, "mmu_version %x\n", mmu_version);
1347 #endif
1348 } else if (!strcmp(featurestr, "nwindows")) {
1349 char *err;
1351 nwindows = strtol(val, &err, 0);
1352 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1353 nwindows < MIN_NWINDOWS) {
1354 fprintf(stderr, "bad numerical value %s\n", val);
1355 goto error;
1357 cpu_def->nwindows = nwindows;
1358 #ifdef DEBUG_FEATURES
1359 fprintf(stderr, "nwindows %d\n", nwindows);
1360 #endif
1361 } else {
1362 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1363 goto error;
1365 } else {
1366 fprintf(stderr, "feature string `%s' not in format "
1367 "(+feature|-feature|feature=xyz)\n", featurestr);
1368 goto error;
1370 featurestr = strtok(NULL, ",");
1372 cpu_def->features |= plus_features;
1373 cpu_def->features &= ~minus_features;
1374 #ifdef DEBUG_FEATURES
1375 print_features(stderr, fprintf, cpu_def->features, NULL);
1376 #endif
1377 free(s);
1378 return 0;
1380 error:
1381 free(s);
1382 return -1;
1385 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1387 unsigned int i;
1389 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1390 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1391 sparc_defs[i].name,
1392 sparc_defs[i].iu_version,
1393 sparc_defs[i].fpu_version,
1394 sparc_defs[i].mmu_version,
1395 sparc_defs[i].nwindows);
1396 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1397 ~sparc_defs[i].features, "-");
1398 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1399 sparc_defs[i].features, "+");
1400 (*cpu_fprintf)(f, "\n");
1402 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1403 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1404 (*cpu_fprintf)(f, "\n");
1405 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1406 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1407 (*cpu_fprintf)(f, "\n");
1408 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1409 "fpu_version mmu_version nwindows\n");
1412 static void cpu_print_cc(FILE *f,
1413 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1414 uint32_t cc)
1416 cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
1417 cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
1418 cc & PSR_CARRY? 'C' : '-');
1421 #ifdef TARGET_SPARC64
1422 #define REGS_PER_LINE 4
1423 #else
1424 #define REGS_PER_LINE 8
1425 #endif
1427 void cpu_dump_state(CPUState *env, FILE *f,
1428 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1429 int flags)
1431 int i, x;
1433 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1434 env->npc);
1435 cpu_fprintf(f, "General Registers:\n");
1437 for (i = 0; i < 8; i++) {
1438 if (i % REGS_PER_LINE == 0) {
1439 cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
1441 cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
1442 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1443 cpu_fprintf(f, "\n");
1446 cpu_fprintf(f, "\nCurrent Register Window:\n");
1447 for (x = 0; x < 3; x++) {
1448 for (i = 0; i < 8; i++) {
1449 if (i % REGS_PER_LINE == 0) {
1450 cpu_fprintf(f, "%%%c%d-%d: ",
1451 x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
1452 i, i + REGS_PER_LINE - 1);
1454 cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
1455 if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
1456 cpu_fprintf(f, "\n");
1460 cpu_fprintf(f, "\nFloating Point Registers:\n");
1461 for (i = 0; i < TARGET_FPREGS; i++) {
1462 if ((i & 3) == 0)
1463 cpu_fprintf(f, "%%f%02d:", i);
1464 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1465 if ((i & 3) == 3)
1466 cpu_fprintf(f, "\n");
1468 #ifdef TARGET_SPARC64
1469 cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
1470 GET_CCR(env));
1471 cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << PSR_CARRY_SHIFT);
1472 cpu_fprintf(f, " xcc: ");
1473 cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << (PSR_CARRY_SHIFT - 4));
1474 cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
1475 env->psrpil);
1476 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
1477 "cleanwin: %d cwp: %d\n",
1478 env->cansave, env->canrestore, env->otherwin, env->wstate,
1479 env->cleanwin, env->nwindows - 1 - env->cwp);
1480 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
1481 TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
1482 #else
1483 cpu_fprintf(f, "psr: %08x (icc: ", GET_PSR(env));
1484 cpu_print_cc(f, cpu_fprintf, GET_PSR(env));
1485 cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
1486 env->psrps? 'P' : '-', env->psret? 'E' : '-',
1487 env->wim);
1488 cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
1489 env->fsr, env->y);
1490 #endif