softfloat: add a 1.0 constant for float32 and float64
[qemu/mini2440/sniper_sniper_test.git] / target-sparc / helper.c
bloba2758808515a8acb9d6e7f7b6572fe4db4cf2655
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>
26 #include <assert.h>
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "qemu-common.h"
32 //#define DEBUG_MMU
33 //#define DEBUG_FEATURES
35 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
37 /* Sparc MMU emulation */
39 /* thread support */
41 static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
43 void cpu_lock(void)
45 spin_lock(&global_cpu_lock);
48 void cpu_unlock(void)
50 spin_unlock(&global_cpu_lock);
53 #if defined(CONFIG_USER_ONLY)
55 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
56 int mmu_idx, int is_softmmu)
58 if (rw & 2)
59 env1->exception_index = TT_TFAULT;
60 else
61 env1->exception_index = TT_DFAULT;
62 return 1;
65 #else
67 #ifndef TARGET_SPARC64
69 * Sparc V8 Reference MMU (SRMMU)
71 static const int access_table[8][8] = {
72 { 0, 0, 0, 0, 8, 0, 12, 12 },
73 { 0, 0, 0, 0, 8, 0, 0, 0 },
74 { 8, 8, 0, 0, 0, 8, 12, 12 },
75 { 8, 8, 0, 0, 0, 8, 0, 0 },
76 { 8, 0, 8, 0, 8, 8, 12, 12 },
77 { 8, 0, 8, 0, 8, 0, 8, 0 },
78 { 8, 8, 8, 0, 8, 8, 12, 12 },
79 { 8, 8, 8, 0, 8, 8, 8, 0 }
82 static const int perm_table[2][8] = {
84 PAGE_READ,
85 PAGE_READ | PAGE_WRITE,
86 PAGE_READ | PAGE_EXEC,
87 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
88 PAGE_EXEC,
89 PAGE_READ | PAGE_WRITE,
90 PAGE_READ | PAGE_EXEC,
91 PAGE_READ | PAGE_WRITE | PAGE_EXEC
94 PAGE_READ,
95 PAGE_READ | PAGE_WRITE,
96 PAGE_READ | PAGE_EXEC,
97 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
98 PAGE_EXEC,
99 PAGE_READ,
105 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
106 int *prot, int *access_index,
107 target_ulong address, int rw, int mmu_idx)
109 int access_perms = 0;
110 target_phys_addr_t pde_ptr;
111 uint32_t pde;
112 target_ulong virt_addr;
113 int error_code = 0, is_dirty, is_user;
114 unsigned long page_offset;
116 is_user = mmu_idx == MMU_USER_IDX;
117 virt_addr = address & TARGET_PAGE_MASK;
119 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
120 // Boot mode: instruction fetches are taken from PROM
121 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
122 *physical = env->prom_addr | (address & 0x7ffffULL);
123 *prot = PAGE_READ | PAGE_EXEC;
124 return 0;
126 *physical = address;
127 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
128 return 0;
131 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
132 *physical = 0xffffffffffff0000ULL;
134 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
135 /* Context base + context number */
136 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
137 pde = ldl_phys(pde_ptr);
139 /* Ctx pde */
140 switch (pde & PTE_ENTRYTYPE_MASK) {
141 default:
142 case 0: /* Invalid */
143 return 1 << 2;
144 case 2: /* L0 PTE, maybe should not happen? */
145 case 3: /* Reserved */
146 return 4 << 2;
147 case 1: /* L0 PDE */
148 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
149 pde = ldl_phys(pde_ptr);
151 switch (pde & PTE_ENTRYTYPE_MASK) {
152 default:
153 case 0: /* Invalid */
154 return (1 << 8) | (1 << 2);
155 case 3: /* Reserved */
156 return (1 << 8) | (4 << 2);
157 case 1: /* L1 PDE */
158 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
159 pde = ldl_phys(pde_ptr);
161 switch (pde & PTE_ENTRYTYPE_MASK) {
162 default:
163 case 0: /* Invalid */
164 return (2 << 8) | (1 << 2);
165 case 3: /* Reserved */
166 return (2 << 8) | (4 << 2);
167 case 1: /* L2 PDE */
168 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
169 pde = ldl_phys(pde_ptr);
171 switch (pde & PTE_ENTRYTYPE_MASK) {
172 default:
173 case 0: /* Invalid */
174 return (3 << 8) | (1 << 2);
175 case 1: /* PDE, should not happen */
176 case 3: /* Reserved */
177 return (3 << 8) | (4 << 2);
178 case 2: /* L3 PTE */
179 virt_addr = address & TARGET_PAGE_MASK;
180 page_offset = (address & TARGET_PAGE_MASK) &
181 (TARGET_PAGE_SIZE - 1);
183 break;
184 case 2: /* L2 PTE */
185 virt_addr = address & ~0x3ffff;
186 page_offset = address & 0x3ffff;
188 break;
189 case 2: /* L1 PTE */
190 virt_addr = address & ~0xffffff;
191 page_offset = address & 0xffffff;
195 /* update page modified and dirty bits */
196 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
197 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
198 pde |= PG_ACCESSED_MASK;
199 if (is_dirty)
200 pde |= PG_MODIFIED_MASK;
201 stl_phys_notdirty(pde_ptr, pde);
203 /* check access */
204 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
205 error_code = access_table[*access_index][access_perms];
206 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
207 return error_code;
209 /* the page can be put in the TLB */
210 *prot = perm_table[is_user][access_perms];
211 if (!(pde & PG_MODIFIED_MASK)) {
212 /* only set write access if already dirty... otherwise wait
213 for dirty access */
214 *prot &= ~PAGE_WRITE;
217 /* Even if large ptes, we map only one 4KB page in the cache to
218 avoid filling it too fast */
219 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
220 return error_code;
223 /* Perform address translation */
224 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
225 int mmu_idx, int is_softmmu)
227 target_phys_addr_t paddr;
228 target_ulong vaddr;
229 int error_code = 0, prot, ret = 0, access_index;
231 error_code = get_physical_address(env, &paddr, &prot, &access_index,
232 address, rw, mmu_idx);
233 if (error_code == 0) {
234 vaddr = address & TARGET_PAGE_MASK;
235 paddr &= TARGET_PAGE_MASK;
236 #ifdef DEBUG_MMU
237 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
238 TARGET_FMT_lx "\n", address, paddr, vaddr);
239 #endif
240 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
241 return ret;
244 if (env->mmuregs[3]) /* Fault status register */
245 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
246 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
247 env->mmuregs[4] = address; /* Fault address register */
249 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
250 // No fault mode: if a mapping is available, just override
251 // permissions. If no mapping is available, redirect accesses to
252 // neverland. Fake/overridden mappings will be flushed when
253 // switching to normal mode.
254 vaddr = address & TARGET_PAGE_MASK;
255 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
256 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
257 return ret;
258 } else {
259 if (rw & 2)
260 env->exception_index = TT_TFAULT;
261 else
262 env->exception_index = TT_DFAULT;
263 return 1;
267 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
269 target_phys_addr_t pde_ptr;
270 uint32_t pde;
272 /* Context base + context number */
273 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
274 (env->mmuregs[2] << 2);
275 pde = ldl_phys(pde_ptr);
277 switch (pde & PTE_ENTRYTYPE_MASK) {
278 default:
279 case 0: /* Invalid */
280 case 2: /* PTE, maybe should not happen? */
281 case 3: /* Reserved */
282 return 0;
283 case 1: /* L1 PDE */
284 if (mmulev == 3)
285 return pde;
286 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
287 pde = ldl_phys(pde_ptr);
289 switch (pde & PTE_ENTRYTYPE_MASK) {
290 default:
291 case 0: /* Invalid */
292 case 3: /* Reserved */
293 return 0;
294 case 2: /* L1 PTE */
295 return pde;
296 case 1: /* L2 PDE */
297 if (mmulev == 2)
298 return pde;
299 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
300 pde = ldl_phys(pde_ptr);
302 switch (pde & PTE_ENTRYTYPE_MASK) {
303 default:
304 case 0: /* Invalid */
305 case 3: /* Reserved */
306 return 0;
307 case 2: /* L2 PTE */
308 return pde;
309 case 1: /* L3 PDE */
310 if (mmulev == 1)
311 return pde;
312 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
313 pde = ldl_phys(pde_ptr);
315 switch (pde & PTE_ENTRYTYPE_MASK) {
316 default:
317 case 0: /* Invalid */
318 case 1: /* PDE, should not happen */
319 case 3: /* Reserved */
320 return 0;
321 case 2: /* L3 PTE */
322 return pde;
327 return 0;
330 #ifdef DEBUG_MMU
331 void dump_mmu(CPUState *env)
333 target_ulong va, va1, va2;
334 unsigned int n, m, o;
335 target_phys_addr_t pde_ptr, pa;
336 uint32_t pde;
338 printf("MMU dump:\n");
339 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
340 pde = ldl_phys(pde_ptr);
341 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
342 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
343 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
344 pde = mmu_probe(env, va, 2);
345 if (pde) {
346 pa = cpu_get_phys_page_debug(env, va);
347 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
348 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
349 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
350 pde = mmu_probe(env, va1, 1);
351 if (pde) {
352 pa = cpu_get_phys_page_debug(env, va1);
353 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
354 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
355 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
356 pde = mmu_probe(env, va2, 0);
357 if (pde) {
358 pa = cpu_get_phys_page_debug(env, va2);
359 printf(" VA: " TARGET_FMT_lx ", PA: "
360 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
361 va2, pa, pde);
368 printf("MMU dump ends\n");
370 #endif /* DEBUG_MMU */
372 #else /* !TARGET_SPARC64 */
374 * UltraSparc IIi I/DMMUs
376 static int get_physical_address_data(CPUState *env,
377 target_phys_addr_t *physical, int *prot,
378 target_ulong address, int rw, int is_user)
380 target_ulong mask;
381 unsigned int i;
383 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
384 *physical = address;
385 *prot = PAGE_READ | PAGE_WRITE;
386 return 0;
389 for (i = 0; i < 64; i++) {
390 switch ((env->dtlb_tte[i] >> 61) & 3) {
391 default:
392 case 0x0: // 8k
393 mask = 0xffffffffffffe000ULL;
394 break;
395 case 0x1: // 64k
396 mask = 0xffffffffffff0000ULL;
397 break;
398 case 0x2: // 512k
399 mask = 0xfffffffffff80000ULL;
400 break;
401 case 0x3: // 4M
402 mask = 0xffffffffffc00000ULL;
403 break;
405 // ctx match, vaddr match, valid?
406 if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
407 (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL) &&
408 (env->dtlb_tte[i] & 0x8000000000000000ULL)) {
409 // access ok?
410 if (((env->dtlb_tte[i] & 0x4) && is_user) ||
411 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
412 if (env->dmmuregs[3]) /* Fault status register */
413 env->dmmuregs[3] = 2; /* overflow (not read before
414 another fault) */
415 env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
416 env->dmmuregs[4] = address; /* Fault address register */
417 env->exception_index = TT_DFAULT;
418 #ifdef DEBUG_MMU
419 printf("DFAULT at 0x%" PRIx64 "\n", address);
420 #endif
421 return 1;
423 *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
424 (address & ~mask & 0x1fffffff000ULL);
425 *prot = PAGE_READ;
426 if (env->dtlb_tte[i] & 0x2)
427 *prot |= PAGE_WRITE;
428 return 0;
431 #ifdef DEBUG_MMU
432 printf("DMISS at 0x%" PRIx64 "\n", address);
433 #endif
434 env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
435 env->exception_index = TT_DMISS;
436 return 1;
439 static int get_physical_address_code(CPUState *env,
440 target_phys_addr_t *physical, int *prot,
441 target_ulong address, int is_user)
443 target_ulong mask;
444 unsigned int i;
446 if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
447 *physical = address;
448 *prot = PAGE_EXEC;
449 return 0;
452 for (i = 0; i < 64; i++) {
453 switch ((env->itlb_tte[i] >> 61) & 3) {
454 default:
455 case 0x0: // 8k
456 mask = 0xffffffffffffe000ULL;
457 break;
458 case 0x1: // 64k
459 mask = 0xffffffffffff0000ULL;
460 break;
461 case 0x2: // 512k
462 mask = 0xfffffffffff80000ULL;
463 break;
464 case 0x3: // 4M
465 mask = 0xffffffffffc00000ULL;
466 break;
468 // ctx match, vaddr match, valid?
469 if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
470 (address & mask) == (env->itlb_tag[i] & ~0x1fffULL) &&
471 (env->itlb_tte[i] & 0x8000000000000000ULL)) {
472 // access ok?
473 if ((env->itlb_tte[i] & 0x4) && is_user) {
474 if (env->immuregs[3]) /* Fault status register */
475 env->immuregs[3] = 2; /* overflow (not read before
476 another fault) */
477 env->immuregs[3] |= (is_user << 3) | 1;
478 env->exception_index = TT_TFAULT;
479 #ifdef DEBUG_MMU
480 printf("TFAULT at 0x%" PRIx64 "\n", address);
481 #endif
482 return 1;
484 *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
485 (address & ~mask & 0x1fffffff000ULL);
486 *prot = PAGE_EXEC;
487 return 0;
490 #ifdef DEBUG_MMU
491 printf("TMISS at 0x%" PRIx64 "\n", address);
492 #endif
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 #ifdef TARGET_SPARC64
663 env->pstate = PS_PRIV;
664 env->hpstate = HS_PRIV;
665 env->tsptr = &env->ts[env->tl & MAXTL_MASK];
666 #else
667 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
668 env->mmuregs[0] |= env->def->mmu_bm;
669 #endif
670 env->pc = 0;
671 env->npc = env->pc + 4;
672 #endif
675 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
677 sparc_def_t def1, *def = &def1;
679 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
680 return -1;
682 env->def = qemu_mallocz(sizeof(*def));
683 memcpy(env->def, def, sizeof(*def));
684 #if defined(CONFIG_USER_ONLY)
685 if ((env->def->features & CPU_FEATURE_FLOAT))
686 env->def->features |= CPU_FEATURE_FLOAT128;
687 #endif
688 env->cpu_model_str = cpu_model;
689 env->version = def->iu_version;
690 env->fsr = def->fpu_version;
691 env->nwindows = def->nwindows;
692 #if !defined(TARGET_SPARC64)
693 env->mmuregs[0] |= def->mmu_version;
694 cpu_sparc_set_id(env, 0);
695 env->mxccregs[7] |= def->mxcc_version;
696 #else
697 env->mmu_version = def->mmu_version;
698 env->maxtl = def->maxtl;
699 env->version |= def->maxtl << 8;
700 env->version |= def->nwindows - 1;
701 #endif
702 return 0;
705 static void cpu_sparc_close(CPUSPARCState *env)
707 free(env->def);
708 free(env);
711 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
713 CPUSPARCState *env;
715 env = qemu_mallocz(sizeof(CPUSPARCState));
716 if (!env)
717 return NULL;
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);
728 return env;
731 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
733 #if !defined(TARGET_SPARC64)
734 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
735 #endif
738 static const sparc_def_t sparc_defs[] = {
739 #ifdef TARGET_SPARC64
741 .name = "Fujitsu Sparc64",
742 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
743 .fpu_version = 0x00000000,
744 .mmu_version = mmu_us_12,
745 .nwindows = 4,
746 .maxtl = 4,
747 .features = CPU_DEFAULT_FEATURES,
750 .name = "Fujitsu Sparc64 III",
751 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
752 .fpu_version = 0x00000000,
753 .mmu_version = mmu_us_12,
754 .nwindows = 5,
755 .maxtl = 4,
756 .features = CPU_DEFAULT_FEATURES,
759 .name = "Fujitsu Sparc64 IV",
760 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
761 .fpu_version = 0x00000000,
762 .mmu_version = mmu_us_12,
763 .nwindows = 8,
764 .maxtl = 5,
765 .features = CPU_DEFAULT_FEATURES,
768 .name = "Fujitsu Sparc64 V",
769 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
770 .fpu_version = 0x00000000,
771 .mmu_version = mmu_us_12,
772 .nwindows = 8,
773 .maxtl = 5,
774 .features = CPU_DEFAULT_FEATURES,
777 .name = "TI UltraSparc I",
778 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
779 .fpu_version = 0x00000000,
780 .mmu_version = mmu_us_12,
781 .nwindows = 8,
782 .maxtl = 5,
783 .features = CPU_DEFAULT_FEATURES,
786 .name = "TI UltraSparc II",
787 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
788 .fpu_version = 0x00000000,
789 .mmu_version = mmu_us_12,
790 .nwindows = 8,
791 .maxtl = 5,
792 .features = CPU_DEFAULT_FEATURES,
795 .name = "TI UltraSparc IIi",
796 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
797 .fpu_version = 0x00000000,
798 .mmu_version = mmu_us_12,
799 .nwindows = 8,
800 .maxtl = 5,
801 .features = CPU_DEFAULT_FEATURES,
804 .name = "TI UltraSparc IIe",
805 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
806 .fpu_version = 0x00000000,
807 .mmu_version = mmu_us_12,
808 .nwindows = 8,
809 .maxtl = 5,
810 .features = CPU_DEFAULT_FEATURES,
813 .name = "Sun UltraSparc III",
814 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
815 .fpu_version = 0x00000000,
816 .mmu_version = mmu_us_12,
817 .nwindows = 8,
818 .maxtl = 5,
819 .features = CPU_DEFAULT_FEATURES,
822 .name = "Sun UltraSparc III Cu",
823 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
824 .fpu_version = 0x00000000,
825 .mmu_version = mmu_us_3,
826 .nwindows = 8,
827 .maxtl = 5,
828 .features = CPU_DEFAULT_FEATURES,
831 .name = "Sun UltraSparc IIIi",
832 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
833 .fpu_version = 0x00000000,
834 .mmu_version = mmu_us_12,
835 .nwindows = 8,
836 .maxtl = 5,
837 .features = CPU_DEFAULT_FEATURES,
840 .name = "Sun UltraSparc IV",
841 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
842 .fpu_version = 0x00000000,
843 .mmu_version = mmu_us_4,
844 .nwindows = 8,
845 .maxtl = 5,
846 .features = CPU_DEFAULT_FEATURES,
849 .name = "Sun UltraSparc IV+",
850 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
851 .fpu_version = 0x00000000,
852 .mmu_version = mmu_us_12,
853 .nwindows = 8,
854 .maxtl = 5,
855 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
858 .name = "Sun UltraSparc IIIi+",
859 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
860 .fpu_version = 0x00000000,
861 .mmu_version = mmu_us_3,
862 .nwindows = 8,
863 .maxtl = 5,
864 .features = CPU_DEFAULT_FEATURES,
867 .name = "Sun UltraSparc T1",
868 // defined in sparc_ifu_fdp.v and ctu.h
869 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
870 .fpu_version = 0x00000000,
871 .mmu_version = mmu_sun4v,
872 .nwindows = 8,
873 .maxtl = 6,
874 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
875 | CPU_FEATURE_GL,
878 .name = "Sun UltraSparc T2",
879 // defined in tlu_asi_ctl.v and n2_revid_cust.v
880 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
881 .fpu_version = 0x00000000,
882 .mmu_version = mmu_sun4v,
883 .nwindows = 8,
884 .maxtl = 6,
885 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
886 | CPU_FEATURE_GL,
889 .name = "NEC UltraSparc I",
890 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
891 .fpu_version = 0x00000000,
892 .mmu_version = mmu_us_12,
893 .nwindows = 8,
894 .maxtl = 5,
895 .features = CPU_DEFAULT_FEATURES,
897 #else
899 .name = "Fujitsu MB86900",
900 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
901 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
902 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
903 .mmu_bm = 0x00004000,
904 .mmu_ctpr_mask = 0x007ffff0,
905 .mmu_cxr_mask = 0x0000003f,
906 .mmu_sfsr_mask = 0xffffffff,
907 .mmu_trcr_mask = 0xffffffff,
908 .nwindows = 7,
909 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
912 .name = "Fujitsu MB86904",
913 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
914 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
915 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
916 .mmu_bm = 0x00004000,
917 .mmu_ctpr_mask = 0x00ffffc0,
918 .mmu_cxr_mask = 0x000000ff,
919 .mmu_sfsr_mask = 0x00016fff,
920 .mmu_trcr_mask = 0x00ffffff,
921 .nwindows = 8,
922 .features = CPU_DEFAULT_FEATURES,
925 .name = "Fujitsu MB86907",
926 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
927 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
928 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
929 .mmu_bm = 0x00004000,
930 .mmu_ctpr_mask = 0xffffffc0,
931 .mmu_cxr_mask = 0x000000ff,
932 .mmu_sfsr_mask = 0x00016fff,
933 .mmu_trcr_mask = 0xffffffff,
934 .nwindows = 8,
935 .features = CPU_DEFAULT_FEATURES,
938 .name = "LSI L64811",
939 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
940 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
941 .mmu_version = 0x10 << 24,
942 .mmu_bm = 0x00004000,
943 .mmu_ctpr_mask = 0x007ffff0,
944 .mmu_cxr_mask = 0x0000003f,
945 .mmu_sfsr_mask = 0xffffffff,
946 .mmu_trcr_mask = 0xffffffff,
947 .nwindows = 8,
948 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
949 CPU_FEATURE_FSMULD,
952 .name = "Cypress CY7C601",
953 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
954 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
955 .mmu_version = 0x10 << 24,
956 .mmu_bm = 0x00004000,
957 .mmu_ctpr_mask = 0x007ffff0,
958 .mmu_cxr_mask = 0x0000003f,
959 .mmu_sfsr_mask = 0xffffffff,
960 .mmu_trcr_mask = 0xffffffff,
961 .nwindows = 8,
962 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
963 CPU_FEATURE_FSMULD,
966 .name = "Cypress CY7C611",
967 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
968 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
969 .mmu_version = 0x10 << 24,
970 .mmu_bm = 0x00004000,
971 .mmu_ctpr_mask = 0x007ffff0,
972 .mmu_cxr_mask = 0x0000003f,
973 .mmu_sfsr_mask = 0xffffffff,
974 .mmu_trcr_mask = 0xffffffff,
975 .nwindows = 8,
976 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
977 CPU_FEATURE_FSMULD,
980 .name = "TI MicroSparc I",
981 .iu_version = 0x41000000,
982 .fpu_version = 4 << 17,
983 .mmu_version = 0x41000000,
984 .mmu_bm = 0x00004000,
985 .mmu_ctpr_mask = 0x007ffff0,
986 .mmu_cxr_mask = 0x0000003f,
987 .mmu_sfsr_mask = 0x00016fff,
988 .mmu_trcr_mask = 0x0000003f,
989 .nwindows = 7,
990 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
991 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
992 CPU_FEATURE_FMUL,
995 .name = "TI MicroSparc II",
996 .iu_version = 0x42000000,
997 .fpu_version = 4 << 17,
998 .mmu_version = 0x02000000,
999 .mmu_bm = 0x00004000,
1000 .mmu_ctpr_mask = 0x00ffffc0,
1001 .mmu_cxr_mask = 0x000000ff,
1002 .mmu_sfsr_mask = 0x00016fff,
1003 .mmu_trcr_mask = 0x00ffffff,
1004 .nwindows = 8,
1005 .features = CPU_DEFAULT_FEATURES,
1008 .name = "TI MicroSparc IIep",
1009 .iu_version = 0x42000000,
1010 .fpu_version = 4 << 17,
1011 .mmu_version = 0x04000000,
1012 .mmu_bm = 0x00004000,
1013 .mmu_ctpr_mask = 0x00ffffc0,
1014 .mmu_cxr_mask = 0x000000ff,
1015 .mmu_sfsr_mask = 0x00016bff,
1016 .mmu_trcr_mask = 0x00ffffff,
1017 .nwindows = 8,
1018 .features = CPU_DEFAULT_FEATURES,
1021 .name = "TI SuperSparc 40", // STP1020NPGA
1022 .iu_version = 0x41000000, // SuperSPARC 2.x
1023 .fpu_version = 0 << 17,
1024 .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
1025 .mmu_bm = 0x00002000,
1026 .mmu_ctpr_mask = 0xffffffc0,
1027 .mmu_cxr_mask = 0x0000ffff,
1028 .mmu_sfsr_mask = 0xffffffff,
1029 .mmu_trcr_mask = 0xffffffff,
1030 .nwindows = 8,
1031 .features = CPU_DEFAULT_FEATURES,
1034 .name = "TI SuperSparc 50", // STP1020PGA
1035 .iu_version = 0x40000000, // SuperSPARC 3.x
1036 .fpu_version = 0 << 17,
1037 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1038 .mmu_bm = 0x00002000,
1039 .mmu_ctpr_mask = 0xffffffc0,
1040 .mmu_cxr_mask = 0x0000ffff,
1041 .mmu_sfsr_mask = 0xffffffff,
1042 .mmu_trcr_mask = 0xffffffff,
1043 .nwindows = 8,
1044 .features = CPU_DEFAULT_FEATURES,
1047 .name = "TI SuperSparc 51",
1048 .iu_version = 0x40000000, // SuperSPARC 3.x
1049 .fpu_version = 0 << 17,
1050 .mmu_version = 0x01000000, // SuperSPARC 3.x, 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 .mxcc_version = 0x00000104,
1057 .nwindows = 8,
1058 .features = CPU_DEFAULT_FEATURES,
1061 .name = "TI SuperSparc 60", // STP1020APGA
1062 .iu_version = 0x40000000, // SuperSPARC 3.x
1063 .fpu_version = 0 << 17,
1064 .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
1065 .mmu_bm = 0x00002000,
1066 .mmu_ctpr_mask = 0xffffffc0,
1067 .mmu_cxr_mask = 0x0000ffff,
1068 .mmu_sfsr_mask = 0xffffffff,
1069 .mmu_trcr_mask = 0xffffffff,
1070 .nwindows = 8,
1071 .features = CPU_DEFAULT_FEATURES,
1074 .name = "TI SuperSparc 61",
1075 .iu_version = 0x44000000, // SuperSPARC 3.x
1076 .fpu_version = 0 << 17,
1077 .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
1078 .mmu_bm = 0x00002000,
1079 .mmu_ctpr_mask = 0xffffffc0,
1080 .mmu_cxr_mask = 0x0000ffff,
1081 .mmu_sfsr_mask = 0xffffffff,
1082 .mmu_trcr_mask = 0xffffffff,
1083 .mxcc_version = 0x00000104,
1084 .nwindows = 8,
1085 .features = CPU_DEFAULT_FEATURES,
1088 .name = "TI SuperSparc II",
1089 .iu_version = 0x40000000, // SuperSPARC II 1.x
1090 .fpu_version = 0 << 17,
1091 .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
1092 .mmu_bm = 0x00002000,
1093 .mmu_ctpr_mask = 0xffffffc0,
1094 .mmu_cxr_mask = 0x0000ffff,
1095 .mmu_sfsr_mask = 0xffffffff,
1096 .mmu_trcr_mask = 0xffffffff,
1097 .mxcc_version = 0x00000104,
1098 .nwindows = 8,
1099 .features = CPU_DEFAULT_FEATURES,
1102 .name = "Ross RT625",
1103 .iu_version = 0x1e000000,
1104 .fpu_version = 1 << 17,
1105 .mmu_version = 0x1e000000,
1106 .mmu_bm = 0x00004000,
1107 .mmu_ctpr_mask = 0x007ffff0,
1108 .mmu_cxr_mask = 0x0000003f,
1109 .mmu_sfsr_mask = 0xffffffff,
1110 .mmu_trcr_mask = 0xffffffff,
1111 .nwindows = 8,
1112 .features = CPU_DEFAULT_FEATURES,
1115 .name = "Ross RT620",
1116 .iu_version = 0x1f000000,
1117 .fpu_version = 1 << 17,
1118 .mmu_version = 0x1f000000,
1119 .mmu_bm = 0x00004000,
1120 .mmu_ctpr_mask = 0x007ffff0,
1121 .mmu_cxr_mask = 0x0000003f,
1122 .mmu_sfsr_mask = 0xffffffff,
1123 .mmu_trcr_mask = 0xffffffff,
1124 .nwindows = 8,
1125 .features = CPU_DEFAULT_FEATURES,
1128 .name = "BIT B5010",
1129 .iu_version = 0x20000000,
1130 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1131 .mmu_version = 0x20000000,
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_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1139 CPU_FEATURE_FSMULD,
1142 .name = "Matsushita MN10501",
1143 .iu_version = 0x50000000,
1144 .fpu_version = 0 << 17,
1145 .mmu_version = 0x50000000,
1146 .mmu_bm = 0x00004000,
1147 .mmu_ctpr_mask = 0x007ffff0,
1148 .mmu_cxr_mask = 0x0000003f,
1149 .mmu_sfsr_mask = 0xffffffff,
1150 .mmu_trcr_mask = 0xffffffff,
1151 .nwindows = 8,
1152 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1153 CPU_FEATURE_FSMULD,
1156 .name = "Weitek W8601",
1157 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1158 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1159 .mmu_version = 0x10 << 24,
1160 .mmu_bm = 0x00004000,
1161 .mmu_ctpr_mask = 0x007ffff0,
1162 .mmu_cxr_mask = 0x0000003f,
1163 .mmu_sfsr_mask = 0xffffffff,
1164 .mmu_trcr_mask = 0xffffffff,
1165 .nwindows = 8,
1166 .features = CPU_DEFAULT_FEATURES,
1169 .name = "LEON2",
1170 .iu_version = 0xf2000000,
1171 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1172 .mmu_version = 0xf2000000,
1173 .mmu_bm = 0x00004000,
1174 .mmu_ctpr_mask = 0x007ffff0,
1175 .mmu_cxr_mask = 0x0000003f,
1176 .mmu_sfsr_mask = 0xffffffff,
1177 .mmu_trcr_mask = 0xffffffff,
1178 .nwindows = 8,
1179 .features = CPU_DEFAULT_FEATURES,
1182 .name = "LEON3",
1183 .iu_version = 0xf3000000,
1184 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1185 .mmu_version = 0xf3000000,
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,
1194 #endif
1197 static const char * const feature_name[] = {
1198 "float",
1199 "float128",
1200 "swap",
1201 "mul",
1202 "div",
1203 "flush",
1204 "fsqrt",
1205 "fmul",
1206 "vis1",
1207 "vis2",
1208 "fsmuld",
1209 "hypv",
1210 "cmt",
1211 "gl",
1214 static void print_features(FILE *f,
1215 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1216 uint32_t features, const char *prefix)
1218 unsigned int i;
1220 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1221 if (feature_name[i] && (features & (1 << i))) {
1222 if (prefix)
1223 (*cpu_fprintf)(f, "%s", prefix);
1224 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1228 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1230 unsigned int i;
1232 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1233 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1234 *features |= 1 << i;
1235 return;
1237 fprintf(stderr, "CPU feature %s not found\n", flagname);
1240 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1242 unsigned int i;
1243 const sparc_def_t *def = NULL;
1244 char *s = strdup(cpu_model);
1245 char *featurestr, *name = strtok(s, ",");
1246 uint32_t plus_features = 0;
1247 uint32_t minus_features = 0;
1248 long long iu_version;
1249 uint32_t fpu_version, mmu_version, nwindows;
1251 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1252 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1253 def = &sparc_defs[i];
1256 if (!def)
1257 goto error;
1258 memcpy(cpu_def, def, sizeof(*def));
1260 featurestr = strtok(NULL, ",");
1261 while (featurestr) {
1262 char *val;
1264 if (featurestr[0] == '+') {
1265 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1266 } else if (featurestr[0] == '-') {
1267 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1268 } else if ((val = strchr(featurestr, '='))) {
1269 *val = 0; val++;
1270 if (!strcmp(featurestr, "iu_version")) {
1271 char *err;
1273 iu_version = strtoll(val, &err, 0);
1274 if (!*val || *err) {
1275 fprintf(stderr, "bad numerical value %s\n", val);
1276 goto error;
1278 cpu_def->iu_version = iu_version;
1279 #ifdef DEBUG_FEATURES
1280 fprintf(stderr, "iu_version %llx\n", iu_version);
1281 #endif
1282 } else if (!strcmp(featurestr, "fpu_version")) {
1283 char *err;
1285 fpu_version = strtol(val, &err, 0);
1286 if (!*val || *err) {
1287 fprintf(stderr, "bad numerical value %s\n", val);
1288 goto error;
1290 cpu_def->fpu_version = fpu_version;
1291 #ifdef DEBUG_FEATURES
1292 fprintf(stderr, "fpu_version %llx\n", fpu_version);
1293 #endif
1294 } else if (!strcmp(featurestr, "mmu_version")) {
1295 char *err;
1297 mmu_version = strtol(val, &err, 0);
1298 if (!*val || *err) {
1299 fprintf(stderr, "bad numerical value %s\n", val);
1300 goto error;
1302 cpu_def->mmu_version = mmu_version;
1303 #ifdef DEBUG_FEATURES
1304 fprintf(stderr, "mmu_version %llx\n", mmu_version);
1305 #endif
1306 } else if (!strcmp(featurestr, "nwindows")) {
1307 char *err;
1309 nwindows = strtol(val, &err, 0);
1310 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1311 nwindows < MIN_NWINDOWS) {
1312 fprintf(stderr, "bad numerical value %s\n", val);
1313 goto error;
1315 cpu_def->nwindows = nwindows;
1316 #ifdef DEBUG_FEATURES
1317 fprintf(stderr, "nwindows %d\n", nwindows);
1318 #endif
1319 } else {
1320 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1321 goto error;
1323 } else {
1324 fprintf(stderr, "feature string `%s' not in format "
1325 "(+feature|-feature|feature=xyz)\n", featurestr);
1326 goto error;
1328 featurestr = strtok(NULL, ",");
1330 cpu_def->features |= plus_features;
1331 cpu_def->features &= ~minus_features;
1332 #ifdef DEBUG_FEATURES
1333 print_features(stderr, fprintf, cpu_def->features, NULL);
1334 #endif
1335 free(s);
1336 return 0;
1338 error:
1339 free(s);
1340 return -1;
1343 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1345 unsigned int i;
1347 for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
1348 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1349 sparc_defs[i].name,
1350 sparc_defs[i].iu_version,
1351 sparc_defs[i].fpu_version,
1352 sparc_defs[i].mmu_version,
1353 sparc_defs[i].nwindows);
1354 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1355 ~sparc_defs[i].features, "-");
1356 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1357 sparc_defs[i].features, "+");
1358 (*cpu_fprintf)(f, "\n");
1360 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1361 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1362 (*cpu_fprintf)(f, "\n");
1363 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1364 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1365 (*cpu_fprintf)(f, "\n");
1366 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1367 "fpu_version mmu_version nwindows\n");
1370 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1372 void cpu_dump_state(CPUState *env, FILE *f,
1373 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1374 int flags)
1376 int i, x;
1378 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1379 env->npc);
1380 cpu_fprintf(f, "General Registers:\n");
1381 for (i = 0; i < 4; i++)
1382 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1383 cpu_fprintf(f, "\n");
1384 for (; i < 8; i++)
1385 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1386 cpu_fprintf(f, "\nCurrent Register Window:\n");
1387 for (x = 0; x < 3; x++) {
1388 for (i = 0; i < 4; i++)
1389 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1390 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1391 env->regwptr[i + x * 8]);
1392 cpu_fprintf(f, "\n");
1393 for (; i < 8; i++)
1394 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1395 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1396 env->regwptr[i + x * 8]);
1397 cpu_fprintf(f, "\n");
1399 cpu_fprintf(f, "\nFloating Point Registers:\n");
1400 for (i = 0; i < 32; i++) {
1401 if ((i & 3) == 0)
1402 cpu_fprintf(f, "%%f%02d:", i);
1403 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1404 if ((i & 3) == 3)
1405 cpu_fprintf(f, "\n");
1407 #ifdef TARGET_SPARC64
1408 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1409 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1410 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1411 "cleanwin %d cwp %d\n",
1412 env->cansave, env->canrestore, env->otherwin, env->wstate,
1413 env->cleanwin, env->nwindows - 1 - env->cwp);
1414 #else
1415 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1416 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1417 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1418 env->psrs?'S':'-', env->psrps?'P':'-',
1419 env->psret?'E':'-', env->wim);
1420 #endif
1421 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);