Fix non-ACPI Timer Interrupt Routing - v3
[qemu/aliguori-queue.git] / target-sparc / helper.c
blob5f9ad409edfcf2c757a4ddede080c2f3a477206a
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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <signal.h>
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "qemu-common.h"
31 //#define DEBUG_MMU
32 //#define DEBUG_FEATURES
34 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
36 /* Sparc MMU emulation */
38 /* thread support */
40 static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
42 void cpu_lock(void)
44 spin_lock(&global_cpu_lock);
47 void cpu_unlock(void)
49 spin_unlock(&global_cpu_lock);
52 #if defined(CONFIG_USER_ONLY)
54 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
55 int mmu_idx, int is_softmmu)
57 if (rw & 2)
58 env1->exception_index = TT_TFAULT;
59 else
60 env1->exception_index = TT_DFAULT;
61 return 1;
64 #else
66 #ifndef TARGET_SPARC64
68 * Sparc V8 Reference MMU (SRMMU)
70 static const int access_table[8][8] = {
71 { 0, 0, 0, 0, 8, 0, 12, 12 },
72 { 0, 0, 0, 0, 8, 0, 0, 0 },
73 { 8, 8, 0, 0, 0, 8, 12, 12 },
74 { 8, 8, 0, 0, 0, 8, 0, 0 },
75 { 8, 0, 8, 0, 8, 8, 12, 12 },
76 { 8, 0, 8, 0, 8, 0, 8, 0 },
77 { 8, 8, 8, 0, 8, 8, 12, 12 },
78 { 8, 8, 8, 0, 8, 8, 8, 0 }
81 static const int perm_table[2][8] = {
83 PAGE_READ,
84 PAGE_READ | PAGE_WRITE,
85 PAGE_READ | PAGE_EXEC,
86 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
87 PAGE_EXEC,
88 PAGE_READ | PAGE_WRITE,
89 PAGE_READ | PAGE_EXEC,
90 PAGE_READ | PAGE_WRITE | PAGE_EXEC
93 PAGE_READ,
94 PAGE_READ | PAGE_WRITE,
95 PAGE_READ | PAGE_EXEC,
96 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
97 PAGE_EXEC,
98 PAGE_READ,
104 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
105 int *prot, int *access_index,
106 target_ulong address, int rw, int mmu_idx)
108 int access_perms = 0;
109 target_phys_addr_t pde_ptr;
110 uint32_t pde;
111 target_ulong virt_addr;
112 int error_code = 0, is_dirty, is_user;
113 unsigned long page_offset;
115 is_user = mmu_idx == MMU_USER_IDX;
116 virt_addr = address & TARGET_PAGE_MASK;
118 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
119 // Boot mode: instruction fetches are taken from PROM
120 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
121 *physical = env->prom_addr | (address & 0x7ffffULL);
122 *prot = PAGE_READ | PAGE_EXEC;
123 return 0;
125 *physical = address;
126 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
127 return 0;
130 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
131 *physical = 0xffffffffffff0000ULL;
133 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
134 /* Context base + context number */
135 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
136 pde = ldl_phys(pde_ptr);
138 /* Ctx pde */
139 switch (pde & PTE_ENTRYTYPE_MASK) {
140 default:
141 case 0: /* Invalid */
142 return 1 << 2;
143 case 2: /* L0 PTE, maybe should not happen? */
144 case 3: /* Reserved */
145 return 4 << 2;
146 case 1: /* L0 PDE */
147 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
148 pde = ldl_phys(pde_ptr);
150 switch (pde & PTE_ENTRYTYPE_MASK) {
151 default:
152 case 0: /* Invalid */
153 return (1 << 8) | (1 << 2);
154 case 3: /* Reserved */
155 return (1 << 8) | (4 << 2);
156 case 1: /* L1 PDE */
157 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
158 pde = ldl_phys(pde_ptr);
160 switch (pde & PTE_ENTRYTYPE_MASK) {
161 default:
162 case 0: /* Invalid */
163 return (2 << 8) | (1 << 2);
164 case 3: /* Reserved */
165 return (2 << 8) | (4 << 2);
166 case 1: /* L2 PDE */
167 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
168 pde = ldl_phys(pde_ptr);
170 switch (pde & PTE_ENTRYTYPE_MASK) {
171 default:
172 case 0: /* Invalid */
173 return (3 << 8) | (1 << 2);
174 case 1: /* PDE, should not happen */
175 case 3: /* Reserved */
176 return (3 << 8) | (4 << 2);
177 case 2: /* L3 PTE */
178 virt_addr = address & TARGET_PAGE_MASK;
179 page_offset = (address & TARGET_PAGE_MASK) &
180 (TARGET_PAGE_SIZE - 1);
182 break;
183 case 2: /* L2 PTE */
184 virt_addr = address & ~0x3ffff;
185 page_offset = address & 0x3ffff;
187 break;
188 case 2: /* L1 PTE */
189 virt_addr = address & ~0xffffff;
190 page_offset = address & 0xffffff;
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);
202 /* check access */
203 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
204 error_code = access_table[*access_index][access_perms];
205 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
206 return error_code;
208 /* the page can be put in the TLB */
209 *prot = perm_table[is_user][access_perms];
210 if (!(pde & PG_MODIFIED_MASK)) {
211 /* only set write access if already dirty... otherwise wait
212 for dirty access */
213 *prot &= ~PAGE_WRITE;
216 /* Even if large ptes, we map only one 4KB page in the cache to
217 avoid filling it too fast */
218 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
219 return error_code;
222 /* Perform address translation */
223 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
224 int mmu_idx, int is_softmmu)
226 target_phys_addr_t paddr;
227 target_ulong vaddr;
228 int error_code = 0, prot, ret = 0, access_index;
230 error_code = get_physical_address(env, &paddr, &prot, &access_index,
231 address, rw, mmu_idx);
232 if (error_code == 0) {
233 vaddr = address & TARGET_PAGE_MASK;
234 paddr &= TARGET_PAGE_MASK;
235 #ifdef DEBUG_MMU
236 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
237 TARGET_FMT_lx "\n", address, paddr, vaddr);
238 #endif
239 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
240 return ret;
243 if (env->mmuregs[3]) /* Fault status register */
244 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
245 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
246 env->mmuregs[4] = address; /* Fault address register */
248 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
249 // No fault mode: if a mapping is available, just override
250 // permissions. If no mapping is available, redirect accesses to
251 // neverland. Fake/overridden mappings will be flushed when
252 // switching to normal mode.
253 vaddr = address & TARGET_PAGE_MASK;
254 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
255 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
256 return ret;
257 } else {
258 if (rw & 2)
259 env->exception_index = TT_TFAULT;
260 else
261 env->exception_index = TT_DFAULT;
262 return 1;
266 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
268 target_phys_addr_t pde_ptr;
269 uint32_t pde;
271 /* Context base + context number */
272 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
273 (env->mmuregs[2] << 2);
274 pde = ldl_phys(pde_ptr);
276 switch (pde & PTE_ENTRYTYPE_MASK) {
277 default:
278 case 0: /* Invalid */
279 case 2: /* PTE, maybe should not happen? */
280 case 3: /* Reserved */
281 return 0;
282 case 1: /* L1 PDE */
283 if (mmulev == 3)
284 return pde;
285 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
286 pde = ldl_phys(pde_ptr);
288 switch (pde & PTE_ENTRYTYPE_MASK) {
289 default:
290 case 0: /* Invalid */
291 case 3: /* Reserved */
292 return 0;
293 case 2: /* L1 PTE */
294 return pde;
295 case 1: /* L2 PDE */
296 if (mmulev == 2)
297 return pde;
298 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
299 pde = ldl_phys(pde_ptr);
301 switch (pde & PTE_ENTRYTYPE_MASK) {
302 default:
303 case 0: /* Invalid */
304 case 3: /* Reserved */
305 return 0;
306 case 2: /* L2 PTE */
307 return pde;
308 case 1: /* L3 PDE */
309 if (mmulev == 1)
310 return pde;
311 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
312 pde = ldl_phys(pde_ptr);
314 switch (pde & PTE_ENTRYTYPE_MASK) {
315 default:
316 case 0: /* Invalid */
317 case 1: /* PDE, should not happen */
318 case 3: /* Reserved */
319 return 0;
320 case 2: /* L3 PTE */
321 return pde;
326 return 0;
329 #ifdef DEBUG_MMU
330 void dump_mmu(CPUState *env)
332 target_ulong va, va1, va2;
333 unsigned int n, m, o;
334 target_phys_addr_t pde_ptr, pa;
335 uint32_t pde;
337 printf("MMU dump:\n");
338 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
339 pde = ldl_phys(pde_ptr);
340 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
341 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
342 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
343 pde = mmu_probe(env, va, 2);
344 if (pde) {
345 pa = cpu_get_phys_page_debug(env, va);
346 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
347 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
348 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
349 pde = mmu_probe(env, va1, 1);
350 if (pde) {
351 pa = cpu_get_phys_page_debug(env, va1);
352 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
353 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
354 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
355 pde = mmu_probe(env, va2, 0);
356 if (pde) {
357 pa = cpu_get_phys_page_debug(env, va2);
358 printf(" VA: " TARGET_FMT_lx ", PA: "
359 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
360 va2, pa, pde);
367 printf("MMU dump ends\n");
369 #endif /* DEBUG_MMU */
371 #else /* !TARGET_SPARC64 */
373 // 41 bit physical address space
374 static inline target_phys_addr_t ultrasparc_truncate_physical(uint64_t x)
376 return x & 0x1ffffffffffULL;
380 * UltraSparc IIi I/DMMUs
383 static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
385 return (x & mask) == (y & mask);
388 // Returns true if TTE tag is valid and matches virtual address value in context
389 // requires virtual address mask value calculated from TTE entry size
390 static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte,
391 uint64_t address, uint64_t context,
392 target_phys_addr_t *physical)
394 uint64_t mask;
396 switch ((tlb_tte >> 61) & 3) {
397 default:
398 case 0x0: // 8k
399 mask = 0xffffffffffffe000ULL;
400 break;
401 case 0x1: // 64k
402 mask = 0xffffffffffff0000ULL;
403 break;
404 case 0x2: // 512k
405 mask = 0xfffffffffff80000ULL;
406 break;
407 case 0x3: // 4M
408 mask = 0xffffffffffc00000ULL;
409 break;
412 // valid, context match, virtual address match?
413 if ((tlb_tte & 0x8000000000000000ULL) &&
414 compare_masked(context, tlb_tag, 0x1fff) &&
415 compare_masked(address, tlb_tag, mask))
417 // decode physical address
418 *physical = ((tlb_tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
419 return 1;
422 return 0;
425 static int get_physical_address_data(CPUState *env,
426 target_phys_addr_t *physical, int *prot,
427 target_ulong address, int rw, int is_user)
429 unsigned int i;
430 uint64_t context;
432 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
433 *physical = ultrasparc_truncate_physical(address);
434 *prot = PAGE_READ | PAGE_WRITE;
435 return 0;
438 context = env->dmmuregs[1] & 0x1fff;
440 for (i = 0; i < 64; i++) {
441 // ctx match, vaddr match, valid?
442 if (ultrasparc_tag_match(env->dtlb_tag[i], env->dtlb_tte[i],
443 address, context, physical)
445 // access ok?
446 if (((env->dtlb_tte[i] & 0x4) && is_user) ||
447 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
448 if (env->dmmuregs[3]) /* Fault status register */
449 env->dmmuregs[3] = 2; /* overflow (not read before
450 another fault) */
451 env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
452 env->dmmuregs[4] = address; /* Fault address register */
453 env->exception_index = TT_DFAULT;
454 #ifdef DEBUG_MMU
455 printf("DFAULT at 0x%" PRIx64 "\n", address);
456 #endif
457 return 1;
459 *prot = PAGE_READ;
460 if (env->dtlb_tte[i] & 0x2)
461 *prot |= PAGE_WRITE;
462 return 0;
465 #ifdef DEBUG_MMU
466 printf("DMISS at 0x%" PRIx64 "\n", address);
467 #endif
468 env->dmmuregs[6] = (address & ~0x1fffULL) | context;
469 env->exception_index = TT_DMISS;
470 return 1;
473 static int get_physical_address_code(CPUState *env,
474 target_phys_addr_t *physical, int *prot,
475 target_ulong address, int is_user)
477 unsigned int i;
478 uint64_t context;
480 if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
481 /* IMMU disabled */
482 *physical = ultrasparc_truncate_physical(address);
483 *prot = PAGE_EXEC;
484 return 0;
487 context = env->dmmuregs[1] & 0x1fff;
489 for (i = 0; i < 64; i++) {
490 // ctx match, vaddr match, valid?
491 if (ultrasparc_tag_match(env->itlb_tag[i], env->itlb_tte[i],
492 address, context, physical)
494 // access ok?
495 if ((env->itlb_tte[i] & 0x4) && is_user) {
496 if (env->immuregs[3]) /* Fault status register */
497 env->immuregs[3] = 2; /* overflow (not read before
498 another fault) */
499 env->immuregs[3] |= (is_user << 3) | 1;
500 env->exception_index = TT_TFAULT;
501 #ifdef DEBUG_MMU
502 printf("TFAULT at 0x%" PRIx64 "\n", address);
503 #endif
504 return 1;
506 *prot = PAGE_EXEC;
507 return 0;
510 #ifdef DEBUG_MMU
511 printf("TMISS at 0x%" PRIx64 "\n", address);
512 #endif
513 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
514 env->immuregs[6] = (address & ~0x1fffULL) | context;
515 env->exception_index = TT_TMISS;
516 return 1;
519 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
520 int *prot, int *access_index,
521 target_ulong address, int rw, int mmu_idx)
523 int is_user = mmu_idx == MMU_USER_IDX;
525 if (rw == 2)
526 return get_physical_address_code(env, physical, prot, address,
527 is_user);
528 else
529 return get_physical_address_data(env, physical, prot, address, rw,
530 is_user);
533 /* Perform address translation */
534 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
535 int mmu_idx, int is_softmmu)
537 target_ulong virt_addr, vaddr;
538 target_phys_addr_t paddr;
539 int error_code = 0, prot, ret = 0, access_index;
541 error_code = get_physical_address(env, &paddr, &prot, &access_index,
542 address, rw, mmu_idx);
543 if (error_code == 0) {
544 virt_addr = address & TARGET_PAGE_MASK;
545 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
546 (TARGET_PAGE_SIZE - 1));
547 #ifdef DEBUG_MMU
548 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
549 "\n", address, paddr, vaddr);
550 #endif
551 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
552 return ret;
554 // XXX
555 return 1;
558 #ifdef DEBUG_MMU
559 void dump_mmu(CPUState *env)
561 unsigned int i;
562 const char *mask;
564 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
565 env->dmmuregs[1], env->dmmuregs[2]);
566 if ((env->lsu & DMMU_E) == 0) {
567 printf("DMMU disabled\n");
568 } else {
569 printf("DMMU dump:\n");
570 for (i = 0; i < 64; i++) {
571 switch ((env->dtlb_tte[i] >> 61) & 3) {
572 default:
573 case 0x0:
574 mask = " 8k";
575 break;
576 case 0x1:
577 mask = " 64k";
578 break;
579 case 0x2:
580 mask = "512k";
581 break;
582 case 0x3:
583 mask = " 4M";
584 break;
586 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
587 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
588 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
589 env->dtlb_tag[i] & ~0x1fffULL,
590 env->dtlb_tte[i] & 0x1ffffffe000ULL,
591 mask,
592 env->dtlb_tte[i] & 0x4? "priv": "user",
593 env->dtlb_tte[i] & 0x2? "RW": "RO",
594 env->dtlb_tte[i] & 0x40? "locked": "unlocked",
595 env->dtlb_tag[i] & 0x1fffULL);
599 if ((env->lsu & IMMU_E) == 0) {
600 printf("IMMU disabled\n");
601 } else {
602 printf("IMMU dump:\n");
603 for (i = 0; i < 64; i++) {
604 switch ((env->itlb_tte[i] >> 61) & 3) {
605 default:
606 case 0x0:
607 mask = " 8k";
608 break;
609 case 0x1:
610 mask = " 64k";
611 break;
612 case 0x2:
613 mask = "512k";
614 break;
615 case 0x3:
616 mask = " 4M";
617 break;
619 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
620 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
621 ", %s, %s, %s, ctx %" PRId64 "\n",
622 env->itlb_tag[i] & ~0x1fffULL,
623 env->itlb_tte[i] & 0x1ffffffe000ULL,
624 mask,
625 env->itlb_tte[i] & 0x4? "priv": "user",
626 env->itlb_tte[i] & 0x40? "locked": "unlocked",
627 env->itlb_tag[i] & 0x1fffULL);
632 #endif /* DEBUG_MMU */
634 #endif /* TARGET_SPARC64 */
635 #endif /* !CONFIG_USER_ONLY */
638 #if defined(CONFIG_USER_ONLY)
639 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
641 return addr;
644 #else
645 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
647 target_phys_addr_t phys_addr;
648 int prot, access_index;
650 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
651 MMU_KERNEL_IDX) != 0)
652 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
653 0, MMU_KERNEL_IDX) != 0)
654 return -1;
655 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
656 return -1;
657 return phys_addr;
659 #endif
661 void cpu_reset(CPUSPARCState *env)
663 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
664 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
665 log_cpu_state(env, 0);
668 tlb_flush(env, 1);
669 env->cwp = 0;
670 #ifndef TARGET_SPARC64
671 env->wim = 1;
672 #endif
673 env->regwptr = env->regbase + (env->cwp * 16);
674 #if defined(CONFIG_USER_ONLY)
675 #ifdef TARGET_SPARC64
676 env->cleanwin = env->nwindows - 2;
677 env->cansave = env->nwindows - 2;
678 env->pstate = PS_RMO | PS_PEF | PS_IE;
679 env->asi = 0x82; // Primary no-fault
680 #endif
681 #else
682 #if !defined(TARGET_SPARC64)
683 env->psret = 0;
684 #endif
685 env->psrs = 1;
686 env->psrps = 1;
687 CC_OP = CC_OP_FLAGS;
688 #ifdef TARGET_SPARC64
689 env->pstate = PS_PRIV;
690 env->hpstate = HS_PRIV;
691 env->tsptr = &env->ts[env->tl & MAXTL_MASK];
692 env->lsu = 0;
693 #else
694 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
695 env->mmuregs[0] |= env->def->mmu_bm;
696 #endif
697 env->pc = 0;
698 env->npc = env->pc + 4;
699 #endif
702 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
704 sparc_def_t def1, *def = &def1;
706 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
707 return -1;
709 env->def = qemu_mallocz(sizeof(*def));
710 memcpy(env->def, def, sizeof(*def));
711 #if defined(CONFIG_USER_ONLY)
712 if ((env->def->features & CPU_FEATURE_FLOAT))
713 env->def->features |= CPU_FEATURE_FLOAT128;
714 #endif
715 env->cpu_model_str = cpu_model;
716 env->version = def->iu_version;
717 env->fsr = def->fpu_version;
718 env->nwindows = def->nwindows;
719 #if !defined(TARGET_SPARC64)
720 env->mmuregs[0] |= def->mmu_version;
721 cpu_sparc_set_id(env, 0);
722 env->mxccregs[7] |= def->mxcc_version;
723 #else
724 env->mmu_version = def->mmu_version;
725 env->maxtl = def->maxtl;
726 env->version |= def->maxtl << 8;
727 env->version |= def->nwindows - 1;
728 #endif
729 return 0;
732 static void cpu_sparc_close(CPUSPARCState *env)
734 free(env->def);
735 free(env);
738 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
740 CPUSPARCState *env;
742 env = qemu_mallocz(sizeof(CPUSPARCState));
743 cpu_exec_init(env);
745 gen_intermediate_code_init(env);
747 if (cpu_sparc_register(env, cpu_model) < 0) {
748 cpu_sparc_close(env);
749 return NULL;
751 cpu_reset(env);
752 qemu_init_vcpu(env);
754 return env;
757 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
759 #if !defined(TARGET_SPARC64)
760 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
761 #endif
764 static const sparc_def_t sparc_defs[] = {
765 #ifdef TARGET_SPARC64
767 .name = "Fujitsu Sparc64",
768 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
769 .fpu_version = 0x00000000,
770 .mmu_version = mmu_us_12,
771 .nwindows = 4,
772 .maxtl = 4,
773 .features = CPU_DEFAULT_FEATURES,
776 .name = "Fujitsu Sparc64 III",
777 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
778 .fpu_version = 0x00000000,
779 .mmu_version = mmu_us_12,
780 .nwindows = 5,
781 .maxtl = 4,
782 .features = CPU_DEFAULT_FEATURES,
785 .name = "Fujitsu Sparc64 IV",
786 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
787 .fpu_version = 0x00000000,
788 .mmu_version = mmu_us_12,
789 .nwindows = 8,
790 .maxtl = 5,
791 .features = CPU_DEFAULT_FEATURES,
794 .name = "Fujitsu Sparc64 V",
795 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
796 .fpu_version = 0x00000000,
797 .mmu_version = mmu_us_12,
798 .nwindows = 8,
799 .maxtl = 5,
800 .features = CPU_DEFAULT_FEATURES,
803 .name = "TI UltraSparc I",
804 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
805 .fpu_version = 0x00000000,
806 .mmu_version = mmu_us_12,
807 .nwindows = 8,
808 .maxtl = 5,
809 .features = CPU_DEFAULT_FEATURES,
812 .name = "TI UltraSparc II",
813 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
814 .fpu_version = 0x00000000,
815 .mmu_version = mmu_us_12,
816 .nwindows = 8,
817 .maxtl = 5,
818 .features = CPU_DEFAULT_FEATURES,
821 .name = "TI UltraSparc IIi",
822 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
823 .fpu_version = 0x00000000,
824 .mmu_version = mmu_us_12,
825 .nwindows = 8,
826 .maxtl = 5,
827 .features = CPU_DEFAULT_FEATURES,
830 .name = "TI UltraSparc IIe",
831 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
832 .fpu_version = 0x00000000,
833 .mmu_version = mmu_us_12,
834 .nwindows = 8,
835 .maxtl = 5,
836 .features = CPU_DEFAULT_FEATURES,
839 .name = "Sun UltraSparc III",
840 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
841 .fpu_version = 0x00000000,
842 .mmu_version = mmu_us_12,
843 .nwindows = 8,
844 .maxtl = 5,
845 .features = CPU_DEFAULT_FEATURES,
848 .name = "Sun UltraSparc III Cu",
849 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
850 .fpu_version = 0x00000000,
851 .mmu_version = mmu_us_3,
852 .nwindows = 8,
853 .maxtl = 5,
854 .features = CPU_DEFAULT_FEATURES,
857 .name = "Sun UltraSparc IIIi",
858 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
859 .fpu_version = 0x00000000,
860 .mmu_version = mmu_us_12,
861 .nwindows = 8,
862 .maxtl = 5,
863 .features = CPU_DEFAULT_FEATURES,
866 .name = "Sun UltraSparc IV",
867 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
868 .fpu_version = 0x00000000,
869 .mmu_version = mmu_us_4,
870 .nwindows = 8,
871 .maxtl = 5,
872 .features = CPU_DEFAULT_FEATURES,
875 .name = "Sun UltraSparc IV+",
876 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
877 .fpu_version = 0x00000000,
878 .mmu_version = mmu_us_12,
879 .nwindows = 8,
880 .maxtl = 5,
881 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
884 .name = "Sun UltraSparc IIIi+",
885 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
886 .fpu_version = 0x00000000,
887 .mmu_version = mmu_us_3,
888 .nwindows = 8,
889 .maxtl = 5,
890 .features = CPU_DEFAULT_FEATURES,
893 .name = "Sun UltraSparc T1",
894 // defined in sparc_ifu_fdp.v and ctu.h
895 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
896 .fpu_version = 0x00000000,
897 .mmu_version = mmu_sun4v,
898 .nwindows = 8,
899 .maxtl = 6,
900 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
901 | CPU_FEATURE_GL,
904 .name = "Sun UltraSparc T2",
905 // defined in tlu_asi_ctl.v and n2_revid_cust.v
906 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
907 .fpu_version = 0x00000000,
908 .mmu_version = mmu_sun4v,
909 .nwindows = 8,
910 .maxtl = 6,
911 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
912 | CPU_FEATURE_GL,
915 .name = "NEC UltraSparc I",
916 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
917 .fpu_version = 0x00000000,
918 .mmu_version = mmu_us_12,
919 .nwindows = 8,
920 .maxtl = 5,
921 .features = CPU_DEFAULT_FEATURES,
923 #else
925 .name = "Fujitsu MB86900",
926 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
927 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
928 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
929 .mmu_bm = 0x00004000,
930 .mmu_ctpr_mask = 0x007ffff0,
931 .mmu_cxr_mask = 0x0000003f,
932 .mmu_sfsr_mask = 0xffffffff,
933 .mmu_trcr_mask = 0xffffffff,
934 .nwindows = 7,
935 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
938 .name = "Fujitsu MB86904",
939 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
940 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
941 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
942 .mmu_bm = 0x00004000,
943 .mmu_ctpr_mask = 0x00ffffc0,
944 .mmu_cxr_mask = 0x000000ff,
945 .mmu_sfsr_mask = 0x00016fff,
946 .mmu_trcr_mask = 0x00ffffff,
947 .nwindows = 8,
948 .features = CPU_DEFAULT_FEATURES,
951 .name = "Fujitsu MB86907",
952 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
953 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
954 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
955 .mmu_bm = 0x00004000,
956 .mmu_ctpr_mask = 0xffffffc0,
957 .mmu_cxr_mask = 0x000000ff,
958 .mmu_sfsr_mask = 0x00016fff,
959 .mmu_trcr_mask = 0xffffffff,
960 .nwindows = 8,
961 .features = CPU_DEFAULT_FEATURES,
964 .name = "LSI L64811",
965 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
966 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
967 .mmu_version = 0x10 << 24,
968 .mmu_bm = 0x00004000,
969 .mmu_ctpr_mask = 0x007ffff0,
970 .mmu_cxr_mask = 0x0000003f,
971 .mmu_sfsr_mask = 0xffffffff,
972 .mmu_trcr_mask = 0xffffffff,
973 .nwindows = 8,
974 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
975 CPU_FEATURE_FSMULD,
978 .name = "Cypress CY7C601",
979 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
980 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
981 .mmu_version = 0x10 << 24,
982 .mmu_bm = 0x00004000,
983 .mmu_ctpr_mask = 0x007ffff0,
984 .mmu_cxr_mask = 0x0000003f,
985 .mmu_sfsr_mask = 0xffffffff,
986 .mmu_trcr_mask = 0xffffffff,
987 .nwindows = 8,
988 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
989 CPU_FEATURE_FSMULD,
992 .name = "Cypress CY7C611",
993 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
994 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
995 .mmu_version = 0x10 << 24,
996 .mmu_bm = 0x00004000,
997 .mmu_ctpr_mask = 0x007ffff0,
998 .mmu_cxr_mask = 0x0000003f,
999 .mmu_sfsr_mask = 0xffffffff,
1000 .mmu_trcr_mask = 0xffffffff,
1001 .nwindows = 8,
1002 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1003 CPU_FEATURE_FSMULD,
1006 .name = "TI MicroSparc I",
1007 .iu_version = 0x41000000,
1008 .fpu_version = 4 << 17,
1009 .mmu_version = 0x41000000,
1010 .mmu_bm = 0x00004000,
1011 .mmu_ctpr_mask = 0x007ffff0,
1012 .mmu_cxr_mask = 0x0000003f,
1013 .mmu_sfsr_mask = 0x00016fff,
1014 .mmu_trcr_mask = 0x0000003f,
1015 .nwindows = 7,
1016 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1017 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1018 CPU_FEATURE_FMUL,
1021 .name = "TI MicroSparc II",
1022 .iu_version = 0x42000000,
1023 .fpu_version = 4 << 17,
1024 .mmu_version = 0x02000000,
1025 .mmu_bm = 0x00004000,
1026 .mmu_ctpr_mask = 0x00ffffc0,
1027 .mmu_cxr_mask = 0x000000ff,
1028 .mmu_sfsr_mask = 0x00016fff,
1029 .mmu_trcr_mask = 0x00ffffff,
1030 .nwindows = 8,
1031 .features = CPU_DEFAULT_FEATURES,
1034 .name = "TI MicroSparc IIep",
1035 .iu_version = 0x42000000,
1036 .fpu_version = 4 << 17,
1037 .mmu_version = 0x04000000,
1038 .mmu_bm = 0x00004000,
1039 .mmu_ctpr_mask = 0x00ffffc0,
1040 .mmu_cxr_mask = 0x000000ff,
1041 .mmu_sfsr_mask = 0x00016bff,
1042 .mmu_trcr_mask = 0x00ffffff,
1043 .nwindows = 8,
1044 .features = CPU_DEFAULT_FEATURES,
1047 .name = "TI SuperSparc 40", // STP1020NPGA
1048 .iu_version = 0x41000000, // SuperSPARC 2.x
1049 .fpu_version = 0 << 17,
1050 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1051 .mmu_bm = 0x00002000,
1052 .mmu_ctpr_mask = 0xffffffc0,
1053 .mmu_cxr_mask = 0x0000ffff,
1054 .mmu_sfsr_mask = 0xffffffff,
1055 .mmu_trcr_mask = 0xffffffff,
1056 .nwindows = 8,
1057 .features = CPU_DEFAULT_FEATURES,
1060 .name = "TI SuperSparc 50", // STP1020PGA
1061 .iu_version = 0x40000000, // SuperSPARC 3.x
1062 .fpu_version = 0 << 17,
1063 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1064 .mmu_bm = 0x00002000,
1065 .mmu_ctpr_mask = 0xffffffc0,
1066 .mmu_cxr_mask = 0x0000ffff,
1067 .mmu_sfsr_mask = 0xffffffff,
1068 .mmu_trcr_mask = 0xffffffff,
1069 .nwindows = 8,
1070 .features = CPU_DEFAULT_FEATURES,
1073 .name = "TI SuperSparc 51",
1074 .iu_version = 0x40000000, // SuperSPARC 3.x
1075 .fpu_version = 0 << 17,
1076 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1077 .mmu_bm = 0x00002000,
1078 .mmu_ctpr_mask = 0xffffffc0,
1079 .mmu_cxr_mask = 0x0000ffff,
1080 .mmu_sfsr_mask = 0xffffffff,
1081 .mmu_trcr_mask = 0xffffffff,
1082 .mxcc_version = 0x00000104,
1083 .nwindows = 8,
1084 .features = CPU_DEFAULT_FEATURES,
1087 .name = "TI SuperSparc 60", // STP1020APGA
1088 .iu_version = 0x40000000, // SuperSPARC 3.x
1089 .fpu_version = 0 << 17,
1090 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1091 .mmu_bm = 0x00002000,
1092 .mmu_ctpr_mask = 0xffffffc0,
1093 .mmu_cxr_mask = 0x0000ffff,
1094 .mmu_sfsr_mask = 0xffffffff,
1095 .mmu_trcr_mask = 0xffffffff,
1096 .nwindows = 8,
1097 .features = CPU_DEFAULT_FEATURES,
1100 .name = "TI SuperSparc 61",
1101 .iu_version = 0x44000000, // SuperSPARC 3.x
1102 .fpu_version = 0 << 17,
1103 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1104 .mmu_bm = 0x00002000,
1105 .mmu_ctpr_mask = 0xffffffc0,
1106 .mmu_cxr_mask = 0x0000ffff,
1107 .mmu_sfsr_mask = 0xffffffff,
1108 .mmu_trcr_mask = 0xffffffff,
1109 .mxcc_version = 0x00000104,
1110 .nwindows = 8,
1111 .features = CPU_DEFAULT_FEATURES,
1114 .name = "TI SuperSparc II",
1115 .iu_version = 0x40000000, // SuperSPARC II 1.x
1116 .fpu_version = 0 << 17,
1117 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1118 .mmu_bm = 0x00002000,
1119 .mmu_ctpr_mask = 0xffffffc0,
1120 .mmu_cxr_mask = 0x0000ffff,
1121 .mmu_sfsr_mask = 0xffffffff,
1122 .mmu_trcr_mask = 0xffffffff,
1123 .mxcc_version = 0x00000104,
1124 .nwindows = 8,
1125 .features = CPU_DEFAULT_FEATURES,
1128 .name = "Ross RT625",
1129 .iu_version = 0x1e000000,
1130 .fpu_version = 1 << 17,
1131 .mmu_version = 0x1e000000,
1132 .mmu_bm = 0x00004000,
1133 .mmu_ctpr_mask = 0x007ffff0,
1134 .mmu_cxr_mask = 0x0000003f,
1135 .mmu_sfsr_mask = 0xffffffff,
1136 .mmu_trcr_mask = 0xffffffff,
1137 .nwindows = 8,
1138 .features = CPU_DEFAULT_FEATURES,
1141 .name = "Ross RT620",
1142 .iu_version = 0x1f000000,
1143 .fpu_version = 1 << 17,
1144 .mmu_version = 0x1f000000,
1145 .mmu_bm = 0x00004000,
1146 .mmu_ctpr_mask = 0x007ffff0,
1147 .mmu_cxr_mask = 0x0000003f,
1148 .mmu_sfsr_mask = 0xffffffff,
1149 .mmu_trcr_mask = 0xffffffff,
1150 .nwindows = 8,
1151 .features = CPU_DEFAULT_FEATURES,
1154 .name = "BIT B5010",
1155 .iu_version = 0x20000000,
1156 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1157 .mmu_version = 0x20000000,
1158 .mmu_bm = 0x00004000,
1159 .mmu_ctpr_mask = 0x007ffff0,
1160 .mmu_cxr_mask = 0x0000003f,
1161 .mmu_sfsr_mask = 0xffffffff,
1162 .mmu_trcr_mask = 0xffffffff,
1163 .nwindows = 8,
1164 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1165 CPU_FEATURE_FSMULD,
1168 .name = "Matsushita MN10501",
1169 .iu_version = 0x50000000,
1170 .fpu_version = 0 << 17,
1171 .mmu_version = 0x50000000,
1172 .mmu_bm = 0x00004000,
1173 .mmu_ctpr_mask = 0x007ffff0,
1174 .mmu_cxr_mask = 0x0000003f,
1175 .mmu_sfsr_mask = 0xffffffff,
1176 .mmu_trcr_mask = 0xffffffff,
1177 .nwindows = 8,
1178 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1179 CPU_FEATURE_FSMULD,
1182 .name = "Weitek W8601",
1183 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1184 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1185 .mmu_version = 0x10 << 24,
1186 .mmu_bm = 0x00004000,
1187 .mmu_ctpr_mask = 0x007ffff0,
1188 .mmu_cxr_mask = 0x0000003f,
1189 .mmu_sfsr_mask = 0xffffffff,
1190 .mmu_trcr_mask = 0xffffffff,
1191 .nwindows = 8,
1192 .features = CPU_DEFAULT_FEATURES,
1195 .name = "LEON2",
1196 .iu_version = 0xf2000000,
1197 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1198 .mmu_version = 0xf2000000,
1199 .mmu_bm = 0x00004000,
1200 .mmu_ctpr_mask = 0x007ffff0,
1201 .mmu_cxr_mask = 0x0000003f,
1202 .mmu_sfsr_mask = 0xffffffff,
1203 .mmu_trcr_mask = 0xffffffff,
1204 .nwindows = 8,
1205 .features = CPU_DEFAULT_FEATURES,
1208 .name = "LEON3",
1209 .iu_version = 0xf3000000,
1210 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1211 .mmu_version = 0xf3000000,
1212 .mmu_bm = 0x00004000,
1213 .mmu_ctpr_mask = 0x007ffff0,
1214 .mmu_cxr_mask = 0x0000003f,
1215 .mmu_sfsr_mask = 0xffffffff,
1216 .mmu_trcr_mask = 0xffffffff,
1217 .nwindows = 8,
1218 .features = CPU_DEFAULT_FEATURES,
1220 #endif
1223 static const char * const feature_name[] = {
1224 "float",
1225 "float128",
1226 "swap",
1227 "mul",
1228 "div",
1229 "flush",
1230 "fsqrt",
1231 "fmul",
1232 "vis1",
1233 "vis2",
1234 "fsmuld",
1235 "hypv",
1236 "cmt",
1237 "gl",
1240 static void print_features(FILE *f,
1241 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1242 uint32_t features, const char *prefix)
1244 unsigned int i;
1246 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1247 if (feature_name[i] && (features & (1 << i))) {
1248 if (prefix)
1249 (*cpu_fprintf)(f, "%s", prefix);
1250 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1254 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1256 unsigned int i;
1258 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1259 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1260 *features |= 1 << i;
1261 return;
1263 fprintf(stderr, "CPU feature %s not found\n", flagname);
1266 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1268 unsigned int i;
1269 const sparc_def_t *def = NULL;
1270 char *s = strdup(cpu_model);
1271 char *featurestr, *name = strtok(s, ",");
1272 uint32_t plus_features = 0;
1273 uint32_t minus_features = 0;
1274 long long iu_version;
1275 uint32_t fpu_version, mmu_version, nwindows;
1277 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1278 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1279 def = &sparc_defs[i];
1282 if (!def)
1283 goto error;
1284 memcpy(cpu_def, def, sizeof(*def));
1286 featurestr = strtok(NULL, ",");
1287 while (featurestr) {
1288 char *val;
1290 if (featurestr[0] == '+') {
1291 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1292 } else if (featurestr[0] == '-') {
1293 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1294 } else if ((val = strchr(featurestr, '='))) {
1295 *val = 0; val++;
1296 if (!strcmp(featurestr, "iu_version")) {
1297 char *err;
1299 iu_version = strtoll(val, &err, 0);
1300 if (!*val || *err) {
1301 fprintf(stderr, "bad numerical value %s\n", val);
1302 goto error;
1304 cpu_def->iu_version = iu_version;
1305 #ifdef DEBUG_FEATURES
1306 fprintf(stderr, "iu_version %llx\n", iu_version);
1307 #endif
1308 } else if (!strcmp(featurestr, "fpu_version")) {
1309 char *err;
1311 fpu_version = strtol(val, &err, 0);
1312 if (!*val || *err) {
1313 fprintf(stderr, "bad numerical value %s\n", val);
1314 goto error;
1316 cpu_def->fpu_version = fpu_version;
1317 #ifdef DEBUG_FEATURES
1318 fprintf(stderr, "fpu_version %llx\n", fpu_version);
1319 #endif
1320 } else if (!strcmp(featurestr, "mmu_version")) {
1321 char *err;
1323 mmu_version = strtol(val, &err, 0);
1324 if (!*val || *err) {
1325 fprintf(stderr, "bad numerical value %s\n", val);
1326 goto error;
1328 cpu_def->mmu_version = mmu_version;
1329 #ifdef DEBUG_FEATURES
1330 fprintf(stderr, "mmu_version %llx\n", mmu_version);
1331 #endif
1332 } else if (!strcmp(featurestr, "nwindows")) {
1333 char *err;
1335 nwindows = strtol(val, &err, 0);
1336 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1337 nwindows < MIN_NWINDOWS) {
1338 fprintf(stderr, "bad numerical value %s\n", val);
1339 goto error;
1341 cpu_def->nwindows = nwindows;
1342 #ifdef DEBUG_FEATURES
1343 fprintf(stderr, "nwindows %d\n", nwindows);
1344 #endif
1345 } else {
1346 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1347 goto error;
1349 } else {
1350 fprintf(stderr, "feature string `%s' not in format "
1351 "(+feature|-feature|feature=xyz)\n", featurestr);
1352 goto error;
1354 featurestr = strtok(NULL, ",");
1356 cpu_def->features |= plus_features;
1357 cpu_def->features &= ~minus_features;
1358 #ifdef DEBUG_FEATURES
1359 print_features(stderr, fprintf, cpu_def->features, NULL);
1360 #endif
1361 free(s);
1362 return 0;
1364 error:
1365 free(s);
1366 return -1;
1369 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1371 unsigned int i;
1373 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1374 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1375 sparc_defs[i].name,
1376 sparc_defs[i].iu_version,
1377 sparc_defs[i].fpu_version,
1378 sparc_defs[i].mmu_version,
1379 sparc_defs[i].nwindows);
1380 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1381 ~sparc_defs[i].features, "-");
1382 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1383 sparc_defs[i].features, "+");
1384 (*cpu_fprintf)(f, "\n");
1386 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1387 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1388 (*cpu_fprintf)(f, "\n");
1389 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1390 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1391 (*cpu_fprintf)(f, "\n");
1392 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1393 "fpu_version mmu_version nwindows\n");
1396 void cpu_dump_state(CPUState *env, FILE *f,
1397 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1398 int flags)
1400 int i, x;
1402 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1403 env->npc);
1404 cpu_fprintf(f, "General Registers:\n");
1405 for (i = 0; i < 4; i++)
1406 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1407 cpu_fprintf(f, "\n");
1408 for (; i < 8; i++)
1409 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1410 cpu_fprintf(f, "\nCurrent Register Window:\n");
1411 for (x = 0; x < 3; x++) {
1412 for (i = 0; i < 4; i++)
1413 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1414 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1415 env->regwptr[i + x * 8]);
1416 cpu_fprintf(f, "\n");
1417 for (; i < 8; i++)
1418 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1419 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1420 env->regwptr[i + x * 8]);
1421 cpu_fprintf(f, "\n");
1423 cpu_fprintf(f, "\nFloating Point Registers:\n");
1424 for (i = 0; i < 32; i++) {
1425 if ((i & 3) == 0)
1426 cpu_fprintf(f, "%%f%02d:", i);
1427 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1428 if ((i & 3) == 3)
1429 cpu_fprintf(f, "\n");
1431 #ifdef TARGET_SPARC64
1432 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1433 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1434 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1435 "cleanwin %d cwp %d\n",
1436 env->cansave, env->canrestore, env->otherwin, env->wstate,
1437 env->cleanwin, env->nwindows - 1 - env->cwp);
1438 #else
1440 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1442 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1443 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1444 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1445 env->psrs?'S':'-', env->psrps?'P':'-',
1446 env->psret?'E':'-', env->wim);
1447 #endif
1448 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);