slirp: Clean up updtime
[qemu/ar7.git] / target-sparc / helper.c
blob2f41418c85cc19c22bb3412191a40cfd8d40c51c
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 * UltraSparc IIi I/DMMUs
375 static int get_physical_address_data(CPUState *env,
376 target_phys_addr_t *physical, int *prot,
377 target_ulong address, int rw, int is_user)
379 target_ulong mask;
380 unsigned int i;
382 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
383 *physical = address;
384 *prot = PAGE_READ | PAGE_WRITE;
385 return 0;
388 for (i = 0; i < 64; i++) {
389 switch ((env->dtlb_tte[i] >> 61) & 3) {
390 default:
391 case 0x0: // 8k
392 mask = 0xffffffffffffe000ULL;
393 break;
394 case 0x1: // 64k
395 mask = 0xffffffffffff0000ULL;
396 break;
397 case 0x2: // 512k
398 mask = 0xfffffffffff80000ULL;
399 break;
400 case 0x3: // 4M
401 mask = 0xffffffffffc00000ULL;
402 break;
404 // ctx match, vaddr match, valid?
405 if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
406 (address & mask) == (env->dtlb_tag[i] & mask) &&
407 (env->dtlb_tte[i] & 0x8000000000000000ULL)) {
408 // access ok?
409 if (((env->dtlb_tte[i] & 0x4) && is_user) ||
410 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
411 if (env->dmmuregs[3]) /* Fault status register */
412 env->dmmuregs[3] = 2; /* overflow (not read before
413 another fault) */
414 env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
415 env->dmmuregs[4] = address; /* Fault address register */
416 env->exception_index = TT_DFAULT;
417 #ifdef DEBUG_MMU
418 printf("DFAULT at 0x%" PRIx64 "\n", address);
419 #endif
420 return 1;
422 *physical = ((env->dtlb_tte[i] & mask) | (address & ~mask)) &
423 0x1ffffffe000ULL;
424 *prot = PAGE_READ;
425 if (env->dtlb_tte[i] & 0x2)
426 *prot |= PAGE_WRITE;
427 return 0;
430 #ifdef DEBUG_MMU
431 printf("DMISS at 0x%" PRIx64 "\n", address);
432 #endif
433 env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
434 env->exception_index = TT_DMISS;
435 return 1;
438 static int get_physical_address_code(CPUState *env,
439 target_phys_addr_t *physical, int *prot,
440 target_ulong address, int is_user)
442 target_ulong mask;
443 unsigned int i;
445 if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
446 *physical = address;
447 *prot = PAGE_EXEC;
448 return 0;
451 for (i = 0; i < 64; i++) {
452 switch ((env->itlb_tte[i] >> 61) & 3) {
453 default:
454 case 0x0: // 8k
455 mask = 0xffffffffffffe000ULL;
456 break;
457 case 0x1: // 64k
458 mask = 0xffffffffffff0000ULL;
459 break;
460 case 0x2: // 512k
461 mask = 0xfffffffffff80000ULL;
462 break;
463 case 0x3: // 4M
464 mask = 0xffffffffffc00000ULL;
465 break;
467 // ctx match, vaddr match, valid?
468 if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
469 (address & mask) == (env->itlb_tag[i] & mask) &&
470 (env->itlb_tte[i] & 0x8000000000000000ULL)) {
471 // access ok?
472 if ((env->itlb_tte[i] & 0x4) && is_user) {
473 if (env->immuregs[3]) /* Fault status register */
474 env->immuregs[3] = 2; /* overflow (not read before
475 another fault) */
476 env->immuregs[3] |= (is_user << 3) | 1;
477 env->exception_index = TT_TFAULT;
478 #ifdef DEBUG_MMU
479 printf("TFAULT at 0x%" PRIx64 "\n", address);
480 #endif
481 return 1;
483 *physical = ((env->itlb_tte[i] & mask) | (address & ~mask)) &
484 0x1ffffffe000ULL;
485 *prot = PAGE_EXEC;
486 return 0;
489 #ifdef DEBUG_MMU
490 printf("TMISS at 0x%" PRIx64 "\n", address);
491 #endif
492 /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
493 env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
494 env->exception_index = TT_TMISS;
495 return 1;
498 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
499 int *prot, int *access_index,
500 target_ulong address, int rw, int mmu_idx)
502 int is_user = mmu_idx == MMU_USER_IDX;
504 if (rw == 2)
505 return get_physical_address_code(env, physical, prot, address,
506 is_user);
507 else
508 return get_physical_address_data(env, physical, prot, address, rw,
509 is_user);
512 /* Perform address translation */
513 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
514 int mmu_idx, int is_softmmu)
516 target_ulong virt_addr, vaddr;
517 target_phys_addr_t paddr;
518 int error_code = 0, prot, ret = 0, access_index;
520 error_code = get_physical_address(env, &paddr, &prot, &access_index,
521 address, rw, mmu_idx);
522 if (error_code == 0) {
523 virt_addr = address & TARGET_PAGE_MASK;
524 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
525 (TARGET_PAGE_SIZE - 1));
526 #ifdef DEBUG_MMU
527 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
528 "\n", address, paddr, vaddr);
529 #endif
530 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
531 return ret;
533 // XXX
534 return 1;
537 #ifdef DEBUG_MMU
538 void dump_mmu(CPUState *env)
540 unsigned int i;
541 const char *mask;
543 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
544 env->dmmuregs[1], env->dmmuregs[2]);
545 if ((env->lsu & DMMU_E) == 0) {
546 printf("DMMU disabled\n");
547 } else {
548 printf("DMMU dump:\n");
549 for (i = 0; i < 64; i++) {
550 switch ((env->dtlb_tte[i] >> 61) & 3) {
551 default:
552 case 0x0:
553 mask = " 8k";
554 break;
555 case 0x1:
556 mask = " 64k";
557 break;
558 case 0x2:
559 mask = "512k";
560 break;
561 case 0x3:
562 mask = " 4M";
563 break;
565 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
566 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
567 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
568 env->dtlb_tag[i] & ~0x1fffULL,
569 env->dtlb_tte[i] & 0x1ffffffe000ULL,
570 mask,
571 env->dtlb_tte[i] & 0x4? "priv": "user",
572 env->dtlb_tte[i] & 0x2? "RW": "RO",
573 env->dtlb_tte[i] & 0x40? "locked": "unlocked",
574 env->dtlb_tag[i] & 0x1fffULL);
578 if ((env->lsu & IMMU_E) == 0) {
579 printf("IMMU disabled\n");
580 } else {
581 printf("IMMU dump:\n");
582 for (i = 0; i < 64; i++) {
583 switch ((env->itlb_tte[i] >> 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->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
599 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
600 ", %s, %s, %s, ctx %" PRId64 "\n",
601 env->itlb_tag[i] & ~0x1fffULL,
602 env->itlb_tte[i] & 0x1ffffffe000ULL,
603 mask,
604 env->itlb_tte[i] & 0x4? "priv": "user",
605 env->itlb_tte[i] & 0x40? "locked": "unlocked",
606 env->itlb_tag[i] & 0x1fffULL);
611 #endif /* DEBUG_MMU */
613 #endif /* TARGET_SPARC64 */
614 #endif /* !CONFIG_USER_ONLY */
617 #if defined(CONFIG_USER_ONLY)
618 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
620 return addr;
623 #else
624 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
626 target_phys_addr_t phys_addr;
627 int prot, access_index;
629 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
630 MMU_KERNEL_IDX) != 0)
631 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
632 0, MMU_KERNEL_IDX) != 0)
633 return -1;
634 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
635 return -1;
636 return phys_addr;
638 #endif
640 void cpu_reset(CPUSPARCState *env)
642 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
643 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
644 log_cpu_state(env, 0);
647 tlb_flush(env, 1);
648 env->cwp = 0;
649 env->wim = 1;
650 env->regwptr = env->regbase + (env->cwp * 16);
651 #if defined(CONFIG_USER_ONLY)
652 #ifdef TARGET_SPARC64
653 env->cleanwin = env->nwindows - 2;
654 env->cansave = env->nwindows - 2;
655 env->pstate = PS_RMO | PS_PEF | PS_IE;
656 env->asi = 0x82; // Primary no-fault
657 #endif
658 #else
659 env->psret = 0;
660 env->psrs = 1;
661 env->psrps = 1;
662 CC_OP = CC_OP_FLAGS;
663 #ifdef TARGET_SPARC64
664 env->pstate = PS_PRIV;
665 env->hpstate = HS_PRIV;
666 env->tsptr = &env->ts[env->tl & MAXTL_MASK];
667 env->lsu = 0;
668 #else
669 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
670 env->mmuregs[0] |= env->def->mmu_bm;
671 #endif
672 env->pc = 0;
673 env->npc = env->pc + 4;
674 #endif
677 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
679 sparc_def_t def1, *def = &def1;
681 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
682 return -1;
684 env->def = qemu_mallocz(sizeof(*def));
685 memcpy(env->def, def, sizeof(*def));
686 #if defined(CONFIG_USER_ONLY)
687 if ((env->def->features & CPU_FEATURE_FLOAT))
688 env->def->features |= CPU_FEATURE_FLOAT128;
689 #endif
690 env->cpu_model_str = cpu_model;
691 env->version = def->iu_version;
692 env->fsr = def->fpu_version;
693 env->nwindows = def->nwindows;
694 #if !defined(TARGET_SPARC64)
695 env->mmuregs[0] |= def->mmu_version;
696 cpu_sparc_set_id(env, 0);
697 env->mxccregs[7] |= def->mxcc_version;
698 #else
699 env->mmu_version = def->mmu_version;
700 env->maxtl = def->maxtl;
701 env->version |= def->maxtl << 8;
702 env->version |= def->nwindows - 1;
703 #endif
704 return 0;
707 static void cpu_sparc_close(CPUSPARCState *env)
709 free(env->def);
710 free(env);
713 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
715 CPUSPARCState *env;
717 env = qemu_mallocz(sizeof(CPUSPARCState));
718 cpu_exec_init(env);
720 gen_intermediate_code_init(env);
722 if (cpu_sparc_register(env, cpu_model) < 0) {
723 cpu_sparc_close(env);
724 return NULL;
726 cpu_reset(env);
727 qemu_init_vcpu(env);
729 return env;
732 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
734 #if !defined(TARGET_SPARC64)
735 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
736 #endif
739 static const sparc_def_t sparc_defs[] = {
740 #ifdef TARGET_SPARC64
742 .name = "Fujitsu Sparc64",
743 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
744 .fpu_version = 0x00000000,
745 .mmu_version = mmu_us_12,
746 .nwindows = 4,
747 .maxtl = 4,
748 .features = CPU_DEFAULT_FEATURES,
751 .name = "Fujitsu Sparc64 III",
752 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
753 .fpu_version = 0x00000000,
754 .mmu_version = mmu_us_12,
755 .nwindows = 5,
756 .maxtl = 4,
757 .features = CPU_DEFAULT_FEATURES,
760 .name = "Fujitsu Sparc64 IV",
761 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
762 .fpu_version = 0x00000000,
763 .mmu_version = mmu_us_12,
764 .nwindows = 8,
765 .maxtl = 5,
766 .features = CPU_DEFAULT_FEATURES,
769 .name = "Fujitsu Sparc64 V",
770 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
771 .fpu_version = 0x00000000,
772 .mmu_version = mmu_us_12,
773 .nwindows = 8,
774 .maxtl = 5,
775 .features = CPU_DEFAULT_FEATURES,
778 .name = "TI UltraSparc I",
779 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
780 .fpu_version = 0x00000000,
781 .mmu_version = mmu_us_12,
782 .nwindows = 8,
783 .maxtl = 5,
784 .features = CPU_DEFAULT_FEATURES,
787 .name = "TI UltraSparc II",
788 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
789 .fpu_version = 0x00000000,
790 .mmu_version = mmu_us_12,
791 .nwindows = 8,
792 .maxtl = 5,
793 .features = CPU_DEFAULT_FEATURES,
796 .name = "TI UltraSparc IIi",
797 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
798 .fpu_version = 0x00000000,
799 .mmu_version = mmu_us_12,
800 .nwindows = 8,
801 .maxtl = 5,
802 .features = CPU_DEFAULT_FEATURES,
805 .name = "TI UltraSparc IIe",
806 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
807 .fpu_version = 0x00000000,
808 .mmu_version = mmu_us_12,
809 .nwindows = 8,
810 .maxtl = 5,
811 .features = CPU_DEFAULT_FEATURES,
814 .name = "Sun UltraSparc III",
815 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
816 .fpu_version = 0x00000000,
817 .mmu_version = mmu_us_12,
818 .nwindows = 8,
819 .maxtl = 5,
820 .features = CPU_DEFAULT_FEATURES,
823 .name = "Sun UltraSparc III Cu",
824 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
825 .fpu_version = 0x00000000,
826 .mmu_version = mmu_us_3,
827 .nwindows = 8,
828 .maxtl = 5,
829 .features = CPU_DEFAULT_FEATURES,
832 .name = "Sun UltraSparc IIIi",
833 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
834 .fpu_version = 0x00000000,
835 .mmu_version = mmu_us_12,
836 .nwindows = 8,
837 .maxtl = 5,
838 .features = CPU_DEFAULT_FEATURES,
841 .name = "Sun UltraSparc IV",
842 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
843 .fpu_version = 0x00000000,
844 .mmu_version = mmu_us_4,
845 .nwindows = 8,
846 .maxtl = 5,
847 .features = CPU_DEFAULT_FEATURES,
850 .name = "Sun UltraSparc IV+",
851 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
852 .fpu_version = 0x00000000,
853 .mmu_version = mmu_us_12,
854 .nwindows = 8,
855 .maxtl = 5,
856 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
859 .name = "Sun UltraSparc IIIi+",
860 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
861 .fpu_version = 0x00000000,
862 .mmu_version = mmu_us_3,
863 .nwindows = 8,
864 .maxtl = 5,
865 .features = CPU_DEFAULT_FEATURES,
868 .name = "Sun UltraSparc T1",
869 // defined in sparc_ifu_fdp.v and ctu.h
870 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
871 .fpu_version = 0x00000000,
872 .mmu_version = mmu_sun4v,
873 .nwindows = 8,
874 .maxtl = 6,
875 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
876 | CPU_FEATURE_GL,
879 .name = "Sun UltraSparc T2",
880 // defined in tlu_asi_ctl.v and n2_revid_cust.v
881 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
882 .fpu_version = 0x00000000,
883 .mmu_version = mmu_sun4v,
884 .nwindows = 8,
885 .maxtl = 6,
886 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
887 | CPU_FEATURE_GL,
890 .name = "NEC UltraSparc I",
891 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
892 .fpu_version = 0x00000000,
893 .mmu_version = mmu_us_12,
894 .nwindows = 8,
895 .maxtl = 5,
896 .features = CPU_DEFAULT_FEATURES,
898 #else
900 .name = "Fujitsu MB86900",
901 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
902 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
903 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
904 .mmu_bm = 0x00004000,
905 .mmu_ctpr_mask = 0x007ffff0,
906 .mmu_cxr_mask = 0x0000003f,
907 .mmu_sfsr_mask = 0xffffffff,
908 .mmu_trcr_mask = 0xffffffff,
909 .nwindows = 7,
910 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
913 .name = "Fujitsu MB86904",
914 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
915 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
916 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
917 .mmu_bm = 0x00004000,
918 .mmu_ctpr_mask = 0x00ffffc0,
919 .mmu_cxr_mask = 0x000000ff,
920 .mmu_sfsr_mask = 0x00016fff,
921 .mmu_trcr_mask = 0x00ffffff,
922 .nwindows = 8,
923 .features = CPU_DEFAULT_FEATURES,
926 .name = "Fujitsu MB86907",
927 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
928 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
929 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
930 .mmu_bm = 0x00004000,
931 .mmu_ctpr_mask = 0xffffffc0,
932 .mmu_cxr_mask = 0x000000ff,
933 .mmu_sfsr_mask = 0x00016fff,
934 .mmu_trcr_mask = 0xffffffff,
935 .nwindows = 8,
936 .features = CPU_DEFAULT_FEATURES,
939 .name = "LSI L64811",
940 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
941 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
942 .mmu_version = 0x10 << 24,
943 .mmu_bm = 0x00004000,
944 .mmu_ctpr_mask = 0x007ffff0,
945 .mmu_cxr_mask = 0x0000003f,
946 .mmu_sfsr_mask = 0xffffffff,
947 .mmu_trcr_mask = 0xffffffff,
948 .nwindows = 8,
949 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
950 CPU_FEATURE_FSMULD,
953 .name = "Cypress CY7C601",
954 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
955 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
956 .mmu_version = 0x10 << 24,
957 .mmu_bm = 0x00004000,
958 .mmu_ctpr_mask = 0x007ffff0,
959 .mmu_cxr_mask = 0x0000003f,
960 .mmu_sfsr_mask = 0xffffffff,
961 .mmu_trcr_mask = 0xffffffff,
962 .nwindows = 8,
963 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
964 CPU_FEATURE_FSMULD,
967 .name = "Cypress CY7C611",
968 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
969 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
970 .mmu_version = 0x10 << 24,
971 .mmu_bm = 0x00004000,
972 .mmu_ctpr_mask = 0x007ffff0,
973 .mmu_cxr_mask = 0x0000003f,
974 .mmu_sfsr_mask = 0xffffffff,
975 .mmu_trcr_mask = 0xffffffff,
976 .nwindows = 8,
977 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
978 CPU_FEATURE_FSMULD,
981 .name = "TI MicroSparc I",
982 .iu_version = 0x41000000,
983 .fpu_version = 4 << 17,
984 .mmu_version = 0x41000000,
985 .mmu_bm = 0x00004000,
986 .mmu_ctpr_mask = 0x007ffff0,
987 .mmu_cxr_mask = 0x0000003f,
988 .mmu_sfsr_mask = 0x00016fff,
989 .mmu_trcr_mask = 0x0000003f,
990 .nwindows = 7,
991 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
992 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
993 CPU_FEATURE_FMUL,
996 .name = "TI MicroSparc II",
997 .iu_version = 0x42000000,
998 .fpu_version = 4 << 17,
999 .mmu_version = 0x02000000,
1000 .mmu_bm = 0x00004000,
1001 .mmu_ctpr_mask = 0x00ffffc0,
1002 .mmu_cxr_mask = 0x000000ff,
1003 .mmu_sfsr_mask = 0x00016fff,
1004 .mmu_trcr_mask = 0x00ffffff,
1005 .nwindows = 8,
1006 .features = CPU_DEFAULT_FEATURES,
1009 .name = "TI MicroSparc IIep",
1010 .iu_version = 0x42000000,
1011 .fpu_version = 4 << 17,
1012 .mmu_version = 0x04000000,
1013 .mmu_bm = 0x00004000,
1014 .mmu_ctpr_mask = 0x00ffffc0,
1015 .mmu_cxr_mask = 0x000000ff,
1016 .mmu_sfsr_mask = 0x00016bff,
1017 .mmu_trcr_mask = 0x00ffffff,
1018 .nwindows = 8,
1019 .features = CPU_DEFAULT_FEATURES,
1022 .name = "TI SuperSparc 40", // STP1020NPGA
1023 .iu_version = 0x41000000, // SuperSPARC 2.x
1024 .fpu_version = 0 << 17,
1025 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1026 .mmu_bm = 0x00002000,
1027 .mmu_ctpr_mask = 0xffffffc0,
1028 .mmu_cxr_mask = 0x0000ffff,
1029 .mmu_sfsr_mask = 0xffffffff,
1030 .mmu_trcr_mask = 0xffffffff,
1031 .nwindows = 8,
1032 .features = CPU_DEFAULT_FEATURES,
1035 .name = "TI SuperSparc 50", // STP1020PGA
1036 .iu_version = 0x40000000, // SuperSPARC 3.x
1037 .fpu_version = 0 << 17,
1038 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1039 .mmu_bm = 0x00002000,
1040 .mmu_ctpr_mask = 0xffffffc0,
1041 .mmu_cxr_mask = 0x0000ffff,
1042 .mmu_sfsr_mask = 0xffffffff,
1043 .mmu_trcr_mask = 0xffffffff,
1044 .nwindows = 8,
1045 .features = CPU_DEFAULT_FEATURES,
1048 .name = "TI SuperSparc 51",
1049 .iu_version = 0x40000000, // SuperSPARC 3.x
1050 .fpu_version = 0 << 17,
1051 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1052 .mmu_bm = 0x00002000,
1053 .mmu_ctpr_mask = 0xffffffc0,
1054 .mmu_cxr_mask = 0x0000ffff,
1055 .mmu_sfsr_mask = 0xffffffff,
1056 .mmu_trcr_mask = 0xffffffff,
1057 .mxcc_version = 0x00000104,
1058 .nwindows = 8,
1059 .features = CPU_DEFAULT_FEATURES,
1062 .name = "TI SuperSparc 60", // STP1020APGA
1063 .iu_version = 0x40000000, // SuperSPARC 3.x
1064 .fpu_version = 0 << 17,
1065 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1066 .mmu_bm = 0x00002000,
1067 .mmu_ctpr_mask = 0xffffffc0,
1068 .mmu_cxr_mask = 0x0000ffff,
1069 .mmu_sfsr_mask = 0xffffffff,
1070 .mmu_trcr_mask = 0xffffffff,
1071 .nwindows = 8,
1072 .features = CPU_DEFAULT_FEATURES,
1075 .name = "TI SuperSparc 61",
1076 .iu_version = 0x44000000, // SuperSPARC 3.x
1077 .fpu_version = 0 << 17,
1078 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1079 .mmu_bm = 0x00002000,
1080 .mmu_ctpr_mask = 0xffffffc0,
1081 .mmu_cxr_mask = 0x0000ffff,
1082 .mmu_sfsr_mask = 0xffffffff,
1083 .mmu_trcr_mask = 0xffffffff,
1084 .mxcc_version = 0x00000104,
1085 .nwindows = 8,
1086 .features = CPU_DEFAULT_FEATURES,
1089 .name = "TI SuperSparc II",
1090 .iu_version = 0x40000000, // SuperSPARC II 1.x
1091 .fpu_version = 0 << 17,
1092 .mmu_version = 0x08000000, // SuperSPARC II 1.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 = "Ross RT625",
1104 .iu_version = 0x1e000000,
1105 .fpu_version = 1 << 17,
1106 .mmu_version = 0x1e000000,
1107 .mmu_bm = 0x00004000,
1108 .mmu_ctpr_mask = 0x007ffff0,
1109 .mmu_cxr_mask = 0x0000003f,
1110 .mmu_sfsr_mask = 0xffffffff,
1111 .mmu_trcr_mask = 0xffffffff,
1112 .nwindows = 8,
1113 .features = CPU_DEFAULT_FEATURES,
1116 .name = "Ross RT620",
1117 .iu_version = 0x1f000000,
1118 .fpu_version = 1 << 17,
1119 .mmu_version = 0x1f000000,
1120 .mmu_bm = 0x00004000,
1121 .mmu_ctpr_mask = 0x007ffff0,
1122 .mmu_cxr_mask = 0x0000003f,
1123 .mmu_sfsr_mask = 0xffffffff,
1124 .mmu_trcr_mask = 0xffffffff,
1125 .nwindows = 8,
1126 .features = CPU_DEFAULT_FEATURES,
1129 .name = "BIT B5010",
1130 .iu_version = 0x20000000,
1131 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1132 .mmu_version = 0x20000000,
1133 .mmu_bm = 0x00004000,
1134 .mmu_ctpr_mask = 0x007ffff0,
1135 .mmu_cxr_mask = 0x0000003f,
1136 .mmu_sfsr_mask = 0xffffffff,
1137 .mmu_trcr_mask = 0xffffffff,
1138 .nwindows = 8,
1139 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1140 CPU_FEATURE_FSMULD,
1143 .name = "Matsushita MN10501",
1144 .iu_version = 0x50000000,
1145 .fpu_version = 0 << 17,
1146 .mmu_version = 0x50000000,
1147 .mmu_bm = 0x00004000,
1148 .mmu_ctpr_mask = 0x007ffff0,
1149 .mmu_cxr_mask = 0x0000003f,
1150 .mmu_sfsr_mask = 0xffffffff,
1151 .mmu_trcr_mask = 0xffffffff,
1152 .nwindows = 8,
1153 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1154 CPU_FEATURE_FSMULD,
1157 .name = "Weitek W8601",
1158 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1159 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1160 .mmu_version = 0x10 << 24,
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 = "LEON2",
1171 .iu_version = 0xf2000000,
1172 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1173 .mmu_version = 0xf2000000,
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_DEFAULT_FEATURES,
1183 .name = "LEON3",
1184 .iu_version = 0xf3000000,
1185 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1186 .mmu_version = 0xf3000000,
1187 .mmu_bm = 0x00004000,
1188 .mmu_ctpr_mask = 0x007ffff0,
1189 .mmu_cxr_mask = 0x0000003f,
1190 .mmu_sfsr_mask = 0xffffffff,
1191 .mmu_trcr_mask = 0xffffffff,
1192 .nwindows = 8,
1193 .features = CPU_DEFAULT_FEATURES,
1195 #endif
1198 static const char * const feature_name[] = {
1199 "float",
1200 "float128",
1201 "swap",
1202 "mul",
1203 "div",
1204 "flush",
1205 "fsqrt",
1206 "fmul",
1207 "vis1",
1208 "vis2",
1209 "fsmuld",
1210 "hypv",
1211 "cmt",
1212 "gl",
1215 static void print_features(FILE *f,
1216 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1217 uint32_t features, const char *prefix)
1219 unsigned int i;
1221 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1222 if (feature_name[i] && (features & (1 << i))) {
1223 if (prefix)
1224 (*cpu_fprintf)(f, "%s", prefix);
1225 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1229 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1231 unsigned int i;
1233 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1234 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1235 *features |= 1 << i;
1236 return;
1238 fprintf(stderr, "CPU feature %s not found\n", flagname);
1241 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1243 unsigned int i;
1244 const sparc_def_t *def = NULL;
1245 char *s = strdup(cpu_model);
1246 char *featurestr, *name = strtok(s, ",");
1247 uint32_t plus_features = 0;
1248 uint32_t minus_features = 0;
1249 long long iu_version;
1250 uint32_t fpu_version, mmu_version, nwindows;
1252 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1253 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1254 def = &sparc_defs[i];
1257 if (!def)
1258 goto error;
1259 memcpy(cpu_def, def, sizeof(*def));
1261 featurestr = strtok(NULL, ",");
1262 while (featurestr) {
1263 char *val;
1265 if (featurestr[0] == '+') {
1266 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1267 } else if (featurestr[0] == '-') {
1268 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1269 } else if ((val = strchr(featurestr, '='))) {
1270 *val = 0; val++;
1271 if (!strcmp(featurestr, "iu_version")) {
1272 char *err;
1274 iu_version = strtoll(val, &err, 0);
1275 if (!*val || *err) {
1276 fprintf(stderr, "bad numerical value %s\n", val);
1277 goto error;
1279 cpu_def->iu_version = iu_version;
1280 #ifdef DEBUG_FEATURES
1281 fprintf(stderr, "iu_version %llx\n", iu_version);
1282 #endif
1283 } else if (!strcmp(featurestr, "fpu_version")) {
1284 char *err;
1286 fpu_version = strtol(val, &err, 0);
1287 if (!*val || *err) {
1288 fprintf(stderr, "bad numerical value %s\n", val);
1289 goto error;
1291 cpu_def->fpu_version = fpu_version;
1292 #ifdef DEBUG_FEATURES
1293 fprintf(stderr, "fpu_version %llx\n", fpu_version);
1294 #endif
1295 } else if (!strcmp(featurestr, "mmu_version")) {
1296 char *err;
1298 mmu_version = strtol(val, &err, 0);
1299 if (!*val || *err) {
1300 fprintf(stderr, "bad numerical value %s\n", val);
1301 goto error;
1303 cpu_def->mmu_version = mmu_version;
1304 #ifdef DEBUG_FEATURES
1305 fprintf(stderr, "mmu_version %llx\n", mmu_version);
1306 #endif
1307 } else if (!strcmp(featurestr, "nwindows")) {
1308 char *err;
1310 nwindows = strtol(val, &err, 0);
1311 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1312 nwindows < MIN_NWINDOWS) {
1313 fprintf(stderr, "bad numerical value %s\n", val);
1314 goto error;
1316 cpu_def->nwindows = nwindows;
1317 #ifdef DEBUG_FEATURES
1318 fprintf(stderr, "nwindows %d\n", nwindows);
1319 #endif
1320 } else {
1321 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1322 goto error;
1324 } else {
1325 fprintf(stderr, "feature string `%s' not in format "
1326 "(+feature|-feature|feature=xyz)\n", featurestr);
1327 goto error;
1329 featurestr = strtok(NULL, ",");
1331 cpu_def->features |= plus_features;
1332 cpu_def->features &= ~minus_features;
1333 #ifdef DEBUG_FEATURES
1334 print_features(stderr, fprintf, cpu_def->features, NULL);
1335 #endif
1336 free(s);
1337 return 0;
1339 error:
1340 free(s);
1341 return -1;
1344 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1346 unsigned int i;
1348 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1349 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1350 sparc_defs[i].name,
1351 sparc_defs[i].iu_version,
1352 sparc_defs[i].fpu_version,
1353 sparc_defs[i].mmu_version,
1354 sparc_defs[i].nwindows);
1355 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1356 ~sparc_defs[i].features, "-");
1357 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1358 sparc_defs[i].features, "+");
1359 (*cpu_fprintf)(f, "\n");
1361 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1362 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1363 (*cpu_fprintf)(f, "\n");
1364 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1365 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1366 (*cpu_fprintf)(f, "\n");
1367 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1368 "fpu_version mmu_version nwindows\n");
1371 void cpu_dump_state(CPUState *env, FILE *f,
1372 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1373 int flags)
1375 int i, x;
1377 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1378 env->npc);
1379 cpu_fprintf(f, "General Registers:\n");
1380 for (i = 0; i < 4; i++)
1381 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1382 cpu_fprintf(f, "\n");
1383 for (; i < 8; i++)
1384 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1385 cpu_fprintf(f, "\nCurrent Register Window:\n");
1386 for (x = 0; x < 3; x++) {
1387 for (i = 0; i < 4; i++)
1388 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1389 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1390 env->regwptr[i + x * 8]);
1391 cpu_fprintf(f, "\n");
1392 for (; i < 8; i++)
1393 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1394 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1395 env->regwptr[i + x * 8]);
1396 cpu_fprintf(f, "\n");
1398 cpu_fprintf(f, "\nFloating Point Registers:\n");
1399 for (i = 0; i < 32; i++) {
1400 if ((i & 3) == 0)
1401 cpu_fprintf(f, "%%f%02d:", i);
1402 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1403 if ((i & 3) == 3)
1404 cpu_fprintf(f, "\n");
1406 #ifdef TARGET_SPARC64
1407 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1408 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1409 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1410 "cleanwin %d cwp %d\n",
1411 env->cansave, env->canrestore, env->otherwin, env->wstate,
1412 env->cleanwin, env->nwindows - 1 - env->cwp);
1413 #else
1415 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1417 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1418 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1419 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1420 env->psrs?'S':'-', env->psrps?'P':'-',
1421 env->psret?'E':'-', env->wim);
1422 #endif
1423 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);