Make it obvious that pci_nic_init() can't fail
[qemu-kvm/fedora.git] / target-sparc / helper.c
blob5951e6b5c3567905f161b9a76323da4e6d6a693c
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(uint64_t tlb_tag, uint64_t tlb_tte,
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 ((tlb_tte & 0x8000000000000000ULL) &&
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->dmmuregs[1] & 0x1fff;
439 for (i = 0; i < 64; i++) {
440 // ctx match, vaddr match, valid?
441 if (ultrasparc_tag_match(env->dtlb_tag[i], env->dtlb_tte[i],
442 address, context, physical)
444 // access ok?
445 if (((env->dtlb_tte[i] & 0x4) && is_user) ||
446 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
447 if (env->dmmuregs[3]) /* Fault status register */
448 env->dmmuregs[3] = 2; /* overflow (not read before
449 another fault) */
450 env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
451 env->dmmuregs[4] = address; /* Fault address register */
452 env->exception_index = TT_DFAULT;
453 #ifdef DEBUG_MMU
454 printf("DFAULT at 0x%" PRIx64 "\n", address);
455 #endif
456 return 1;
458 *prot = PAGE_READ;
459 if (env->dtlb_tte[i] & 0x2)
460 *prot |= PAGE_WRITE;
461 return 0;
464 #ifdef DEBUG_MMU
465 printf("DMISS at 0x%" PRIx64 "\n", address);
466 #endif
467 env->dmmuregs[6] = (address & ~0x1fffULL) | context;
468 env->exception_index = TT_DMISS;
469 return 1;
472 static int get_physical_address_code(CPUState *env,
473 target_phys_addr_t *physical, int *prot,
474 target_ulong address, int is_user)
476 unsigned int i;
477 uint64_t context;
479 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
480 /* IMMU disabled */
481 *physical = ultrasparc_truncate_physical(address);
482 *prot = PAGE_EXEC;
483 return 0;
486 context = env->dmmuregs[1] & 0x1fff;
488 for (i = 0; i < 64; i++) {
489 // ctx match, vaddr match, valid?
490 if (ultrasparc_tag_match(env->itlb_tag[i], env->itlb_tte[i],
491 address, context, physical)
493 // access ok?
494 if ((env->itlb_tte[i] & 0x4) && is_user) {
495 if (env->immuregs[3]) /* Fault status register */
496 env->immuregs[3] = 2; /* overflow (not read before
497 another fault) */
498 env->immuregs[3] |= (is_user << 3) | 1;
499 env->exception_index = TT_TFAULT;
500 #ifdef DEBUG_MMU
501 printf("TFAULT at 0x%" PRIx64 "\n", address);
502 #endif
503 return 1;
505 *prot = PAGE_EXEC;
506 return 0;
509 #ifdef DEBUG_MMU
510 printf("TMISS at 0x%" PRIx64 "\n", address);
511 #endif
512 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
513 env->immuregs[6] = (address & ~0x1fffULL) | context;
514 env->exception_index = TT_TMISS;
515 return 1;
518 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
519 int *prot, int *access_index,
520 target_ulong address, int rw, int mmu_idx)
522 int is_user = mmu_idx == MMU_USER_IDX;
524 if (rw == 2)
525 return get_physical_address_code(env, physical, prot, address,
526 is_user);
527 else
528 return get_physical_address_data(env, physical, prot, address, rw,
529 is_user);
532 /* Perform address translation */
533 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
534 int mmu_idx, int is_softmmu)
536 target_ulong virt_addr, vaddr;
537 target_phys_addr_t paddr;
538 int error_code = 0, prot, ret = 0, access_index;
540 error_code = get_physical_address(env, &paddr, &prot, &access_index,
541 address, rw, mmu_idx);
542 if (error_code == 0) {
543 virt_addr = address & TARGET_PAGE_MASK;
544 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
545 (TARGET_PAGE_SIZE - 1));
546 #ifdef DEBUG_MMU
547 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
548 "\n", address, paddr, vaddr);
549 #endif
550 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
551 return ret;
553 // XXX
554 return 1;
557 #ifdef DEBUG_MMU
558 void dump_mmu(CPUState *env)
560 unsigned int i;
561 const char *mask;
563 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
564 env->dmmuregs[1], env->dmmuregs[2]);
565 if ((env->lsu & DMMU_E) == 0) {
566 printf("DMMU disabled\n");
567 } else {
568 printf("DMMU dump:\n");
569 for (i = 0; i < 64; i++) {
570 switch ((env->dtlb_tte[i] >> 61) & 3) {
571 default:
572 case 0x0:
573 mask = " 8k";
574 break;
575 case 0x1:
576 mask = " 64k";
577 break;
578 case 0x2:
579 mask = "512k";
580 break;
581 case 0x3:
582 mask = " 4M";
583 break;
585 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
586 printf("VA: %" PRIx64 ", PA: %" PRIx64
587 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
588 env->dtlb_tag[i] & (uint64_t)~0x1fffULL,
589 env->dtlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
590 mask,
591 env->dtlb_tte[i] & 0x4? "priv": "user",
592 env->dtlb_tte[i] & 0x2? "RW": "RO",
593 env->dtlb_tte[i] & 0x40? "locked": "unlocked",
594 env->dtlb_tag[i] & (uint64_t)0x1fffULL);
598 if ((env->lsu & IMMU_E) == 0) {
599 printf("IMMU disabled\n");
600 } else {
601 printf("IMMU dump:\n");
602 for (i = 0; i < 64; i++) {
603 switch ((env->itlb_tte[i] >> 61) & 3) {
604 default:
605 case 0x0:
606 mask = " 8k";
607 break;
608 case 0x1:
609 mask = " 64k";
610 break;
611 case 0x2:
612 mask = "512k";
613 break;
614 case 0x3:
615 mask = " 4M";
616 break;
618 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
619 printf("VA: %" PRIx64 ", PA: %" PRIx64
620 ", %s, %s, %s, ctx %" PRId64 "\n",
621 env->itlb_tag[i] & (uint64_t)~0x1fffULL,
622 env->itlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
623 mask,
624 env->itlb_tte[i] & 0x4? "priv": "user",
625 env->itlb_tte[i] & 0x40? "locked": "unlocked",
626 env->itlb_tag[i] & (uint64_t)0x1fffULL);
631 #endif /* DEBUG_MMU */
633 #endif /* TARGET_SPARC64 */
634 #endif /* !CONFIG_USER_ONLY */
637 #if defined(CONFIG_USER_ONLY)
638 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
640 return addr;
643 #else
644 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
646 target_phys_addr_t phys_addr;
647 int prot, access_index;
649 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
650 MMU_KERNEL_IDX) != 0)
651 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
652 0, MMU_KERNEL_IDX) != 0)
653 return -1;
654 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
655 return -1;
656 return phys_addr;
658 #endif
660 void cpu_reset(CPUSPARCState *env)
662 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
663 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
664 log_cpu_state(env, 0);
667 tlb_flush(env, 1);
668 env->cwp = 0;
669 #ifndef TARGET_SPARC64
670 env->wim = 1;
671 #endif
672 env->regwptr = env->regbase + (env->cwp * 16);
673 #if defined(CONFIG_USER_ONLY)
674 #ifdef TARGET_SPARC64
675 env->cleanwin = env->nwindows - 2;
676 env->cansave = env->nwindows - 2;
677 env->pstate = PS_RMO | PS_PEF | PS_IE;
678 env->asi = 0x82; // Primary no-fault
679 #endif
680 #else
681 #if !defined(TARGET_SPARC64)
682 env->psret = 0;
683 #endif
684 env->psrs = 1;
685 env->psrps = 1;
686 CC_OP = CC_OP_FLAGS;
687 #ifdef TARGET_SPARC64
688 env->pstate = PS_PRIV;
689 env->hpstate = HS_PRIV;
690 env->tsptr = &env->ts[env->tl & MAXTL_MASK];
691 env->lsu = 0;
692 #else
693 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
694 env->mmuregs[0] |= env->def->mmu_bm;
695 #endif
696 env->pc = 0;
697 env->npc = env->pc + 4;
698 #endif
701 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
703 sparc_def_t def1, *def = &def1;
705 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
706 return -1;
708 env->def = qemu_mallocz(sizeof(*def));
709 memcpy(env->def, def, sizeof(*def));
710 #if defined(CONFIG_USER_ONLY)
711 if ((env->def->features & CPU_FEATURE_FLOAT))
712 env->def->features |= CPU_FEATURE_FLOAT128;
713 #endif
714 env->cpu_model_str = cpu_model;
715 env->version = def->iu_version;
716 env->fsr = def->fpu_version;
717 env->nwindows = def->nwindows;
718 #if !defined(TARGET_SPARC64)
719 env->mmuregs[0] |= def->mmu_version;
720 cpu_sparc_set_id(env, 0);
721 env->mxccregs[7] |= def->mxcc_version;
722 #else
723 env->mmu_version = def->mmu_version;
724 env->maxtl = def->maxtl;
725 env->version |= def->maxtl << 8;
726 env->version |= def->nwindows - 1;
727 #endif
728 return 0;
731 static void cpu_sparc_close(CPUSPARCState *env)
733 free(env->def);
734 free(env);
737 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
739 CPUSPARCState *env;
741 env = qemu_mallocz(sizeof(CPUSPARCState));
742 cpu_exec_init(env);
744 gen_intermediate_code_init(env);
746 if (cpu_sparc_register(env, cpu_model) < 0) {
747 cpu_sparc_close(env);
748 return NULL;
750 cpu_reset(env);
751 qemu_init_vcpu(env);
753 return env;
756 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
758 #if !defined(TARGET_SPARC64)
759 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
760 #endif
763 static const sparc_def_t sparc_defs[] = {
764 #ifdef TARGET_SPARC64
766 .name = "Fujitsu Sparc64",
767 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
768 .fpu_version = 0x00000000,
769 .mmu_version = mmu_us_12,
770 .nwindows = 4,
771 .maxtl = 4,
772 .features = CPU_DEFAULT_FEATURES,
775 .name = "Fujitsu Sparc64 III",
776 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
777 .fpu_version = 0x00000000,
778 .mmu_version = mmu_us_12,
779 .nwindows = 5,
780 .maxtl = 4,
781 .features = CPU_DEFAULT_FEATURES,
784 .name = "Fujitsu Sparc64 IV",
785 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
786 .fpu_version = 0x00000000,
787 .mmu_version = mmu_us_12,
788 .nwindows = 8,
789 .maxtl = 5,
790 .features = CPU_DEFAULT_FEATURES,
793 .name = "Fujitsu Sparc64 V",
794 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
795 .fpu_version = 0x00000000,
796 .mmu_version = mmu_us_12,
797 .nwindows = 8,
798 .maxtl = 5,
799 .features = CPU_DEFAULT_FEATURES,
802 .name = "TI UltraSparc I",
803 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
804 .fpu_version = 0x00000000,
805 .mmu_version = mmu_us_12,
806 .nwindows = 8,
807 .maxtl = 5,
808 .features = CPU_DEFAULT_FEATURES,
811 .name = "TI UltraSparc II",
812 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 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 IIi",
821 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 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 IIe",
830 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
831 .fpu_version = 0x00000000,
832 .mmu_version = mmu_us_12,
833 .nwindows = 8,
834 .maxtl = 5,
835 .features = CPU_DEFAULT_FEATURES,
838 .name = "Sun UltraSparc III",
839 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
840 .fpu_version = 0x00000000,
841 .mmu_version = mmu_us_12,
842 .nwindows = 8,
843 .maxtl = 5,
844 .features = CPU_DEFAULT_FEATURES,
847 .name = "Sun UltraSparc III Cu",
848 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
849 .fpu_version = 0x00000000,
850 .mmu_version = mmu_us_3,
851 .nwindows = 8,
852 .maxtl = 5,
853 .features = CPU_DEFAULT_FEATURES,
856 .name = "Sun UltraSparc IIIi",
857 .iu_version = ((0x3eULL << 48) | (0x16ULL << 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 IV",
866 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
867 .fpu_version = 0x00000000,
868 .mmu_version = mmu_us_4,
869 .nwindows = 8,
870 .maxtl = 5,
871 .features = CPU_DEFAULT_FEATURES,
874 .name = "Sun UltraSparc IV+",
875 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
876 .fpu_version = 0x00000000,
877 .mmu_version = mmu_us_12,
878 .nwindows = 8,
879 .maxtl = 5,
880 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
883 .name = "Sun UltraSparc IIIi+",
884 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
885 .fpu_version = 0x00000000,
886 .mmu_version = mmu_us_3,
887 .nwindows = 8,
888 .maxtl = 5,
889 .features = CPU_DEFAULT_FEATURES,
892 .name = "Sun UltraSparc T1",
893 // defined in sparc_ifu_fdp.v and ctu.h
894 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
895 .fpu_version = 0x00000000,
896 .mmu_version = mmu_sun4v,
897 .nwindows = 8,
898 .maxtl = 6,
899 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
900 | CPU_FEATURE_GL,
903 .name = "Sun UltraSparc T2",
904 // defined in tlu_asi_ctl.v and n2_revid_cust.v
905 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
906 .fpu_version = 0x00000000,
907 .mmu_version = mmu_sun4v,
908 .nwindows = 8,
909 .maxtl = 6,
910 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
911 | CPU_FEATURE_GL,
914 .name = "NEC UltraSparc I",
915 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
916 .fpu_version = 0x00000000,
917 .mmu_version = mmu_us_12,
918 .nwindows = 8,
919 .maxtl = 5,
920 .features = CPU_DEFAULT_FEATURES,
922 #else
924 .name = "Fujitsu MB86900",
925 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
926 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
927 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
928 .mmu_bm = 0x00004000,
929 .mmu_ctpr_mask = 0x007ffff0,
930 .mmu_cxr_mask = 0x0000003f,
931 .mmu_sfsr_mask = 0xffffffff,
932 .mmu_trcr_mask = 0xffffffff,
933 .nwindows = 7,
934 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
937 .name = "Fujitsu MB86904",
938 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
939 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
940 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
941 .mmu_bm = 0x00004000,
942 .mmu_ctpr_mask = 0x00ffffc0,
943 .mmu_cxr_mask = 0x000000ff,
944 .mmu_sfsr_mask = 0x00016fff,
945 .mmu_trcr_mask = 0x00ffffff,
946 .nwindows = 8,
947 .features = CPU_DEFAULT_FEATURES,
950 .name = "Fujitsu MB86907",
951 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
952 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
953 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
954 .mmu_bm = 0x00004000,
955 .mmu_ctpr_mask = 0xffffffc0,
956 .mmu_cxr_mask = 0x000000ff,
957 .mmu_sfsr_mask = 0x00016fff,
958 .mmu_trcr_mask = 0xffffffff,
959 .nwindows = 8,
960 .features = CPU_DEFAULT_FEATURES,
963 .name = "LSI L64811",
964 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
965 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
966 .mmu_version = 0x10 << 24,
967 .mmu_bm = 0x00004000,
968 .mmu_ctpr_mask = 0x007ffff0,
969 .mmu_cxr_mask = 0x0000003f,
970 .mmu_sfsr_mask = 0xffffffff,
971 .mmu_trcr_mask = 0xffffffff,
972 .nwindows = 8,
973 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
974 CPU_FEATURE_FSMULD,
977 .name = "Cypress CY7C601",
978 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
979 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
980 .mmu_version = 0x10 << 24,
981 .mmu_bm = 0x00004000,
982 .mmu_ctpr_mask = 0x007ffff0,
983 .mmu_cxr_mask = 0x0000003f,
984 .mmu_sfsr_mask = 0xffffffff,
985 .mmu_trcr_mask = 0xffffffff,
986 .nwindows = 8,
987 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
988 CPU_FEATURE_FSMULD,
991 .name = "Cypress CY7C611",
992 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
993 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
994 .mmu_version = 0x10 << 24,
995 .mmu_bm = 0x00004000,
996 .mmu_ctpr_mask = 0x007ffff0,
997 .mmu_cxr_mask = 0x0000003f,
998 .mmu_sfsr_mask = 0xffffffff,
999 .mmu_trcr_mask = 0xffffffff,
1000 .nwindows = 8,
1001 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1002 CPU_FEATURE_FSMULD,
1005 .name = "TI MicroSparc I",
1006 .iu_version = 0x41000000,
1007 .fpu_version = 4 << 17,
1008 .mmu_version = 0x41000000,
1009 .mmu_bm = 0x00004000,
1010 .mmu_ctpr_mask = 0x007ffff0,
1011 .mmu_cxr_mask = 0x0000003f,
1012 .mmu_sfsr_mask = 0x00016fff,
1013 .mmu_trcr_mask = 0x0000003f,
1014 .nwindows = 7,
1015 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1016 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1017 CPU_FEATURE_FMUL,
1020 .name = "TI MicroSparc II",
1021 .iu_version = 0x42000000,
1022 .fpu_version = 4 << 17,
1023 .mmu_version = 0x02000000,
1024 .mmu_bm = 0x00004000,
1025 .mmu_ctpr_mask = 0x00ffffc0,
1026 .mmu_cxr_mask = 0x000000ff,
1027 .mmu_sfsr_mask = 0x00016fff,
1028 .mmu_trcr_mask = 0x00ffffff,
1029 .nwindows = 8,
1030 .features = CPU_DEFAULT_FEATURES,
1033 .name = "TI MicroSparc IIep",
1034 .iu_version = 0x42000000,
1035 .fpu_version = 4 << 17,
1036 .mmu_version = 0x04000000,
1037 .mmu_bm = 0x00004000,
1038 .mmu_ctpr_mask = 0x00ffffc0,
1039 .mmu_cxr_mask = 0x000000ff,
1040 .mmu_sfsr_mask = 0x00016bff,
1041 .mmu_trcr_mask = 0x00ffffff,
1042 .nwindows = 8,
1043 .features = CPU_DEFAULT_FEATURES,
1046 .name = "TI SuperSparc 40", // STP1020NPGA
1047 .iu_version = 0x41000000, // SuperSPARC 2.x
1048 .fpu_version = 0 << 17,
1049 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1050 .mmu_bm = 0x00002000,
1051 .mmu_ctpr_mask = 0xffffffc0,
1052 .mmu_cxr_mask = 0x0000ffff,
1053 .mmu_sfsr_mask = 0xffffffff,
1054 .mmu_trcr_mask = 0xffffffff,
1055 .nwindows = 8,
1056 .features = CPU_DEFAULT_FEATURES,
1059 .name = "TI SuperSparc 50", // STP1020PGA
1060 .iu_version = 0x40000000, // SuperSPARC 3.x
1061 .fpu_version = 0 << 17,
1062 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1063 .mmu_bm = 0x00002000,
1064 .mmu_ctpr_mask = 0xffffffc0,
1065 .mmu_cxr_mask = 0x0000ffff,
1066 .mmu_sfsr_mask = 0xffffffff,
1067 .mmu_trcr_mask = 0xffffffff,
1068 .nwindows = 8,
1069 .features = CPU_DEFAULT_FEATURES,
1072 .name = "TI SuperSparc 51",
1073 .iu_version = 0x40000000, // SuperSPARC 3.x
1074 .fpu_version = 0 << 17,
1075 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1076 .mmu_bm = 0x00002000,
1077 .mmu_ctpr_mask = 0xffffffc0,
1078 .mmu_cxr_mask = 0x0000ffff,
1079 .mmu_sfsr_mask = 0xffffffff,
1080 .mmu_trcr_mask = 0xffffffff,
1081 .mxcc_version = 0x00000104,
1082 .nwindows = 8,
1083 .features = CPU_DEFAULT_FEATURES,
1086 .name = "TI SuperSparc 60", // STP1020APGA
1087 .iu_version = 0x40000000, // SuperSPARC 3.x
1088 .fpu_version = 0 << 17,
1089 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1090 .mmu_bm = 0x00002000,
1091 .mmu_ctpr_mask = 0xffffffc0,
1092 .mmu_cxr_mask = 0x0000ffff,
1093 .mmu_sfsr_mask = 0xffffffff,
1094 .mmu_trcr_mask = 0xffffffff,
1095 .nwindows = 8,
1096 .features = CPU_DEFAULT_FEATURES,
1099 .name = "TI SuperSparc 61",
1100 .iu_version = 0x44000000, // SuperSPARC 3.x
1101 .fpu_version = 0 << 17,
1102 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1103 .mmu_bm = 0x00002000,
1104 .mmu_ctpr_mask = 0xffffffc0,
1105 .mmu_cxr_mask = 0x0000ffff,
1106 .mmu_sfsr_mask = 0xffffffff,
1107 .mmu_trcr_mask = 0xffffffff,
1108 .mxcc_version = 0x00000104,
1109 .nwindows = 8,
1110 .features = CPU_DEFAULT_FEATURES,
1113 .name = "TI SuperSparc II",
1114 .iu_version = 0x40000000, // SuperSPARC II 1.x
1115 .fpu_version = 0 << 17,
1116 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1117 .mmu_bm = 0x00002000,
1118 .mmu_ctpr_mask = 0xffffffc0,
1119 .mmu_cxr_mask = 0x0000ffff,
1120 .mmu_sfsr_mask = 0xffffffff,
1121 .mmu_trcr_mask = 0xffffffff,
1122 .mxcc_version = 0x00000104,
1123 .nwindows = 8,
1124 .features = CPU_DEFAULT_FEATURES,
1127 .name = "Ross RT625",
1128 .iu_version = 0x1e000000,
1129 .fpu_version = 1 << 17,
1130 .mmu_version = 0x1e000000,
1131 .mmu_bm = 0x00004000,
1132 .mmu_ctpr_mask = 0x007ffff0,
1133 .mmu_cxr_mask = 0x0000003f,
1134 .mmu_sfsr_mask = 0xffffffff,
1135 .mmu_trcr_mask = 0xffffffff,
1136 .nwindows = 8,
1137 .features = CPU_DEFAULT_FEATURES,
1140 .name = "Ross RT620",
1141 .iu_version = 0x1f000000,
1142 .fpu_version = 1 << 17,
1143 .mmu_version = 0x1f000000,
1144 .mmu_bm = 0x00004000,
1145 .mmu_ctpr_mask = 0x007ffff0,
1146 .mmu_cxr_mask = 0x0000003f,
1147 .mmu_sfsr_mask = 0xffffffff,
1148 .mmu_trcr_mask = 0xffffffff,
1149 .nwindows = 8,
1150 .features = CPU_DEFAULT_FEATURES,
1153 .name = "BIT B5010",
1154 .iu_version = 0x20000000,
1155 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1156 .mmu_version = 0x20000000,
1157 .mmu_bm = 0x00004000,
1158 .mmu_ctpr_mask = 0x007ffff0,
1159 .mmu_cxr_mask = 0x0000003f,
1160 .mmu_sfsr_mask = 0xffffffff,
1161 .mmu_trcr_mask = 0xffffffff,
1162 .nwindows = 8,
1163 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1164 CPU_FEATURE_FSMULD,
1167 .name = "Matsushita MN10501",
1168 .iu_version = 0x50000000,
1169 .fpu_version = 0 << 17,
1170 .mmu_version = 0x50000000,
1171 .mmu_bm = 0x00004000,
1172 .mmu_ctpr_mask = 0x007ffff0,
1173 .mmu_cxr_mask = 0x0000003f,
1174 .mmu_sfsr_mask = 0xffffffff,
1175 .mmu_trcr_mask = 0xffffffff,
1176 .nwindows = 8,
1177 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1178 CPU_FEATURE_FSMULD,
1181 .name = "Weitek W8601",
1182 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1183 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1184 .mmu_version = 0x10 << 24,
1185 .mmu_bm = 0x00004000,
1186 .mmu_ctpr_mask = 0x007ffff0,
1187 .mmu_cxr_mask = 0x0000003f,
1188 .mmu_sfsr_mask = 0xffffffff,
1189 .mmu_trcr_mask = 0xffffffff,
1190 .nwindows = 8,
1191 .features = CPU_DEFAULT_FEATURES,
1194 .name = "LEON2",
1195 .iu_version = 0xf2000000,
1196 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1197 .mmu_version = 0xf2000000,
1198 .mmu_bm = 0x00004000,
1199 .mmu_ctpr_mask = 0x007ffff0,
1200 .mmu_cxr_mask = 0x0000003f,
1201 .mmu_sfsr_mask = 0xffffffff,
1202 .mmu_trcr_mask = 0xffffffff,
1203 .nwindows = 8,
1204 .features = CPU_DEFAULT_FEATURES,
1207 .name = "LEON3",
1208 .iu_version = 0xf3000000,
1209 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1210 .mmu_version = 0xf3000000,
1211 .mmu_bm = 0x00004000,
1212 .mmu_ctpr_mask = 0x007ffff0,
1213 .mmu_cxr_mask = 0x0000003f,
1214 .mmu_sfsr_mask = 0xffffffff,
1215 .mmu_trcr_mask = 0xffffffff,
1216 .nwindows = 8,
1217 .features = CPU_DEFAULT_FEATURES,
1219 #endif
1222 static const char * const feature_name[] = {
1223 "float",
1224 "float128",
1225 "swap",
1226 "mul",
1227 "div",
1228 "flush",
1229 "fsqrt",
1230 "fmul",
1231 "vis1",
1232 "vis2",
1233 "fsmuld",
1234 "hypv",
1235 "cmt",
1236 "gl",
1239 static void print_features(FILE *f,
1240 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1241 uint32_t features, const char *prefix)
1243 unsigned int i;
1245 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1246 if (feature_name[i] && (features & (1 << i))) {
1247 if (prefix)
1248 (*cpu_fprintf)(f, "%s", prefix);
1249 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1253 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1255 unsigned int i;
1257 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1258 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1259 *features |= 1 << i;
1260 return;
1262 fprintf(stderr, "CPU feature %s not found\n", flagname);
1265 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1267 unsigned int i;
1268 const sparc_def_t *def = NULL;
1269 char *s = strdup(cpu_model);
1270 char *featurestr, *name = strtok(s, ",");
1271 uint32_t plus_features = 0;
1272 uint32_t minus_features = 0;
1273 long long iu_version;
1274 uint32_t fpu_version, mmu_version, nwindows;
1276 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1277 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1278 def = &sparc_defs[i];
1281 if (!def)
1282 goto error;
1283 memcpy(cpu_def, def, sizeof(*def));
1285 featurestr = strtok(NULL, ",");
1286 while (featurestr) {
1287 char *val;
1289 if (featurestr[0] == '+') {
1290 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1291 } else if (featurestr[0] == '-') {
1292 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1293 } else if ((val = strchr(featurestr, '='))) {
1294 *val = 0; val++;
1295 if (!strcmp(featurestr, "iu_version")) {
1296 char *err;
1298 iu_version = strtoll(val, &err, 0);
1299 if (!*val || *err) {
1300 fprintf(stderr, "bad numerical value %s\n", val);
1301 goto error;
1303 cpu_def->iu_version = iu_version;
1304 #ifdef DEBUG_FEATURES
1305 fprintf(stderr, "iu_version %llx\n", iu_version);
1306 #endif
1307 } else if (!strcmp(featurestr, "fpu_version")) {
1308 char *err;
1310 fpu_version = strtol(val, &err, 0);
1311 if (!*val || *err) {
1312 fprintf(stderr, "bad numerical value %s\n", val);
1313 goto error;
1315 cpu_def->fpu_version = fpu_version;
1316 #ifdef DEBUG_FEATURES
1317 fprintf(stderr, "fpu_version %x\n", fpu_version);
1318 #endif
1319 } else if (!strcmp(featurestr, "mmu_version")) {
1320 char *err;
1322 mmu_version = strtol(val, &err, 0);
1323 if (!*val || *err) {
1324 fprintf(stderr, "bad numerical value %s\n", val);
1325 goto error;
1327 cpu_def->mmu_version = mmu_version;
1328 #ifdef DEBUG_FEATURES
1329 fprintf(stderr, "mmu_version %x\n", mmu_version);
1330 #endif
1331 } else if (!strcmp(featurestr, "nwindows")) {
1332 char *err;
1334 nwindows = strtol(val, &err, 0);
1335 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1336 nwindows < MIN_NWINDOWS) {
1337 fprintf(stderr, "bad numerical value %s\n", val);
1338 goto error;
1340 cpu_def->nwindows = nwindows;
1341 #ifdef DEBUG_FEATURES
1342 fprintf(stderr, "nwindows %d\n", nwindows);
1343 #endif
1344 } else {
1345 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1346 goto error;
1348 } else {
1349 fprintf(stderr, "feature string `%s' not in format "
1350 "(+feature|-feature|feature=xyz)\n", featurestr);
1351 goto error;
1353 featurestr = strtok(NULL, ",");
1355 cpu_def->features |= plus_features;
1356 cpu_def->features &= ~minus_features;
1357 #ifdef DEBUG_FEATURES
1358 print_features(stderr, fprintf, cpu_def->features, NULL);
1359 #endif
1360 free(s);
1361 return 0;
1363 error:
1364 free(s);
1365 return -1;
1368 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1370 unsigned int i;
1372 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1373 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1374 sparc_defs[i].name,
1375 sparc_defs[i].iu_version,
1376 sparc_defs[i].fpu_version,
1377 sparc_defs[i].mmu_version,
1378 sparc_defs[i].nwindows);
1379 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1380 ~sparc_defs[i].features, "-");
1381 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1382 sparc_defs[i].features, "+");
1383 (*cpu_fprintf)(f, "\n");
1385 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1386 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1387 (*cpu_fprintf)(f, "\n");
1388 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1389 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1390 (*cpu_fprintf)(f, "\n");
1391 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1392 "fpu_version mmu_version nwindows\n");
1395 void cpu_dump_state(CPUState *env, FILE *f,
1396 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1397 int flags)
1399 int i, x;
1401 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1402 env->npc);
1403 cpu_fprintf(f, "General Registers:\n");
1404 for (i = 0; i < 4; i++)
1405 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1406 cpu_fprintf(f, "\n");
1407 for (; i < 8; i++)
1408 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1409 cpu_fprintf(f, "\nCurrent Register Window:\n");
1410 for (x = 0; x < 3; x++) {
1411 for (i = 0; i < 4; i++)
1412 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1413 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1414 env->regwptr[i + x * 8]);
1415 cpu_fprintf(f, "\n");
1416 for (; i < 8; i++)
1417 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1418 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1419 env->regwptr[i + x * 8]);
1420 cpu_fprintf(f, "\n");
1422 cpu_fprintf(f, "\nFloating Point Registers:\n");
1423 for (i = 0; i < 32; i++) {
1424 if ((i & 3) == 0)
1425 cpu_fprintf(f, "%%f%02d:", i);
1426 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1427 if ((i & 3) == 3)
1428 cpu_fprintf(f, "\n");
1430 #ifdef TARGET_SPARC64
1431 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1432 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1433 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1434 "cleanwin %d cwp %d\n",
1435 env->cansave, env->canrestore, env->otherwin, env->wstate,
1436 env->cleanwin, env->nwindows - 1 - env->cwp);
1437 #else
1439 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1441 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1442 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1443 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1444 env->psrs?'S':'-', env->psrps?'P':'-',
1445 env->psret?'E':'-', env->wim);
1446 #endif
1447 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);