Implement ldxfsr/stxfsr, fix ld(x)fsr masks, convert to TCG
[qemu/mini2440.git] / target-sparc / helper.c
blob14014805d49acdd412f93cabf3afae5a8df12da5
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
34 //#define DEBUG_PCALL
36 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
38 /* Sparc MMU emulation */
40 /* thread support */
42 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
44 void cpu_lock(void)
46 spin_lock(&global_cpu_lock);
49 void cpu_unlock(void)
51 spin_unlock(&global_cpu_lock);
54 #if defined(CONFIG_USER_ONLY)
56 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
57 int mmu_idx, int is_softmmu)
59 if (rw & 2)
60 env1->exception_index = TT_TFAULT;
61 else
62 env1->exception_index = TT_DFAULT;
63 return 1;
66 #else
68 #ifndef TARGET_SPARC64
70 * Sparc V8 Reference MMU (SRMMU)
72 static const int access_table[8][8] = {
73 { 0, 0, 0, 0, 8, 0, 12, 12 },
74 { 0, 0, 0, 0, 8, 0, 0, 0 },
75 { 8, 8, 0, 0, 0, 8, 12, 12 },
76 { 8, 8, 0, 0, 0, 8, 0, 0 },
77 { 8, 0, 8, 0, 8, 8, 12, 12 },
78 { 8, 0, 8, 0, 8, 0, 8, 0 },
79 { 8, 8, 8, 0, 8, 8, 12, 12 },
80 { 8, 8, 8, 0, 8, 8, 8, 0 }
83 static const int perm_table[2][8] = {
85 PAGE_READ,
86 PAGE_READ | PAGE_WRITE,
87 PAGE_READ | PAGE_EXEC,
88 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
89 PAGE_EXEC,
90 PAGE_READ | PAGE_WRITE,
91 PAGE_READ | PAGE_EXEC,
92 PAGE_READ | PAGE_WRITE | PAGE_EXEC
95 PAGE_READ,
96 PAGE_READ | PAGE_WRITE,
97 PAGE_READ | PAGE_EXEC,
98 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
99 PAGE_EXEC,
100 PAGE_READ,
106 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
107 int *prot, int *access_index,
108 target_ulong address, int rw, int mmu_idx)
110 int access_perms = 0;
111 target_phys_addr_t pde_ptr;
112 uint32_t pde;
113 target_ulong virt_addr;
114 int error_code = 0, is_dirty, is_user;
115 unsigned long page_offset;
117 is_user = mmu_idx == MMU_USER_IDX;
118 virt_addr = address & TARGET_PAGE_MASK;
120 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
121 // Boot mode: instruction fetches are taken from PROM
122 if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
123 *physical = env->prom_addr | (address & 0x7ffffULL);
124 *prot = PAGE_READ | PAGE_EXEC;
125 return 0;
127 *physical = address;
128 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
129 return 0;
132 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
133 *physical = 0xffffffffffff0000ULL;
135 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
136 /* Context base + context number */
137 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
138 pde = ldl_phys(pde_ptr);
140 /* Ctx pde */
141 switch (pde & PTE_ENTRYTYPE_MASK) {
142 default:
143 case 0: /* Invalid */
144 return 1 << 2;
145 case 2: /* L0 PTE, maybe should not happen? */
146 case 3: /* Reserved */
147 return 4 << 2;
148 case 1: /* L0 PDE */
149 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
150 pde = ldl_phys(pde_ptr);
152 switch (pde & PTE_ENTRYTYPE_MASK) {
153 default:
154 case 0: /* Invalid */
155 return (1 << 8) | (1 << 2);
156 case 3: /* Reserved */
157 return (1 << 8) | (4 << 2);
158 case 1: /* L1 PDE */
159 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
160 pde = ldl_phys(pde_ptr);
162 switch (pde & PTE_ENTRYTYPE_MASK) {
163 default:
164 case 0: /* Invalid */
165 return (2 << 8) | (1 << 2);
166 case 3: /* Reserved */
167 return (2 << 8) | (4 << 2);
168 case 1: /* L2 PDE */
169 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
170 pde = ldl_phys(pde_ptr);
172 switch (pde & PTE_ENTRYTYPE_MASK) {
173 default:
174 case 0: /* Invalid */
175 return (3 << 8) | (1 << 2);
176 case 1: /* PDE, should not happen */
177 case 3: /* Reserved */
178 return (3 << 8) | (4 << 2);
179 case 2: /* L3 PTE */
180 virt_addr = address & TARGET_PAGE_MASK;
181 page_offset = (address & TARGET_PAGE_MASK) &
182 (TARGET_PAGE_SIZE - 1);
184 break;
185 case 2: /* L2 PTE */
186 virt_addr = address & ~0x3ffff;
187 page_offset = address & 0x3ffff;
189 break;
190 case 2: /* L1 PTE */
191 virt_addr = address & ~0xffffff;
192 page_offset = address & 0xffffff;
196 /* update page modified and dirty bits */
197 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
198 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
199 pde |= PG_ACCESSED_MASK;
200 if (is_dirty)
201 pde |= PG_MODIFIED_MASK;
202 stl_phys_notdirty(pde_ptr, pde);
204 /* check access */
205 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
206 error_code = access_table[*access_index][access_perms];
207 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
208 return error_code;
210 /* the page can be put in the TLB */
211 *prot = perm_table[is_user][access_perms];
212 if (!(pde & PG_MODIFIED_MASK)) {
213 /* only set write access if already dirty... otherwise wait
214 for dirty access */
215 *prot &= ~PAGE_WRITE;
218 /* Even if large ptes, we map only one 4KB page in the cache to
219 avoid filling it too fast */
220 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
221 return error_code;
224 /* Perform address translation */
225 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
226 int mmu_idx, int is_softmmu)
228 target_phys_addr_t paddr;
229 target_ulong vaddr;
230 int error_code = 0, prot, ret = 0, access_index;
232 error_code = get_physical_address(env, &paddr, &prot, &access_index,
233 address, rw, mmu_idx);
234 if (error_code == 0) {
235 vaddr = address & TARGET_PAGE_MASK;
236 paddr &= TARGET_PAGE_MASK;
237 #ifdef DEBUG_MMU
238 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
239 TARGET_FMT_lx "\n", address, paddr, vaddr);
240 #endif
241 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
242 return ret;
245 if (env->mmuregs[3]) /* Fault status register */
246 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
247 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
248 env->mmuregs[4] = address; /* Fault address register */
250 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
251 // No fault mode: if a mapping is available, just override
252 // permissions. If no mapping is available, redirect accesses to
253 // neverland. Fake/overridden mappings will be flushed when
254 // switching to normal mode.
255 vaddr = address & TARGET_PAGE_MASK;
256 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
257 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
258 return ret;
259 } else {
260 if (rw & 2)
261 env->exception_index = TT_TFAULT;
262 else
263 env->exception_index = TT_DFAULT;
264 return 1;
268 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
270 target_phys_addr_t pde_ptr;
271 uint32_t pde;
273 /* Context base + context number */
274 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
275 (env->mmuregs[2] << 2);
276 pde = ldl_phys(pde_ptr);
278 switch (pde & PTE_ENTRYTYPE_MASK) {
279 default:
280 case 0: /* Invalid */
281 case 2: /* PTE, maybe should not happen? */
282 case 3: /* Reserved */
283 return 0;
284 case 1: /* L1 PDE */
285 if (mmulev == 3)
286 return pde;
287 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
288 pde = ldl_phys(pde_ptr);
290 switch (pde & PTE_ENTRYTYPE_MASK) {
291 default:
292 case 0: /* Invalid */
293 case 3: /* Reserved */
294 return 0;
295 case 2: /* L1 PTE */
296 return pde;
297 case 1: /* L2 PDE */
298 if (mmulev == 2)
299 return pde;
300 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
301 pde = ldl_phys(pde_ptr);
303 switch (pde & PTE_ENTRYTYPE_MASK) {
304 default:
305 case 0: /* Invalid */
306 case 3: /* Reserved */
307 return 0;
308 case 2: /* L2 PTE */
309 return pde;
310 case 1: /* L3 PDE */
311 if (mmulev == 1)
312 return pde;
313 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
314 pde = ldl_phys(pde_ptr);
316 switch (pde & PTE_ENTRYTYPE_MASK) {
317 default:
318 case 0: /* Invalid */
319 case 1: /* PDE, should not happen */
320 case 3: /* Reserved */
321 return 0;
322 case 2: /* L3 PTE */
323 return pde;
328 return 0;
331 #ifdef DEBUG_MMU
332 void dump_mmu(CPUState *env)
334 target_ulong va, va1, va2;
335 unsigned int n, m, o;
336 target_phys_addr_t pde_ptr, pa;
337 uint32_t pde;
339 printf("MMU dump:\n");
340 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
341 pde = ldl_phys(pde_ptr);
342 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
343 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
344 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
345 pde = mmu_probe(env, va, 2);
346 if (pde) {
347 pa = cpu_get_phys_page_debug(env, va);
348 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
349 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
350 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
351 pde = mmu_probe(env, va1, 1);
352 if (pde) {
353 pa = cpu_get_phys_page_debug(env, va1);
354 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
355 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
356 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
357 pde = mmu_probe(env, va2, 0);
358 if (pde) {
359 pa = cpu_get_phys_page_debug(env, va2);
360 printf(" VA: " TARGET_FMT_lx ", PA: "
361 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
362 va2, pa, pde);
369 printf("MMU dump ends\n");
371 #endif /* DEBUG_MMU */
373 #else /* !TARGET_SPARC64 */
375 * UltraSparc IIi I/DMMUs
377 static int get_physical_address_data(CPUState *env,
378 target_phys_addr_t *physical, int *prot,
379 target_ulong address, int rw, int is_user)
381 target_ulong mask;
382 unsigned int i;
384 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
385 *physical = address;
386 *prot = PAGE_READ | PAGE_WRITE;
387 return 0;
390 for (i = 0; i < 64; i++) {
391 switch ((env->dtlb_tte[i] >> 61) & 3) {
392 default:
393 case 0x0: // 8k
394 mask = 0xffffffffffffe000ULL;
395 break;
396 case 0x1: // 64k
397 mask = 0xffffffffffff0000ULL;
398 break;
399 case 0x2: // 512k
400 mask = 0xfffffffffff80000ULL;
401 break;
402 case 0x3: // 4M
403 mask = 0xffffffffffc00000ULL;
404 break;
406 // ctx match, vaddr match?
407 if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
408 (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
409 // valid, access ok?
410 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
411 ((env->dtlb_tte[i] & 0x4) && is_user) ||
412 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
413 if (env->dmmuregs[3]) /* Fault status register */
414 env->dmmuregs[3] = 2; /* overflow (not read before
415 another fault) */
416 env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
417 env->dmmuregs[4] = address; /* Fault address register */
418 env->exception_index = TT_DFAULT;
419 #ifdef DEBUG_MMU
420 printf("DFAULT at 0x%" PRIx64 "\n", address);
421 #endif
422 return 1;
424 *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
425 (address & ~mask & 0x1fffffff000ULL);
426 *prot = PAGE_READ;
427 if (env->dtlb_tte[i] & 0x2)
428 *prot |= PAGE_WRITE;
429 return 0;
432 #ifdef DEBUG_MMU
433 printf("DMISS at 0x%" PRIx64 "\n", address);
434 #endif
435 env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
436 env->exception_index = TT_DMISS;
437 return 1;
440 static int get_physical_address_code(CPUState *env,
441 target_phys_addr_t *physical, int *prot,
442 target_ulong address, int is_user)
444 target_ulong mask;
445 unsigned int i;
447 if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
448 *physical = address;
449 *prot = PAGE_EXEC;
450 return 0;
453 for (i = 0; i < 64; i++) {
454 switch ((env->itlb_tte[i] >> 61) & 3) {
455 default:
456 case 0x0: // 8k
457 mask = 0xffffffffffffe000ULL;
458 break;
459 case 0x1: // 64k
460 mask = 0xffffffffffff0000ULL;
461 break;
462 case 0x2: // 512k
463 mask = 0xfffffffffff80000ULL;
464 break;
465 case 0x3: // 4M
466 mask = 0xffffffffffc00000ULL;
467 break;
469 // ctx match, vaddr match?
470 if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
471 (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
472 // valid, access ok?
473 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
474 ((env->itlb_tte[i] & 0x4) && is_user)) {
475 if (env->immuregs[3]) /* Fault status register */
476 env->immuregs[3] = 2; /* overflow (not read before
477 another fault) */
478 env->immuregs[3] |= (is_user << 3) | 1;
479 env->exception_index = TT_TFAULT;
480 #ifdef DEBUG_MMU
481 printf("TFAULT at 0x%" PRIx64 "\n", address);
482 #endif
483 return 1;
485 *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
486 (address & ~mask & 0x1fffffff000ULL);
487 *prot = PAGE_EXEC;
488 return 0;
491 #ifdef DEBUG_MMU
492 printf("TMISS at 0x%" PRIx64 "\n", address);
493 #endif
494 env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
495 env->exception_index = TT_TMISS;
496 return 1;
499 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
500 int *prot, int *access_index,
501 target_ulong address, int rw, int mmu_idx)
503 int is_user = mmu_idx == MMU_USER_IDX;
505 if (rw == 2)
506 return get_physical_address_code(env, physical, prot, address,
507 is_user);
508 else
509 return get_physical_address_data(env, physical, prot, address, rw,
510 is_user);
513 /* Perform address translation */
514 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
515 int mmu_idx, int is_softmmu)
517 target_ulong virt_addr, vaddr;
518 target_phys_addr_t paddr;
519 int error_code = 0, prot, ret = 0, access_index;
521 error_code = get_physical_address(env, &paddr, &prot, &access_index,
522 address, rw, mmu_idx);
523 if (error_code == 0) {
524 virt_addr = address & TARGET_PAGE_MASK;
525 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
526 (TARGET_PAGE_SIZE - 1));
527 #ifdef DEBUG_MMU
528 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
529 "\n", address, paddr, vaddr);
530 #endif
531 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
532 return ret;
534 // XXX
535 return 1;
538 #ifdef DEBUG_MMU
539 void dump_mmu(CPUState *env)
541 unsigned int i;
542 const char *mask;
544 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
545 env->dmmuregs[1], env->dmmuregs[2]);
546 if ((env->lsu & DMMU_E) == 0) {
547 printf("DMMU disabled\n");
548 } else {
549 printf("DMMU dump:\n");
550 for (i = 0; i < 64; i++) {
551 switch ((env->dtlb_tte[i] >> 61) & 3) {
552 default:
553 case 0x0:
554 mask = " 8k";
555 break;
556 case 0x1:
557 mask = " 64k";
558 break;
559 case 0x2:
560 mask = "512k";
561 break;
562 case 0x3:
563 mask = " 4M";
564 break;
566 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
567 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
568 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
569 env->dtlb_tag[i] & ~0x1fffULL,
570 env->dtlb_tte[i] & 0x1ffffffe000ULL,
571 mask,
572 env->dtlb_tte[i] & 0x4? "priv": "user",
573 env->dtlb_tte[i] & 0x2? "RW": "RO",
574 env->dtlb_tte[i] & 0x40? "locked": "unlocked",
575 env->dtlb_tag[i] & 0x1fffULL);
579 if ((env->lsu & IMMU_E) == 0) {
580 printf("IMMU disabled\n");
581 } else {
582 printf("IMMU dump:\n");
583 for (i = 0; i < 64; i++) {
584 switch ((env->itlb_tte[i] >> 61) & 3) {
585 default:
586 case 0x0:
587 mask = " 8k";
588 break;
589 case 0x1:
590 mask = " 64k";
591 break;
592 case 0x2:
593 mask = "512k";
594 break;
595 case 0x3:
596 mask = " 4M";
597 break;
599 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
600 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
601 ", %s, %s, %s, ctx %" PRId64 "\n",
602 env->itlb_tag[i] & ~0x1fffULL,
603 env->itlb_tte[i] & 0x1ffffffe000ULL,
604 mask,
605 env->itlb_tte[i] & 0x4? "priv": "user",
606 env->itlb_tte[i] & 0x40? "locked": "unlocked",
607 env->itlb_tag[i] & 0x1fffULL);
612 #endif /* DEBUG_MMU */
614 #endif /* TARGET_SPARC64 */
615 #endif /* !CONFIG_USER_ONLY */
618 #if defined(CONFIG_USER_ONLY)
619 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
621 return addr;
624 #else
625 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
627 target_phys_addr_t phys_addr;
628 int prot, access_index;
630 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
631 MMU_KERNEL_IDX) != 0)
632 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
633 0, MMU_KERNEL_IDX) != 0)
634 return -1;
635 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
636 return -1;
637 return phys_addr;
639 #endif
641 void cpu_reset(CPUSPARCState *env)
643 tlb_flush(env, 1);
644 env->cwp = 0;
645 env->wim = 1;
646 env->regwptr = env->regbase + (env->cwp * 16);
647 #if defined(CONFIG_USER_ONLY)
648 env->user_mode_only = 1;
649 #ifdef TARGET_SPARC64
650 env->cleanwin = env->nwindows - 2;
651 env->cansave = env->nwindows - 2;
652 env->pstate = PS_RMO | PS_PEF | PS_IE;
653 env->asi = 0x82; // Primary no-fault
654 #endif
655 #else
656 env->psret = 0;
657 env->psrs = 1;
658 env->psrps = 1;
659 #ifdef TARGET_SPARC64
660 env->pstate = PS_PRIV;
661 env->hpstate = HS_PRIV;
662 env->pc = 0x1fff0000020ULL; // XXX should be different for system_reset
663 env->tsptr = &env->ts[env->tl & MAXTL_MASK];
664 #else
665 env->pc = 0;
666 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
667 env->mmuregs[0] |= env->def->mmu_bm;
668 #endif
669 env->npc = env->pc + 4;
670 #endif
673 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
675 sparc_def_t def1, *def = &def1;
677 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
678 return -1;
680 env->def = qemu_mallocz(sizeof(*def));
681 memcpy(env->def, def, sizeof(*def));
682 #if defined(CONFIG_USER_ONLY)
683 if ((env->def->features & CPU_FEATURE_FLOAT))
684 env->def->features |= CPU_FEATURE_FLOAT128;
685 #endif
686 env->cpu_model_str = cpu_model;
687 env->version = def->iu_version;
688 env->fsr = def->fpu_version;
689 env->nwindows = def->nwindows;
690 #if !defined(TARGET_SPARC64)
691 env->mmuregs[0] |= def->mmu_version;
692 cpu_sparc_set_id(env, 0);
693 #else
694 env->mmu_version = def->mmu_version;
695 env->maxtl = def->maxtl;
696 env->version |= def->maxtl << 8;
697 env->version |= def->nwindows - 1;
698 #endif
699 return 0;
702 static void cpu_sparc_close(CPUSPARCState *env)
704 free(env->def);
705 free(env);
708 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
710 CPUSPARCState *env;
712 env = qemu_mallocz(sizeof(CPUSPARCState));
713 if (!env)
714 return NULL;
715 cpu_exec_init(env);
717 gen_intermediate_code_init(env);
719 if (cpu_sparc_register(env, cpu_model) < 0) {
720 cpu_sparc_close(env);
721 return NULL;
723 cpu_reset(env);
725 return env;
728 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
730 #if !defined(TARGET_SPARC64)
731 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
732 #endif
735 static const sparc_def_t sparc_defs[] = {
736 #ifdef TARGET_SPARC64
738 .name = "Fujitsu Sparc64",
739 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
740 .fpu_version = 0x00000000,
741 .mmu_version = mmu_us_12,
742 .nwindows = 4,
743 .maxtl = 4,
744 .features = CPU_DEFAULT_FEATURES,
747 .name = "Fujitsu Sparc64 III",
748 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
749 .fpu_version = 0x00000000,
750 .mmu_version = mmu_us_12,
751 .nwindows = 5,
752 .maxtl = 4,
753 .features = CPU_DEFAULT_FEATURES,
756 .name = "Fujitsu Sparc64 IV",
757 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
758 .fpu_version = 0x00000000,
759 .mmu_version = mmu_us_12,
760 .nwindows = 8,
761 .maxtl = 5,
762 .features = CPU_DEFAULT_FEATURES,
765 .name = "Fujitsu Sparc64 V",
766 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
767 .fpu_version = 0x00000000,
768 .mmu_version = mmu_us_12,
769 .nwindows = 8,
770 .maxtl = 5,
771 .features = CPU_DEFAULT_FEATURES,
774 .name = "TI UltraSparc I",
775 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
776 .fpu_version = 0x00000000,
777 .mmu_version = mmu_us_12,
778 .nwindows = 8,
779 .maxtl = 5,
780 .features = CPU_DEFAULT_FEATURES,
783 .name = "TI UltraSparc II",
784 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
785 .fpu_version = 0x00000000,
786 .mmu_version = mmu_us_12,
787 .nwindows = 8,
788 .maxtl = 5,
789 .features = CPU_DEFAULT_FEATURES,
792 .name = "TI UltraSparc IIi",
793 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
794 .fpu_version = 0x00000000,
795 .mmu_version = mmu_us_12,
796 .nwindows = 8,
797 .maxtl = 5,
798 .features = CPU_DEFAULT_FEATURES,
801 .name = "TI UltraSparc IIe",
802 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
803 .fpu_version = 0x00000000,
804 .mmu_version = mmu_us_12,
805 .nwindows = 8,
806 .maxtl = 5,
807 .features = CPU_DEFAULT_FEATURES,
810 .name = "Sun UltraSparc III",
811 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
812 .fpu_version = 0x00000000,
813 .mmu_version = mmu_us_12,
814 .nwindows = 8,
815 .maxtl = 5,
816 .features = CPU_DEFAULT_FEATURES,
819 .name = "Sun UltraSparc III Cu",
820 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
821 .fpu_version = 0x00000000,
822 .mmu_version = mmu_us_3,
823 .nwindows = 8,
824 .maxtl = 5,
825 .features = CPU_DEFAULT_FEATURES,
828 .name = "Sun UltraSparc IIIi",
829 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
830 .fpu_version = 0x00000000,
831 .mmu_version = mmu_us_12,
832 .nwindows = 8,
833 .maxtl = 5,
834 .features = CPU_DEFAULT_FEATURES,
837 .name = "Sun UltraSparc IV",
838 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
839 .fpu_version = 0x00000000,
840 .mmu_version = mmu_us_4,
841 .nwindows = 8,
842 .maxtl = 5,
843 .features = CPU_DEFAULT_FEATURES,
846 .name = "Sun UltraSparc IV+",
847 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
848 .fpu_version = 0x00000000,
849 .mmu_version = mmu_us_12,
850 .nwindows = 8,
851 .maxtl = 5,
852 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
855 .name = "Sun UltraSparc IIIi+",
856 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
857 .fpu_version = 0x00000000,
858 .mmu_version = mmu_us_3,
859 .nwindows = 8,
860 .maxtl = 5,
861 .features = CPU_DEFAULT_FEATURES,
864 .name = "Sun UltraSparc T1",
865 // defined in sparc_ifu_fdp.v and ctu.h
866 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
867 .fpu_version = 0x00000000,
868 .mmu_version = mmu_sun4v,
869 .nwindows = 8,
870 .maxtl = 6,
871 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
872 | CPU_FEATURE_GL,
875 .name = "Sun UltraSparc T2",
876 // defined in tlu_asi_ctl.v and n2_revid_cust.v
877 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
878 .fpu_version = 0x00000000,
879 .mmu_version = mmu_sun4v,
880 .nwindows = 8,
881 .maxtl = 6,
882 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
883 | CPU_FEATURE_GL,
886 .name = "NEC UltraSparc I",
887 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
888 .fpu_version = 0x00000000,
889 .mmu_version = mmu_us_12,
890 .nwindows = 8,
891 .maxtl = 5,
892 .features = CPU_DEFAULT_FEATURES,
894 #else
896 .name = "Fujitsu MB86900",
897 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
898 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
899 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
900 .mmu_bm = 0x00004000,
901 .mmu_ctpr_mask = 0x007ffff0,
902 .mmu_cxr_mask = 0x0000003f,
903 .mmu_sfsr_mask = 0xffffffff,
904 .mmu_trcr_mask = 0xffffffff,
905 .nwindows = 7,
906 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
909 .name = "Fujitsu MB86904",
910 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
911 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
912 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
913 .mmu_bm = 0x00004000,
914 .mmu_ctpr_mask = 0x00ffffc0,
915 .mmu_cxr_mask = 0x000000ff,
916 .mmu_sfsr_mask = 0x00016fff,
917 .mmu_trcr_mask = 0x00ffffff,
918 .nwindows = 8,
919 .features = CPU_DEFAULT_FEATURES,
922 .name = "Fujitsu MB86907",
923 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
924 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
925 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
926 .mmu_bm = 0x00004000,
927 .mmu_ctpr_mask = 0xffffffc0,
928 .mmu_cxr_mask = 0x000000ff,
929 .mmu_sfsr_mask = 0x00016fff,
930 .mmu_trcr_mask = 0xffffffff,
931 .nwindows = 8,
932 .features = CPU_DEFAULT_FEATURES,
935 .name = "LSI L64811",
936 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
937 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
938 .mmu_version = 0x10 << 24,
939 .mmu_bm = 0x00004000,
940 .mmu_ctpr_mask = 0x007ffff0,
941 .mmu_cxr_mask = 0x0000003f,
942 .mmu_sfsr_mask = 0xffffffff,
943 .mmu_trcr_mask = 0xffffffff,
944 .nwindows = 8,
945 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
946 CPU_FEATURE_FSMULD,
949 .name = "Cypress CY7C601",
950 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
951 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
952 .mmu_version = 0x10 << 24,
953 .mmu_bm = 0x00004000,
954 .mmu_ctpr_mask = 0x007ffff0,
955 .mmu_cxr_mask = 0x0000003f,
956 .mmu_sfsr_mask = 0xffffffff,
957 .mmu_trcr_mask = 0xffffffff,
958 .nwindows = 8,
959 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
960 CPU_FEATURE_FSMULD,
963 .name = "Cypress CY7C611",
964 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
965 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
966 .mmu_version = 0x10 << 24,
967 .mmu_bm = 0x00004000,
968 .mmu_ctpr_mask = 0x007ffff0,
969 .mmu_cxr_mask = 0x0000003f,
970 .mmu_sfsr_mask = 0xffffffff,
971 .mmu_trcr_mask = 0xffffffff,
972 .nwindows = 8,
973 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
974 CPU_FEATURE_FSMULD,
977 .name = "TI SuperSparc II",
978 .iu_version = 0x40000000,
979 .fpu_version = 0 << 17,
980 .mmu_version = 0x04000000,
981 .mmu_bm = 0x00002000,
982 .mmu_ctpr_mask = 0xffffffc0,
983 .mmu_cxr_mask = 0x0000ffff,
984 .mmu_sfsr_mask = 0xffffffff,
985 .mmu_trcr_mask = 0xffffffff,
986 .nwindows = 8,
987 .features = CPU_DEFAULT_FEATURES,
990 .name = "TI MicroSparc I",
991 .iu_version = 0x41000000,
992 .fpu_version = 4 << 17,
993 .mmu_version = 0x41000000,
994 .mmu_bm = 0x00004000,
995 .mmu_ctpr_mask = 0x007ffff0,
996 .mmu_cxr_mask = 0x0000003f,
997 .mmu_sfsr_mask = 0x00016fff,
998 .mmu_trcr_mask = 0x0000003f,
999 .nwindows = 7,
1000 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1001 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1002 CPU_FEATURE_FMUL,
1005 .name = "TI MicroSparc II",
1006 .iu_version = 0x42000000,
1007 .fpu_version = 4 << 17,
1008 .mmu_version = 0x02000000,
1009 .mmu_bm = 0x00004000,
1010 .mmu_ctpr_mask = 0x00ffffc0,
1011 .mmu_cxr_mask = 0x000000ff,
1012 .mmu_sfsr_mask = 0x00016fff,
1013 .mmu_trcr_mask = 0x00ffffff,
1014 .nwindows = 8,
1015 .features = CPU_DEFAULT_FEATURES,
1018 .name = "TI MicroSparc IIep",
1019 .iu_version = 0x42000000,
1020 .fpu_version = 4 << 17,
1021 .mmu_version = 0x04000000,
1022 .mmu_bm = 0x00004000,
1023 .mmu_ctpr_mask = 0x00ffffc0,
1024 .mmu_cxr_mask = 0x000000ff,
1025 .mmu_sfsr_mask = 0x00016bff,
1026 .mmu_trcr_mask = 0x00ffffff,
1027 .nwindows = 8,
1028 .features = CPU_DEFAULT_FEATURES,
1031 .name = "TI SuperSparc 40", // STP1020NPGA
1032 .iu_version = 0x41000000,
1033 .fpu_version = 0 << 17,
1034 .mmu_version = 0x00000000,
1035 .mmu_bm = 0x00002000,
1036 .mmu_ctpr_mask = 0xffffffc0,
1037 .mmu_cxr_mask = 0x0000ffff,
1038 .mmu_sfsr_mask = 0xffffffff,
1039 .mmu_trcr_mask = 0xffffffff,
1040 .nwindows = 8,
1041 .features = CPU_DEFAULT_FEATURES,
1044 .name = "TI SuperSparc 50", // STP1020PGA
1045 .iu_version = 0x40000000,
1046 .fpu_version = 0 << 17,
1047 .mmu_version = 0x04000000,
1048 .mmu_bm = 0x00002000,
1049 .mmu_ctpr_mask = 0xffffffc0,
1050 .mmu_cxr_mask = 0x0000ffff,
1051 .mmu_sfsr_mask = 0xffffffff,
1052 .mmu_trcr_mask = 0xffffffff,
1053 .nwindows = 8,
1054 .features = CPU_DEFAULT_FEATURES,
1057 .name = "TI SuperSparc 51",
1058 .iu_version = 0x43000000,
1059 .fpu_version = 0 << 17,
1060 .mmu_version = 0x04000000,
1061 .mmu_bm = 0x00002000,
1062 .mmu_ctpr_mask = 0xffffffc0,
1063 .mmu_cxr_mask = 0x0000ffff,
1064 .mmu_sfsr_mask = 0xffffffff,
1065 .mmu_trcr_mask = 0xffffffff,
1066 .nwindows = 8,
1067 .features = CPU_DEFAULT_FEATURES,
1070 .name = "TI SuperSparc 60", // STP1020APGA
1071 .iu_version = 0x40000000,
1072 .fpu_version = 0 << 17,
1073 .mmu_version = 0x03000000,
1074 .mmu_bm = 0x00002000,
1075 .mmu_ctpr_mask = 0xffffffc0,
1076 .mmu_cxr_mask = 0x0000ffff,
1077 .mmu_sfsr_mask = 0xffffffff,
1078 .mmu_trcr_mask = 0xffffffff,
1079 .nwindows = 8,
1080 .features = CPU_DEFAULT_FEATURES,
1083 .name = "TI SuperSparc 61",
1084 .iu_version = 0x44000000,
1085 .fpu_version = 0 << 17,
1086 .mmu_version = 0x04000000,
1087 .mmu_bm = 0x00002000,
1088 .mmu_ctpr_mask = 0xffffffc0,
1089 .mmu_cxr_mask = 0x0000ffff,
1090 .mmu_sfsr_mask = 0xffffffff,
1091 .mmu_trcr_mask = 0xffffffff,
1092 .nwindows = 8,
1093 .features = CPU_DEFAULT_FEATURES,
1096 .name = "Ross RT625",
1097 .iu_version = 0x1e000000,
1098 .fpu_version = 1 << 17,
1099 .mmu_version = 0x1e000000,
1100 .mmu_bm = 0x00004000,
1101 .mmu_ctpr_mask = 0x007ffff0,
1102 .mmu_cxr_mask = 0x0000003f,
1103 .mmu_sfsr_mask = 0xffffffff,
1104 .mmu_trcr_mask = 0xffffffff,
1105 .nwindows = 8,
1106 .features = CPU_DEFAULT_FEATURES,
1109 .name = "Ross RT620",
1110 .iu_version = 0x1f000000,
1111 .fpu_version = 1 << 17,
1112 .mmu_version = 0x1f000000,
1113 .mmu_bm = 0x00004000,
1114 .mmu_ctpr_mask = 0x007ffff0,
1115 .mmu_cxr_mask = 0x0000003f,
1116 .mmu_sfsr_mask = 0xffffffff,
1117 .mmu_trcr_mask = 0xffffffff,
1118 .nwindows = 8,
1119 .features = CPU_DEFAULT_FEATURES,
1122 .name = "BIT B5010",
1123 .iu_version = 0x20000000,
1124 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1125 .mmu_version = 0x20000000,
1126 .mmu_bm = 0x00004000,
1127 .mmu_ctpr_mask = 0x007ffff0,
1128 .mmu_cxr_mask = 0x0000003f,
1129 .mmu_sfsr_mask = 0xffffffff,
1130 .mmu_trcr_mask = 0xffffffff,
1131 .nwindows = 8,
1132 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1133 CPU_FEATURE_FSMULD,
1136 .name = "Matsushita MN10501",
1137 .iu_version = 0x50000000,
1138 .fpu_version = 0 << 17,
1139 .mmu_version = 0x50000000,
1140 .mmu_bm = 0x00004000,
1141 .mmu_ctpr_mask = 0x007ffff0,
1142 .mmu_cxr_mask = 0x0000003f,
1143 .mmu_sfsr_mask = 0xffffffff,
1144 .mmu_trcr_mask = 0xffffffff,
1145 .nwindows = 8,
1146 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1147 CPU_FEATURE_FSMULD,
1150 .name = "Weitek W8601",
1151 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1152 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1153 .mmu_version = 0x10 << 24,
1154 .mmu_bm = 0x00004000,
1155 .mmu_ctpr_mask = 0x007ffff0,
1156 .mmu_cxr_mask = 0x0000003f,
1157 .mmu_sfsr_mask = 0xffffffff,
1158 .mmu_trcr_mask = 0xffffffff,
1159 .nwindows = 8,
1160 .features = CPU_DEFAULT_FEATURES,
1163 .name = "LEON2",
1164 .iu_version = 0xf2000000,
1165 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1166 .mmu_version = 0xf2000000,
1167 .mmu_bm = 0x00004000,
1168 .mmu_ctpr_mask = 0x007ffff0,
1169 .mmu_cxr_mask = 0x0000003f,
1170 .mmu_sfsr_mask = 0xffffffff,
1171 .mmu_trcr_mask = 0xffffffff,
1172 .nwindows = 8,
1173 .features = CPU_DEFAULT_FEATURES,
1176 .name = "LEON3",
1177 .iu_version = 0xf3000000,
1178 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1179 .mmu_version = 0xf3000000,
1180 .mmu_bm = 0x00004000,
1181 .mmu_ctpr_mask = 0x007ffff0,
1182 .mmu_cxr_mask = 0x0000003f,
1183 .mmu_sfsr_mask = 0xffffffff,
1184 .mmu_trcr_mask = 0xffffffff,
1185 .nwindows = 8,
1186 .features = CPU_DEFAULT_FEATURES,
1188 #endif
1191 static const char * const feature_name[] = {
1192 "float",
1193 "float128",
1194 "swap",
1195 "mul",
1196 "div",
1197 "flush",
1198 "fsqrt",
1199 "fmul",
1200 "vis1",
1201 "vis2",
1202 "fsmuld",
1203 "hypv",
1204 "cmt",
1205 "gl",
1208 static void print_features(FILE *f,
1209 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1210 uint32_t features, const char *prefix)
1212 unsigned int i;
1214 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1215 if (feature_name[i] && (features & (1 << i))) {
1216 if (prefix)
1217 (*cpu_fprintf)(f, "%s", prefix);
1218 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1222 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1224 unsigned int i;
1226 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1227 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1228 *features |= 1 << i;
1229 return;
1231 fprintf(stderr, "CPU feature %s not found\n", flagname);
1234 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1236 unsigned int i;
1237 const sparc_def_t *def = NULL;
1238 char *s = strdup(cpu_model);
1239 char *featurestr, *name = strtok(s, ",");
1240 uint32_t plus_features = 0;
1241 uint32_t minus_features = 0;
1242 long long iu_version;
1243 uint32_t fpu_version, mmu_version, nwindows;
1245 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1246 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1247 def = &sparc_defs[i];
1250 if (!def)
1251 goto error;
1252 memcpy(cpu_def, def, sizeof(*def));
1254 featurestr = strtok(NULL, ",");
1255 while (featurestr) {
1256 char *val;
1258 if (featurestr[0] == '+') {
1259 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1260 } else if (featurestr[0] == '-') {
1261 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1262 } else if ((val = strchr(featurestr, '='))) {
1263 *val = 0; val++;
1264 if (!strcmp(featurestr, "iu_version")) {
1265 char *err;
1267 iu_version = strtoll(val, &err, 0);
1268 if (!*val || *err) {
1269 fprintf(stderr, "bad numerical value %s\n", val);
1270 goto error;
1272 cpu_def->iu_version = iu_version;
1273 #ifdef DEBUG_FEATURES
1274 fprintf(stderr, "iu_version %llx\n", iu_version);
1275 #endif
1276 } else if (!strcmp(featurestr, "fpu_version")) {
1277 char *err;
1279 fpu_version = strtol(val, &err, 0);
1280 if (!*val || *err) {
1281 fprintf(stderr, "bad numerical value %s\n", val);
1282 goto error;
1284 cpu_def->fpu_version = fpu_version;
1285 #ifdef DEBUG_FEATURES
1286 fprintf(stderr, "fpu_version %llx\n", fpu_version);
1287 #endif
1288 } else if (!strcmp(featurestr, "mmu_version")) {
1289 char *err;
1291 mmu_version = strtol(val, &err, 0);
1292 if (!*val || *err) {
1293 fprintf(stderr, "bad numerical value %s\n", val);
1294 goto error;
1296 cpu_def->mmu_version = mmu_version;
1297 #ifdef DEBUG_FEATURES
1298 fprintf(stderr, "mmu_version %llx\n", mmu_version);
1299 #endif
1300 } else if (!strcmp(featurestr, "nwindows")) {
1301 char *err;
1303 nwindows = strtol(val, &err, 0);
1304 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1305 nwindows < MIN_NWINDOWS) {
1306 fprintf(stderr, "bad numerical value %s\n", val);
1307 goto error;
1309 cpu_def->nwindows = nwindows;
1310 #ifdef DEBUG_FEATURES
1311 fprintf(stderr, "nwindows %d\n", nwindows);
1312 #endif
1313 } else {
1314 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1315 goto error;
1317 } else {
1318 fprintf(stderr, "feature string `%s' not in format "
1319 "(+feature|-feature|feature=xyz)\n", featurestr);
1320 goto error;
1322 featurestr = strtok(NULL, ",");
1324 cpu_def->features |= plus_features;
1325 cpu_def->features &= ~minus_features;
1326 #ifdef DEBUG_FEATURES
1327 print_features(stderr, fprintf, cpu_def->features, NULL);
1328 #endif
1329 free(s);
1330 return 0;
1332 error:
1333 free(s);
1334 return -1;
1337 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1339 unsigned int i;
1341 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1342 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1343 sparc_defs[i].name,
1344 sparc_defs[i].iu_version,
1345 sparc_defs[i].fpu_version,
1346 sparc_defs[i].mmu_version,
1347 sparc_defs[i].nwindows);
1348 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1349 ~sparc_defs[i].features, "-");
1350 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1351 sparc_defs[i].features, "+");
1352 (*cpu_fprintf)(f, "\n");
1354 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1355 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1356 (*cpu_fprintf)(f, "\n");
1357 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1358 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1359 (*cpu_fprintf)(f, "\n");
1360 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1361 "fpu_version mmu_version nwindows\n");
1364 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1366 void cpu_dump_state(CPUState *env, FILE *f,
1367 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1368 int flags)
1370 int i, x;
1372 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1373 env->npc);
1374 cpu_fprintf(f, "General Registers:\n");
1375 for (i = 0; i < 4; i++)
1376 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1377 cpu_fprintf(f, "\n");
1378 for (; i < 8; i++)
1379 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1380 cpu_fprintf(f, "\nCurrent Register Window:\n");
1381 for (x = 0; x < 3; x++) {
1382 for (i = 0; i < 4; i++)
1383 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1384 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1385 env->regwptr[i + x * 8]);
1386 cpu_fprintf(f, "\n");
1387 for (; i < 8; 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");
1393 cpu_fprintf(f, "\nFloating Point Registers:\n");
1394 for (i = 0; i < 32; i++) {
1395 if ((i & 3) == 0)
1396 cpu_fprintf(f, "%%f%02d:", i);
1397 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1398 if ((i & 3) == 3)
1399 cpu_fprintf(f, "\n");
1401 #ifdef TARGET_SPARC64
1402 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1403 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1404 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1405 "cleanwin %d cwp %d\n",
1406 env->cansave, env->canrestore, env->otherwin, env->wstate,
1407 env->cleanwin, env->nwindows - 1 - env->cwp);
1408 #else
1409 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1410 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1411 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1412 env->psrs?'S':'-', env->psrps?'P':'-',
1413 env->psret?'E':'-', env->wim);
1414 #endif
1415 cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
1418 #ifdef TARGET_SPARC64
1419 #if !defined(CONFIG_USER_ONLY)
1420 #include "qemu-common.h"
1421 #include "hw/irq.h"
1422 #include "qemu-timer.h"
1423 #endif
1425 void helper_tick_set_count(void *opaque, uint64_t count)
1427 #if !defined(CONFIG_USER_ONLY)
1428 ptimer_set_count(opaque, -count);
1429 #endif
1432 uint64_t helper_tick_get_count(void *opaque)
1434 #if !defined(CONFIG_USER_ONLY)
1435 return -ptimer_get_count(opaque);
1436 #else
1437 return 0;
1438 #endif
1441 void helper_tick_set_limit(void *opaque, uint64_t limit)
1443 #if !defined(CONFIG_USER_ONLY)
1444 ptimer_set_limit(opaque, -limit, 0);
1445 #endif
1447 #endif