kvm: external module: workqueue compatibility
[qemu-kvm/fedora.git] / target-sparc / helper.c
blob44406e17e65e69e70f3cc62867aec85839b78394
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"
31 #include "helper.h"
33 //#define DEBUG_MMU
34 //#define DEBUG_FEATURES
35 //#define DEBUG_PCALL
37 typedef struct sparc_def_t sparc_def_t;
39 struct sparc_def_t {
40 const char *name;
41 target_ulong iu_version;
42 uint32_t fpu_version;
43 uint32_t mmu_version;
44 uint32_t mmu_bm;
45 uint32_t mmu_ctpr_mask;
46 uint32_t mmu_cxr_mask;
47 uint32_t mmu_sfsr_mask;
48 uint32_t mmu_trcr_mask;
49 uint32_t features;
50 uint32_t nwindows;
53 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
55 /* Sparc MMU emulation */
57 /* thread support */
59 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
61 void cpu_lock(void)
63 spin_lock(&global_cpu_lock);
66 void cpu_unlock(void)
68 spin_unlock(&global_cpu_lock);
71 #if defined(CONFIG_USER_ONLY)
73 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
74 int mmu_idx, int is_softmmu)
76 if (rw & 2)
77 env1->exception_index = TT_TFAULT;
78 else
79 env1->exception_index = TT_DFAULT;
80 return 1;
83 #else
85 #ifndef TARGET_SPARC64
87 * Sparc V8 Reference MMU (SRMMU)
89 static const int access_table[8][8] = {
90 { 0, 0, 0, 0, 8, 0, 12, 12 },
91 { 0, 0, 0, 0, 8, 0, 0, 0 },
92 { 8, 8, 0, 0, 0, 8, 12, 12 },
93 { 8, 8, 0, 0, 0, 8, 0, 0 },
94 { 8, 0, 8, 0, 8, 8, 12, 12 },
95 { 8, 0, 8, 0, 8, 0, 8, 0 },
96 { 8, 8, 8, 0, 8, 8, 12, 12 },
97 { 8, 8, 8, 0, 8, 8, 8, 0 }
100 static const int perm_table[2][8] = {
102 PAGE_READ,
103 PAGE_READ | PAGE_WRITE,
104 PAGE_READ | PAGE_EXEC,
105 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
106 PAGE_EXEC,
107 PAGE_READ | PAGE_WRITE,
108 PAGE_READ | PAGE_EXEC,
109 PAGE_READ | PAGE_WRITE | PAGE_EXEC
112 PAGE_READ,
113 PAGE_READ | PAGE_WRITE,
114 PAGE_READ | PAGE_EXEC,
115 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
116 PAGE_EXEC,
117 PAGE_READ,
123 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
124 int *prot, int *access_index,
125 target_ulong address, int rw, int mmu_idx)
127 int access_perms = 0;
128 target_phys_addr_t pde_ptr;
129 uint32_t pde;
130 target_ulong virt_addr;
131 int error_code = 0, is_dirty, is_user;
132 unsigned long page_offset;
134 is_user = mmu_idx == MMU_USER_IDX;
135 virt_addr = address & TARGET_PAGE_MASK;
137 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
138 // Boot mode: instruction fetches are taken from PROM
139 if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
140 *physical = env->prom_addr | (address & 0x7ffffULL);
141 *prot = PAGE_READ | PAGE_EXEC;
142 return 0;
144 *physical = address;
145 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
146 return 0;
149 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
150 *physical = 0xffffffffffff0000ULL;
152 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
153 /* Context base + context number */
154 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
155 pde = ldl_phys(pde_ptr);
157 /* Ctx pde */
158 switch (pde & PTE_ENTRYTYPE_MASK) {
159 default:
160 case 0: /* Invalid */
161 return 1 << 2;
162 case 2: /* L0 PTE, maybe should not happen? */
163 case 3: /* Reserved */
164 return 4 << 2;
165 case 1: /* L0 PDE */
166 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
167 pde = ldl_phys(pde_ptr);
169 switch (pde & PTE_ENTRYTYPE_MASK) {
170 default:
171 case 0: /* Invalid */
172 return (1 << 8) | (1 << 2);
173 case 3: /* Reserved */
174 return (1 << 8) | (4 << 2);
175 case 1: /* L1 PDE */
176 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
177 pde = ldl_phys(pde_ptr);
179 switch (pde & PTE_ENTRYTYPE_MASK) {
180 default:
181 case 0: /* Invalid */
182 return (2 << 8) | (1 << 2);
183 case 3: /* Reserved */
184 return (2 << 8) | (4 << 2);
185 case 1: /* L2 PDE */
186 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
187 pde = ldl_phys(pde_ptr);
189 switch (pde & PTE_ENTRYTYPE_MASK) {
190 default:
191 case 0: /* Invalid */
192 return (3 << 8) | (1 << 2);
193 case 1: /* PDE, should not happen */
194 case 3: /* Reserved */
195 return (3 << 8) | (4 << 2);
196 case 2: /* L3 PTE */
197 virt_addr = address & TARGET_PAGE_MASK;
198 page_offset = (address & TARGET_PAGE_MASK) &
199 (TARGET_PAGE_SIZE - 1);
201 break;
202 case 2: /* L2 PTE */
203 virt_addr = address & ~0x3ffff;
204 page_offset = address & 0x3ffff;
206 break;
207 case 2: /* L1 PTE */
208 virt_addr = address & ~0xffffff;
209 page_offset = address & 0xffffff;
213 /* update page modified and dirty bits */
214 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
215 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
216 pde |= PG_ACCESSED_MASK;
217 if (is_dirty)
218 pde |= PG_MODIFIED_MASK;
219 stl_phys_notdirty(pde_ptr, pde);
221 /* check access */
222 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
223 error_code = access_table[*access_index][access_perms];
224 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
225 return error_code;
227 /* the page can be put in the TLB */
228 *prot = perm_table[is_user][access_perms];
229 if (!(pde & PG_MODIFIED_MASK)) {
230 /* only set write access if already dirty... otherwise wait
231 for dirty access */
232 *prot &= ~PAGE_WRITE;
235 /* Even if large ptes, we map only one 4KB page in the cache to
236 avoid filling it too fast */
237 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
238 return error_code;
241 /* Perform address translation */
242 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
243 int mmu_idx, int is_softmmu)
245 target_phys_addr_t paddr;
246 target_ulong vaddr;
247 int error_code = 0, prot, ret = 0, access_index;
249 error_code = get_physical_address(env, &paddr, &prot, &access_index,
250 address, rw, mmu_idx);
251 if (error_code == 0) {
252 vaddr = address & TARGET_PAGE_MASK;
253 paddr &= TARGET_PAGE_MASK;
254 #ifdef DEBUG_MMU
255 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
256 TARGET_FMT_lx "\n", address, paddr, vaddr);
257 #endif
258 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
259 return ret;
262 if (env->mmuregs[3]) /* Fault status register */
263 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
264 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
265 env->mmuregs[4] = address; /* Fault address register */
267 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
268 // No fault mode: if a mapping is available, just override
269 // permissions. If no mapping is available, redirect accesses to
270 // neverland. Fake/overridden mappings will be flushed when
271 // switching to normal mode.
272 vaddr = address & TARGET_PAGE_MASK;
273 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
274 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
275 return ret;
276 } else {
277 if (rw & 2)
278 env->exception_index = TT_TFAULT;
279 else
280 env->exception_index = TT_DFAULT;
281 return 1;
285 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
287 target_phys_addr_t pde_ptr;
288 uint32_t pde;
290 /* Context base + context number */
291 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
292 (env->mmuregs[2] << 2);
293 pde = ldl_phys(pde_ptr);
295 switch (pde & PTE_ENTRYTYPE_MASK) {
296 default:
297 case 0: /* Invalid */
298 case 2: /* PTE, maybe should not happen? */
299 case 3: /* Reserved */
300 return 0;
301 case 1: /* L1 PDE */
302 if (mmulev == 3)
303 return pde;
304 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
305 pde = ldl_phys(pde_ptr);
307 switch (pde & PTE_ENTRYTYPE_MASK) {
308 default:
309 case 0: /* Invalid */
310 case 3: /* Reserved */
311 return 0;
312 case 2: /* L1 PTE */
313 return pde;
314 case 1: /* L2 PDE */
315 if (mmulev == 2)
316 return pde;
317 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
318 pde = ldl_phys(pde_ptr);
320 switch (pde & PTE_ENTRYTYPE_MASK) {
321 default:
322 case 0: /* Invalid */
323 case 3: /* Reserved */
324 return 0;
325 case 2: /* L2 PTE */
326 return pde;
327 case 1: /* L3 PDE */
328 if (mmulev == 1)
329 return pde;
330 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
331 pde = ldl_phys(pde_ptr);
333 switch (pde & PTE_ENTRYTYPE_MASK) {
334 default:
335 case 0: /* Invalid */
336 case 1: /* PDE, should not happen */
337 case 3: /* Reserved */
338 return 0;
339 case 2: /* L3 PTE */
340 return pde;
345 return 0;
348 #ifdef DEBUG_MMU
349 void dump_mmu(CPUState *env)
351 target_ulong va, va1, va2;
352 unsigned int n, m, o;
353 target_phys_addr_t pde_ptr, pa;
354 uint32_t pde;
356 printf("MMU dump:\n");
357 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
358 pde = ldl_phys(pde_ptr);
359 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
360 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
361 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
362 pde = mmu_probe(env, va, 2);
363 if (pde) {
364 pa = cpu_get_phys_page_debug(env, va);
365 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
366 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
367 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
368 pde = mmu_probe(env, va1, 1);
369 if (pde) {
370 pa = cpu_get_phys_page_debug(env, va1);
371 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
372 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
373 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
374 pde = mmu_probe(env, va2, 0);
375 if (pde) {
376 pa = cpu_get_phys_page_debug(env, va2);
377 printf(" VA: " TARGET_FMT_lx ", PA: "
378 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
379 va2, pa, pde);
386 printf("MMU dump ends\n");
388 #endif /* DEBUG_MMU */
390 #else /* !TARGET_SPARC64 */
392 * UltraSparc IIi I/DMMUs
394 static int get_physical_address_data(CPUState *env,
395 target_phys_addr_t *physical, int *prot,
396 target_ulong address, int rw, int is_user)
398 target_ulong mask;
399 unsigned int i;
401 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
402 *physical = address;
403 *prot = PAGE_READ | PAGE_WRITE;
404 return 0;
407 for (i = 0; i < 64; i++) {
408 switch ((env->dtlb_tte[i] >> 61) & 3) {
409 default:
410 case 0x0: // 8k
411 mask = 0xffffffffffffe000ULL;
412 break;
413 case 0x1: // 64k
414 mask = 0xffffffffffff0000ULL;
415 break;
416 case 0x2: // 512k
417 mask = 0xfffffffffff80000ULL;
418 break;
419 case 0x3: // 4M
420 mask = 0xffffffffffc00000ULL;
421 break;
423 // ctx match, vaddr match?
424 if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
425 (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
426 // valid, access ok?
427 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
428 ((env->dtlb_tte[i] & 0x4) && is_user) ||
429 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
430 if (env->dmmuregs[3]) /* Fault status register */
431 env->dmmuregs[3] = 2; /* overflow (not read before
432 another fault) */
433 env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
434 env->dmmuregs[4] = address; /* Fault address register */
435 env->exception_index = TT_DFAULT;
436 #ifdef DEBUG_MMU
437 printf("DFAULT at 0x%" PRIx64 "\n", address);
438 #endif
439 return 1;
441 *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
442 (address & ~mask & 0x1fffffff000ULL);
443 *prot = PAGE_READ;
444 if (env->dtlb_tte[i] & 0x2)
445 *prot |= PAGE_WRITE;
446 return 0;
449 #ifdef DEBUG_MMU
450 printf("DMISS at 0x%" PRIx64 "\n", address);
451 #endif
452 env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
453 env->exception_index = TT_DMISS;
454 return 1;
457 static int get_physical_address_code(CPUState *env,
458 target_phys_addr_t *physical, int *prot,
459 target_ulong address, int is_user)
461 target_ulong mask;
462 unsigned int i;
464 if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
465 *physical = address;
466 *prot = PAGE_EXEC;
467 return 0;
470 for (i = 0; i < 64; i++) {
471 switch ((env->itlb_tte[i] >> 61) & 3) {
472 default:
473 case 0x0: // 8k
474 mask = 0xffffffffffffe000ULL;
475 break;
476 case 0x1: // 64k
477 mask = 0xffffffffffff0000ULL;
478 break;
479 case 0x2: // 512k
480 mask = 0xfffffffffff80000ULL;
481 break;
482 case 0x3: // 4M
483 mask = 0xffffffffffc00000ULL;
484 break;
486 // ctx match, vaddr match?
487 if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
488 (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
489 // valid, access ok?
490 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
491 ((env->itlb_tte[i] & 0x4) && is_user)) {
492 if (env->immuregs[3]) /* Fault status register */
493 env->immuregs[3] = 2; /* overflow (not read before
494 another fault) */
495 env->immuregs[3] |= (is_user << 3) | 1;
496 env->exception_index = TT_TFAULT;
497 #ifdef DEBUG_MMU
498 printf("TFAULT at 0x%" PRIx64 "\n", address);
499 #endif
500 return 1;
502 *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
503 (address & ~mask & 0x1fffffff000ULL);
504 *prot = PAGE_EXEC;
505 return 0;
508 #ifdef DEBUG_MMU
509 printf("TMISS at 0x%" PRIx64 "\n", address);
510 #endif
511 env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
512 env->exception_index = TT_TMISS;
513 return 1;
516 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
517 int *prot, int *access_index,
518 target_ulong address, int rw, int mmu_idx)
520 int is_user = mmu_idx == MMU_USER_IDX;
522 if (rw == 2)
523 return get_physical_address_code(env, physical, prot, address,
524 is_user);
525 else
526 return get_physical_address_data(env, physical, prot, address, rw,
527 is_user);
530 /* Perform address translation */
531 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
532 int mmu_idx, int is_softmmu)
534 target_ulong virt_addr, vaddr;
535 target_phys_addr_t paddr;
536 int error_code = 0, prot, ret = 0, access_index;
538 error_code = get_physical_address(env, &paddr, &prot, &access_index,
539 address, rw, mmu_idx);
540 if (error_code == 0) {
541 virt_addr = address & TARGET_PAGE_MASK;
542 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
543 (TARGET_PAGE_SIZE - 1));
544 #ifdef DEBUG_MMU
545 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
546 "\n", address, paddr, vaddr);
547 #endif
548 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
549 return ret;
551 // XXX
552 return 1;
555 #ifdef DEBUG_MMU
556 void dump_mmu(CPUState *env)
558 unsigned int i;
559 const char *mask;
561 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
562 env->dmmuregs[1], env->dmmuregs[2]);
563 if ((env->lsu & DMMU_E) == 0) {
564 printf("DMMU disabled\n");
565 } else {
566 printf("DMMU dump:\n");
567 for (i = 0; i < 64; i++) {
568 switch ((env->dtlb_tte[i] >> 61) & 3) {
569 default:
570 case 0x0:
571 mask = " 8k";
572 break;
573 case 0x1:
574 mask = " 64k";
575 break;
576 case 0x2:
577 mask = "512k";
578 break;
579 case 0x3:
580 mask = " 4M";
581 break;
583 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
584 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
585 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
586 env->dtlb_tag[i] & ~0x1fffULL,
587 env->dtlb_tte[i] & 0x1ffffffe000ULL,
588 mask,
589 env->dtlb_tte[i] & 0x4? "priv": "user",
590 env->dtlb_tte[i] & 0x2? "RW": "RO",
591 env->dtlb_tte[i] & 0x40? "locked": "unlocked",
592 env->dtlb_tag[i] & 0x1fffULL);
596 if ((env->lsu & IMMU_E) == 0) {
597 printf("IMMU disabled\n");
598 } else {
599 printf("IMMU dump:\n");
600 for (i = 0; i < 64; i++) {
601 switch ((env->itlb_tte[i] >> 61) & 3) {
602 default:
603 case 0x0:
604 mask = " 8k";
605 break;
606 case 0x1:
607 mask = " 64k";
608 break;
609 case 0x2:
610 mask = "512k";
611 break;
612 case 0x3:
613 mask = " 4M";
614 break;
616 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
617 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
618 ", %s, %s, %s, ctx %" PRId64 "\n",
619 env->itlb_tag[i] & ~0x1fffULL,
620 env->itlb_tte[i] & 0x1ffffffe000ULL,
621 mask,
622 env->itlb_tte[i] & 0x4? "priv": "user",
623 env->itlb_tte[i] & 0x40? "locked": "unlocked",
624 env->itlb_tag[i] & 0x1fffULL);
629 #endif /* DEBUG_MMU */
631 #endif /* TARGET_SPARC64 */
632 #endif /* !CONFIG_USER_ONLY */
635 #if defined(CONFIG_USER_ONLY)
636 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
638 return addr;
641 #else
642 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
644 target_phys_addr_t phys_addr;
645 int prot, access_index;
647 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
648 MMU_KERNEL_IDX) != 0)
649 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
650 0, MMU_KERNEL_IDX) != 0)
651 return -1;
652 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
653 return -1;
654 return phys_addr;
656 #endif
658 #ifdef TARGET_SPARC64
659 #ifdef DEBUG_PCALL
660 static const char * const excp_names[0x80] = {
661 [TT_TFAULT] = "Instruction Access Fault",
662 [TT_TMISS] = "Instruction Access MMU Miss",
663 [TT_CODE_ACCESS] = "Instruction Access Error",
664 [TT_ILL_INSN] = "Illegal Instruction",
665 [TT_PRIV_INSN] = "Privileged Instruction",
666 [TT_NFPU_INSN] = "FPU Disabled",
667 [TT_FP_EXCP] = "FPU Exception",
668 [TT_TOVF] = "Tag Overflow",
669 [TT_CLRWIN] = "Clean Windows",
670 [TT_DIV_ZERO] = "Division By Zero",
671 [TT_DFAULT] = "Data Access Fault",
672 [TT_DMISS] = "Data Access MMU Miss",
673 [TT_DATA_ACCESS] = "Data Access Error",
674 [TT_DPROT] = "Data Protection Error",
675 [TT_UNALIGNED] = "Unaligned Memory Access",
676 [TT_PRIV_ACT] = "Privileged Action",
677 [TT_EXTINT | 0x1] = "External Interrupt 1",
678 [TT_EXTINT | 0x2] = "External Interrupt 2",
679 [TT_EXTINT | 0x3] = "External Interrupt 3",
680 [TT_EXTINT | 0x4] = "External Interrupt 4",
681 [TT_EXTINT | 0x5] = "External Interrupt 5",
682 [TT_EXTINT | 0x6] = "External Interrupt 6",
683 [TT_EXTINT | 0x7] = "External Interrupt 7",
684 [TT_EXTINT | 0x8] = "External Interrupt 8",
685 [TT_EXTINT | 0x9] = "External Interrupt 9",
686 [TT_EXTINT | 0xa] = "External Interrupt 10",
687 [TT_EXTINT | 0xb] = "External Interrupt 11",
688 [TT_EXTINT | 0xc] = "External Interrupt 12",
689 [TT_EXTINT | 0xd] = "External Interrupt 13",
690 [TT_EXTINT | 0xe] = "External Interrupt 14",
691 [TT_EXTINT | 0xf] = "External Interrupt 15",
693 #endif
695 void do_interrupt(CPUState *env)
697 int intno = env->exception_index;
699 #ifdef DEBUG_PCALL
700 if (loglevel & CPU_LOG_INT) {
701 static int count;
702 const char *name;
704 if (intno < 0 || intno >= 0x180)
705 name = "Unknown";
706 else if (intno >= 0x100)
707 name = "Trap Instruction";
708 else if (intno >= 0xc0)
709 name = "Window Fill";
710 else if (intno >= 0x80)
711 name = "Window Spill";
712 else {
713 name = excp_names[intno];
714 if (!name)
715 name = "Unknown";
718 fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
719 " SP=%016" PRIx64 "\n",
720 count, name, intno,
721 env->pc,
722 env->npc, env->regwptr[6]);
723 cpu_dump_state(env, logfile, fprintf, 0);
724 #if 0
726 int i;
727 uint8_t *ptr;
729 fprintf(logfile, " code=");
730 ptr = (uint8_t *)env->pc;
731 for(i = 0; i < 16; i++) {
732 fprintf(logfile, " %02x", ldub(ptr + i));
734 fprintf(logfile, "\n");
736 #endif
737 count++;
739 #endif
740 #if !defined(CONFIG_USER_ONLY)
741 if (env->tl == MAXTL) {
742 cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state",
743 env->exception_index);
744 return;
746 #endif
747 if (env->tl < MAXTL - 1) {
748 env->tl++;
749 } else {
750 env->pstate |= PS_RED;
751 if (env->tl != MAXTL)
752 env->tl++;
754 env->tsptr = &env->ts[env->tl];
755 env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
756 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
757 GET_CWP64(env);
758 env->tsptr->tpc = env->pc;
759 env->tsptr->tnpc = env->npc;
760 env->tsptr->tt = intno;
761 if (!(env->features & CPU_FEATURE_GL))
762 change_pstate(PS_PEF | PS_PRIV | PS_AG);
764 if (intno == TT_CLRWIN)
765 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
766 else if ((intno & 0x1c0) == TT_SPILL)
767 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
768 else if ((intno & 0x1c0) == TT_FILL)
769 cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
770 env->tbr &= ~0x7fffULL;
771 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
772 env->pc = env->tbr;
773 env->npc = env->pc + 4;
774 env->exception_index = 0;
776 #else
777 #ifdef DEBUG_PCALL
778 static const char * const excp_names[0x80] = {
779 [TT_TFAULT] = "Instruction Access Fault",
780 [TT_ILL_INSN] = "Illegal Instruction",
781 [TT_PRIV_INSN] = "Privileged Instruction",
782 [TT_NFPU_INSN] = "FPU Disabled",
783 [TT_WIN_OVF] = "Window Overflow",
784 [TT_WIN_UNF] = "Window Underflow",
785 [TT_UNALIGNED] = "Unaligned Memory Access",
786 [TT_FP_EXCP] = "FPU Exception",
787 [TT_DFAULT] = "Data Access Fault",
788 [TT_TOVF] = "Tag Overflow",
789 [TT_EXTINT | 0x1] = "External Interrupt 1",
790 [TT_EXTINT | 0x2] = "External Interrupt 2",
791 [TT_EXTINT | 0x3] = "External Interrupt 3",
792 [TT_EXTINT | 0x4] = "External Interrupt 4",
793 [TT_EXTINT | 0x5] = "External Interrupt 5",
794 [TT_EXTINT | 0x6] = "External Interrupt 6",
795 [TT_EXTINT | 0x7] = "External Interrupt 7",
796 [TT_EXTINT | 0x8] = "External Interrupt 8",
797 [TT_EXTINT | 0x9] = "External Interrupt 9",
798 [TT_EXTINT | 0xa] = "External Interrupt 10",
799 [TT_EXTINT | 0xb] = "External Interrupt 11",
800 [TT_EXTINT | 0xc] = "External Interrupt 12",
801 [TT_EXTINT | 0xd] = "External Interrupt 13",
802 [TT_EXTINT | 0xe] = "External Interrupt 14",
803 [TT_EXTINT | 0xf] = "External Interrupt 15",
804 [TT_TOVF] = "Tag Overflow",
805 [TT_CODE_ACCESS] = "Instruction Access Error",
806 [TT_DATA_ACCESS] = "Data Access Error",
807 [TT_DIV_ZERO] = "Division By Zero",
808 [TT_NCP_INSN] = "Coprocessor Disabled",
810 #endif
812 void do_interrupt(CPUState *env)
814 int cwp, intno = env->exception_index;
816 #ifdef DEBUG_PCALL
817 if (loglevel & CPU_LOG_INT) {
818 static int count;
819 const char *name;
821 if (intno < 0 || intno >= 0x100)
822 name = "Unknown";
823 else if (intno >= 0x80)
824 name = "Trap Instruction";
825 else {
826 name = excp_names[intno];
827 if (!name)
828 name = "Unknown";
831 fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
832 count, name, intno,
833 env->pc,
834 env->npc, env->regwptr[6]);
835 cpu_dump_state(env, logfile, fprintf, 0);
836 #if 0
838 int i;
839 uint8_t *ptr;
841 fprintf(logfile, " code=");
842 ptr = (uint8_t *)env->pc;
843 for(i = 0; i < 16; i++) {
844 fprintf(logfile, " %02x", ldub(ptr + i));
846 fprintf(logfile, "\n");
848 #endif
849 count++;
851 #endif
852 #if !defined(CONFIG_USER_ONLY)
853 if (env->psret == 0) {
854 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
855 env->exception_index);
856 return;
858 #endif
859 env->psret = 0;
860 cwp = cpu_cwp_dec(env, env->cwp - 1);
861 cpu_set_cwp(env, cwp);
862 env->regwptr[9] = env->pc;
863 env->regwptr[10] = env->npc;
864 env->psrps = env->psrs;
865 env->psrs = 1;
866 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
867 env->pc = env->tbr;
868 env->npc = env->pc + 4;
869 env->exception_index = 0;
871 #endif
873 void memcpy32(target_ulong *dst, const target_ulong *src)
875 dst[0] = src[0];
876 dst[1] = src[1];
877 dst[2] = src[2];
878 dst[3] = src[3];
879 dst[4] = src[4];
880 dst[5] = src[5];
881 dst[6] = src[6];
882 dst[7] = src[7];
885 void cpu_reset(CPUSPARCState *env)
887 tlb_flush(env, 1);
888 env->cwp = 0;
889 env->wim = 1;
890 env->regwptr = env->regbase + (env->cwp * 16);
891 #if defined(CONFIG_USER_ONLY)
892 env->user_mode_only = 1;
893 #ifdef TARGET_SPARC64
894 env->cleanwin = env->nwindows - 2;
895 env->cansave = env->nwindows - 2;
896 env->pstate = PS_RMO | PS_PEF | PS_IE;
897 env->asi = 0x82; // Primary no-fault
898 #endif
899 #else
900 env->psret = 0;
901 env->psrs = 1;
902 env->psrps = 1;
903 #ifdef TARGET_SPARC64
904 env->pstate = PS_PRIV;
905 env->hpstate = HS_PRIV;
906 env->pc = 0x1fff0000000ULL;
907 env->tsptr = &env->ts[env->tl];
908 #else
909 env->pc = 0;
910 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
911 env->mmuregs[0] |= env->mmu_bm;
912 #endif
913 env->npc = env->pc + 4;
914 #endif
917 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
919 sparc_def_t def1, *def = &def1;
921 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
922 return -1;
924 env->features = def->features;
925 env->cpu_model_str = cpu_model;
926 env->version = def->iu_version;
927 env->fsr = def->fpu_version;
928 env->nwindows = def->nwindows;
929 #if !defined(TARGET_SPARC64)
930 env->mmu_bm = def->mmu_bm;
931 env->mmu_ctpr_mask = def->mmu_ctpr_mask;
932 env->mmu_cxr_mask = def->mmu_cxr_mask;
933 env->mmu_sfsr_mask = def->mmu_sfsr_mask;
934 env->mmu_trcr_mask = def->mmu_trcr_mask;
935 env->mmuregs[0] |= def->mmu_version;
936 cpu_sparc_set_id(env, 0);
937 #else
938 env->mmu_version = def->mmu_version;
939 env->version |= def->nwindows - 1;
940 #endif
941 return 0;
944 static void cpu_sparc_close(CPUSPARCState *env)
946 free(env);
949 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
951 CPUSPARCState *env;
953 env = qemu_mallocz(sizeof(CPUSPARCState));
954 if (!env)
955 return NULL;
956 cpu_exec_init(env);
958 gen_intermediate_code_init(env);
960 if (cpu_sparc_register(env, cpu_model) < 0) {
961 cpu_sparc_close(env);
962 return NULL;
964 cpu_reset(env);
966 return env;
969 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
971 #if !defined(TARGET_SPARC64)
972 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
973 #endif
976 static const sparc_def_t sparc_defs[] = {
977 #ifdef TARGET_SPARC64
979 .name = "Fujitsu Sparc64",
980 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)
981 | (MAXTL << 8)),
982 .fpu_version = 0x00000000,
983 .mmu_version = mmu_us_12,
984 .nwindows = 4,
985 .features = CPU_DEFAULT_FEATURES,
988 .name = "Fujitsu Sparc64 III",
989 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)
990 | (MAXTL << 8)),
991 .fpu_version = 0x00000000,
992 .mmu_version = mmu_us_12,
993 .nwindows = 5,
994 .features = CPU_DEFAULT_FEATURES,
997 .name = "Fujitsu Sparc64 IV",
998 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)
999 | (MAXTL << 8)),
1000 .fpu_version = 0x00000000,
1001 .mmu_version = mmu_us_12,
1002 .nwindows = 8,
1003 .features = CPU_DEFAULT_FEATURES,
1006 .name = "Fujitsu Sparc64 V",
1007 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)
1008 | (MAXTL << 8)),
1009 .fpu_version = 0x00000000,
1010 .mmu_version = mmu_us_12,
1011 .nwindows = 8,
1012 .features = CPU_DEFAULT_FEATURES,
1015 .name = "TI UltraSparc I",
1016 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
1017 | (MAXTL << 8)),
1018 .fpu_version = 0x00000000,
1019 .mmu_version = mmu_us_12,
1020 .nwindows = 8,
1021 .features = CPU_DEFAULT_FEATURES,
1024 .name = "TI UltraSparc II",
1025 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)
1026 | (MAXTL << 8)),
1027 .fpu_version = 0x00000000,
1028 .mmu_version = mmu_us_12,
1029 .nwindows = 8,
1030 .features = CPU_DEFAULT_FEATURES,
1033 .name = "TI UltraSparc IIi",
1034 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)
1035 | (MAXTL << 8)),
1036 .fpu_version = 0x00000000,
1037 .mmu_version = mmu_us_12,
1038 .nwindows = 8,
1039 .features = CPU_DEFAULT_FEATURES,
1042 .name = "TI UltraSparc IIe",
1043 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)
1044 | (MAXTL << 8)),
1045 .fpu_version = 0x00000000,
1046 .mmu_version = mmu_us_12,
1047 .nwindows = 8,
1048 .features = CPU_DEFAULT_FEATURES,
1051 .name = "Sun UltraSparc III",
1052 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)
1053 | (MAXTL << 8)),
1054 .fpu_version = 0x00000000,
1055 .mmu_version = mmu_us_12,
1056 .nwindows = 8,
1057 .features = CPU_DEFAULT_FEATURES,
1060 .name = "Sun UltraSparc III Cu",
1061 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)
1062 | (MAXTL << 8)),
1063 .fpu_version = 0x00000000,
1064 .mmu_version = mmu_us_3,
1065 .nwindows = 8,
1066 .features = CPU_DEFAULT_FEATURES,
1069 .name = "Sun UltraSparc IIIi",
1070 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)
1071 | (MAXTL << 8)),
1072 .fpu_version = 0x00000000,
1073 .mmu_version = mmu_us_12,
1074 .nwindows = 8,
1075 .features = CPU_DEFAULT_FEATURES,
1078 .name = "Sun UltraSparc IV",
1079 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)
1080 | (MAXTL << 8)),
1081 .fpu_version = 0x00000000,
1082 .mmu_version = mmu_us_4,
1083 .nwindows = 8,
1084 .features = CPU_DEFAULT_FEATURES,
1087 .name = "Sun UltraSparc IV+",
1088 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)
1089 | (MAXTL << 8)),
1090 .fpu_version = 0x00000000,
1091 .mmu_version = mmu_us_12,
1092 .nwindows = 8,
1093 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
1096 .name = "Sun UltraSparc IIIi+",
1097 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)
1098 | (MAXTL << 8)),
1099 .fpu_version = 0x00000000,
1100 .mmu_version = mmu_us_3,
1101 .nwindows = 8,
1102 .features = CPU_DEFAULT_FEATURES,
1105 .name = "NEC UltraSparc I",
1106 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
1107 | (MAXTL << 8)),
1108 .fpu_version = 0x00000000,
1109 .mmu_version = mmu_us_12,
1110 .nwindows = 8,
1111 .features = CPU_DEFAULT_FEATURES,
1113 #else
1115 .name = "Fujitsu MB86900",
1116 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1117 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1118 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
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 = 7,
1125 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1128 .name = "Fujitsu MB86904",
1129 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1130 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1131 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1132 .mmu_bm = 0x00004000,
1133 .mmu_ctpr_mask = 0x00ffffc0,
1134 .mmu_cxr_mask = 0x000000ff,
1135 .mmu_sfsr_mask = 0x00016fff,
1136 .mmu_trcr_mask = 0x00ffffff,
1137 .nwindows = 8,
1138 .features = CPU_DEFAULT_FEATURES,
1141 .name = "Fujitsu MB86907",
1142 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1143 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1144 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1145 .mmu_bm = 0x00004000,
1146 .mmu_ctpr_mask = 0xffffffc0,
1147 .mmu_cxr_mask = 0x000000ff,
1148 .mmu_sfsr_mask = 0x00016fff,
1149 .mmu_trcr_mask = 0xffffffff,
1150 .nwindows = 8,
1151 .features = CPU_DEFAULT_FEATURES,
1154 .name = "LSI L64811",
1155 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1156 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1157 .mmu_version = 0x10 << 24,
1158 .mmu_bm = 0x00004000,
1159 .mmu_ctpr_mask = 0x007ffff0,
1160 .mmu_cxr_mask = 0x0000003f,
1161 .mmu_sfsr_mask = 0xffffffff,
1162 .mmu_trcr_mask = 0xffffffff,
1163 .nwindows = 8,
1164 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1165 CPU_FEATURE_FSMULD,
1168 .name = "Cypress CY7C601",
1169 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1170 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1171 .mmu_version = 0x10 << 24,
1172 .mmu_bm = 0x00004000,
1173 .mmu_ctpr_mask = 0x007ffff0,
1174 .mmu_cxr_mask = 0x0000003f,
1175 .mmu_sfsr_mask = 0xffffffff,
1176 .mmu_trcr_mask = 0xffffffff,
1177 .nwindows = 8,
1178 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1179 CPU_FEATURE_FSMULD,
1182 .name = "Cypress CY7C611",
1183 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1184 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1185 .mmu_version = 0x10 << 24,
1186 .mmu_bm = 0x00004000,
1187 .mmu_ctpr_mask = 0x007ffff0,
1188 .mmu_cxr_mask = 0x0000003f,
1189 .mmu_sfsr_mask = 0xffffffff,
1190 .mmu_trcr_mask = 0xffffffff,
1191 .nwindows = 8,
1192 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1193 CPU_FEATURE_FSMULD,
1196 .name = "TI SuperSparc II",
1197 .iu_version = 0x40000000,
1198 .fpu_version = 0 << 17,
1199 .mmu_version = 0x04000000,
1200 .mmu_bm = 0x00002000,
1201 .mmu_ctpr_mask = 0xffffffc0,
1202 .mmu_cxr_mask = 0x0000ffff,
1203 .mmu_sfsr_mask = 0xffffffff,
1204 .mmu_trcr_mask = 0xffffffff,
1205 .nwindows = 8,
1206 .features = CPU_DEFAULT_FEATURES,
1209 .name = "TI MicroSparc I",
1210 .iu_version = 0x41000000,
1211 .fpu_version = 4 << 17,
1212 .mmu_version = 0x41000000,
1213 .mmu_bm = 0x00004000,
1214 .mmu_ctpr_mask = 0x007ffff0,
1215 .mmu_cxr_mask = 0x0000003f,
1216 .mmu_sfsr_mask = 0x00016fff,
1217 .mmu_trcr_mask = 0x0000003f,
1218 .nwindows = 7,
1219 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1220 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1221 CPU_FEATURE_FMUL,
1224 .name = "TI MicroSparc II",
1225 .iu_version = 0x42000000,
1226 .fpu_version = 4 << 17,
1227 .mmu_version = 0x02000000,
1228 .mmu_bm = 0x00004000,
1229 .mmu_ctpr_mask = 0x00ffffc0,
1230 .mmu_cxr_mask = 0x000000ff,
1231 .mmu_sfsr_mask = 0x00016fff,
1232 .mmu_trcr_mask = 0x00ffffff,
1233 .nwindows = 8,
1234 .features = CPU_DEFAULT_FEATURES,
1237 .name = "TI MicroSparc IIep",
1238 .iu_version = 0x42000000,
1239 .fpu_version = 4 << 17,
1240 .mmu_version = 0x04000000,
1241 .mmu_bm = 0x00004000,
1242 .mmu_ctpr_mask = 0x00ffffc0,
1243 .mmu_cxr_mask = 0x000000ff,
1244 .mmu_sfsr_mask = 0x00016bff,
1245 .mmu_trcr_mask = 0x00ffffff,
1246 .nwindows = 8,
1247 .features = CPU_DEFAULT_FEATURES,
1250 .name = "TI SuperSparc 40", // STP1020NPGA
1251 .iu_version = 0x41000000,
1252 .fpu_version = 0 << 17,
1253 .mmu_version = 0x00000000,
1254 .mmu_bm = 0x00002000,
1255 .mmu_ctpr_mask = 0xffffffc0,
1256 .mmu_cxr_mask = 0x0000ffff,
1257 .mmu_sfsr_mask = 0xffffffff,
1258 .mmu_trcr_mask = 0xffffffff,
1259 .nwindows = 8,
1260 .features = CPU_DEFAULT_FEATURES,
1263 .name = "TI SuperSparc 50", // STP1020PGA
1264 .iu_version = 0x40000000,
1265 .fpu_version = 0 << 17,
1266 .mmu_version = 0x04000000,
1267 .mmu_bm = 0x00002000,
1268 .mmu_ctpr_mask = 0xffffffc0,
1269 .mmu_cxr_mask = 0x0000ffff,
1270 .mmu_sfsr_mask = 0xffffffff,
1271 .mmu_trcr_mask = 0xffffffff,
1272 .nwindows = 8,
1273 .features = CPU_DEFAULT_FEATURES,
1276 .name = "TI SuperSparc 51",
1277 .iu_version = 0x43000000,
1278 .fpu_version = 0 << 17,
1279 .mmu_version = 0x04000000,
1280 .mmu_bm = 0x00002000,
1281 .mmu_ctpr_mask = 0xffffffc0,
1282 .mmu_cxr_mask = 0x0000ffff,
1283 .mmu_sfsr_mask = 0xffffffff,
1284 .mmu_trcr_mask = 0xffffffff,
1285 .nwindows = 8,
1286 .features = CPU_DEFAULT_FEATURES,
1289 .name = "TI SuperSparc 60", // STP1020APGA
1290 .iu_version = 0x40000000,
1291 .fpu_version = 0 << 17,
1292 .mmu_version = 0x03000000,
1293 .mmu_bm = 0x00002000,
1294 .mmu_ctpr_mask = 0xffffffc0,
1295 .mmu_cxr_mask = 0x0000ffff,
1296 .mmu_sfsr_mask = 0xffffffff,
1297 .mmu_trcr_mask = 0xffffffff,
1298 .nwindows = 8,
1299 .features = CPU_DEFAULT_FEATURES,
1302 .name = "TI SuperSparc 61",
1303 .iu_version = 0x44000000,
1304 .fpu_version = 0 << 17,
1305 .mmu_version = 0x04000000,
1306 .mmu_bm = 0x00002000,
1307 .mmu_ctpr_mask = 0xffffffc0,
1308 .mmu_cxr_mask = 0x0000ffff,
1309 .mmu_sfsr_mask = 0xffffffff,
1310 .mmu_trcr_mask = 0xffffffff,
1311 .nwindows = 8,
1312 .features = CPU_DEFAULT_FEATURES,
1315 .name = "Ross RT625",
1316 .iu_version = 0x1e000000,
1317 .fpu_version = 1 << 17,
1318 .mmu_version = 0x1e000000,
1319 .mmu_bm = 0x00004000,
1320 .mmu_ctpr_mask = 0x007ffff0,
1321 .mmu_cxr_mask = 0x0000003f,
1322 .mmu_sfsr_mask = 0xffffffff,
1323 .mmu_trcr_mask = 0xffffffff,
1324 .nwindows = 8,
1325 .features = CPU_DEFAULT_FEATURES,
1328 .name = "Ross RT620",
1329 .iu_version = 0x1f000000,
1330 .fpu_version = 1 << 17,
1331 .mmu_version = 0x1f000000,
1332 .mmu_bm = 0x00004000,
1333 .mmu_ctpr_mask = 0x007ffff0,
1334 .mmu_cxr_mask = 0x0000003f,
1335 .mmu_sfsr_mask = 0xffffffff,
1336 .mmu_trcr_mask = 0xffffffff,
1337 .nwindows = 8,
1338 .features = CPU_DEFAULT_FEATURES,
1341 .name = "BIT B5010",
1342 .iu_version = 0x20000000,
1343 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1344 .mmu_version = 0x20000000,
1345 .mmu_bm = 0x00004000,
1346 .mmu_ctpr_mask = 0x007ffff0,
1347 .mmu_cxr_mask = 0x0000003f,
1348 .mmu_sfsr_mask = 0xffffffff,
1349 .mmu_trcr_mask = 0xffffffff,
1350 .nwindows = 8,
1351 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1352 CPU_FEATURE_FSMULD,
1355 .name = "Matsushita MN10501",
1356 .iu_version = 0x50000000,
1357 .fpu_version = 0 << 17,
1358 .mmu_version = 0x50000000,
1359 .mmu_bm = 0x00004000,
1360 .mmu_ctpr_mask = 0x007ffff0,
1361 .mmu_cxr_mask = 0x0000003f,
1362 .mmu_sfsr_mask = 0xffffffff,
1363 .mmu_trcr_mask = 0xffffffff,
1364 .nwindows = 8,
1365 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1366 CPU_FEATURE_FSMULD,
1369 .name = "Weitek W8601",
1370 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1371 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1372 .mmu_version = 0x10 << 24,
1373 .mmu_bm = 0x00004000,
1374 .mmu_ctpr_mask = 0x007ffff0,
1375 .mmu_cxr_mask = 0x0000003f,
1376 .mmu_sfsr_mask = 0xffffffff,
1377 .mmu_trcr_mask = 0xffffffff,
1378 .nwindows = 8,
1379 .features = CPU_DEFAULT_FEATURES,
1382 .name = "LEON2",
1383 .iu_version = 0xf2000000,
1384 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1385 .mmu_version = 0xf2000000,
1386 .mmu_bm = 0x00004000,
1387 .mmu_ctpr_mask = 0x007ffff0,
1388 .mmu_cxr_mask = 0x0000003f,
1389 .mmu_sfsr_mask = 0xffffffff,
1390 .mmu_trcr_mask = 0xffffffff,
1391 .nwindows = 8,
1392 .features = CPU_DEFAULT_FEATURES,
1395 .name = "LEON3",
1396 .iu_version = 0xf3000000,
1397 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1398 .mmu_version = 0xf3000000,
1399 .mmu_bm = 0x00004000,
1400 .mmu_ctpr_mask = 0x007ffff0,
1401 .mmu_cxr_mask = 0x0000003f,
1402 .mmu_sfsr_mask = 0xffffffff,
1403 .mmu_trcr_mask = 0xffffffff,
1404 .nwindows = 8,
1405 .features = CPU_DEFAULT_FEATURES,
1407 #endif
1410 static const char * const feature_name[] = {
1411 "float",
1412 "float128",
1413 "swap",
1414 "mul",
1415 "div",
1416 "flush",
1417 "fsqrt",
1418 "fmul",
1419 "vis1",
1420 "vis2",
1421 "fsmuld",
1422 "hypv",
1423 "cmt",
1424 "gl",
1427 static void print_features(FILE *f,
1428 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1429 uint32_t features, const char *prefix)
1431 unsigned int i;
1433 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1434 if (feature_name[i] && (features & (1 << i))) {
1435 if (prefix)
1436 (*cpu_fprintf)(f, "%s", prefix);
1437 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1441 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1443 unsigned int i;
1445 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1446 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1447 *features |= 1 << i;
1448 return;
1450 fprintf(stderr, "CPU feature %s not found\n", flagname);
1453 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1455 unsigned int i;
1456 const sparc_def_t *def = NULL;
1457 char *s = strdup(cpu_model);
1458 char *featurestr, *name = strtok(s, ",");
1459 uint32_t plus_features = 0;
1460 uint32_t minus_features = 0;
1461 long long iu_version;
1462 uint32_t fpu_version, mmu_version, nwindows;
1464 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1465 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1466 def = &sparc_defs[i];
1469 if (!def)
1470 goto error;
1471 memcpy(cpu_def, def, sizeof(*def));
1473 featurestr = strtok(NULL, ",");
1474 while (featurestr) {
1475 char *val;
1477 if (featurestr[0] == '+') {
1478 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1479 } else if (featurestr[0] == '-') {
1480 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1481 } else if ((val = strchr(featurestr, '='))) {
1482 *val = 0; val++;
1483 if (!strcmp(featurestr, "iu_version")) {
1484 char *err;
1486 iu_version = strtoll(val, &err, 0);
1487 if (!*val || *err) {
1488 fprintf(stderr, "bad numerical value %s\n", val);
1489 goto error;
1491 cpu_def->iu_version = iu_version;
1492 #ifdef DEBUG_FEATURES
1493 fprintf(stderr, "iu_version %llx\n", iu_version);
1494 #endif
1495 } else if (!strcmp(featurestr, "fpu_version")) {
1496 char *err;
1498 fpu_version = strtol(val, &err, 0);
1499 if (!*val || *err) {
1500 fprintf(stderr, "bad numerical value %s\n", val);
1501 goto error;
1503 cpu_def->fpu_version = fpu_version;
1504 #ifdef DEBUG_FEATURES
1505 fprintf(stderr, "fpu_version %llx\n", fpu_version);
1506 #endif
1507 } else if (!strcmp(featurestr, "mmu_version")) {
1508 char *err;
1510 mmu_version = strtol(val, &err, 0);
1511 if (!*val || *err) {
1512 fprintf(stderr, "bad numerical value %s\n", val);
1513 goto error;
1515 cpu_def->mmu_version = mmu_version;
1516 #ifdef DEBUG_FEATURES
1517 fprintf(stderr, "mmu_version %llx\n", mmu_version);
1518 #endif
1519 } else if (!strcmp(featurestr, "nwindows")) {
1520 char *err;
1522 nwindows = strtol(val, &err, 0);
1523 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1524 nwindows < MIN_NWINDOWS) {
1525 fprintf(stderr, "bad numerical value %s\n", val);
1526 goto error;
1528 cpu_def->nwindows = nwindows;
1529 #ifdef DEBUG_FEATURES
1530 fprintf(stderr, "nwindows %d\n", nwindows);
1531 #endif
1532 } else {
1533 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1534 goto error;
1536 } else {
1537 fprintf(stderr, "feature string `%s' not in format "
1538 "(+feature|-feature|feature=xyz)\n", featurestr);
1539 goto error;
1541 featurestr = strtok(NULL, ",");
1543 cpu_def->features |= plus_features;
1544 cpu_def->features &= ~minus_features;
1545 #ifdef DEBUG_FEATURES
1546 print_features(stderr, fprintf, cpu_def->features, NULL);
1547 #endif
1548 free(s);
1549 return 0;
1551 error:
1552 free(s);
1553 return -1;
1556 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1558 unsigned int i;
1560 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1561 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1562 sparc_defs[i].name,
1563 sparc_defs[i].iu_version,
1564 sparc_defs[i].fpu_version,
1565 sparc_defs[i].mmu_version,
1566 sparc_defs[i].nwindows);
1567 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1568 ~sparc_defs[i].features, "-");
1569 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1570 sparc_defs[i].features, "+");
1571 (*cpu_fprintf)(f, "\n");
1573 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1574 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1575 (*cpu_fprintf)(f, "\n");
1576 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1577 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1578 (*cpu_fprintf)(f, "\n");
1579 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1580 "fpu_version mmu_version nwindows\n");
1583 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1585 void cpu_dump_state(CPUState *env, FILE *f,
1586 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1587 int flags)
1589 int i, x;
1591 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1592 env->npc);
1593 cpu_fprintf(f, "General Registers:\n");
1594 for (i = 0; i < 4; i++)
1595 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1596 cpu_fprintf(f, "\n");
1597 for (; i < 8; i++)
1598 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1599 cpu_fprintf(f, "\nCurrent Register Window:\n");
1600 for (x = 0; x < 3; x++) {
1601 for (i = 0; i < 4; i++)
1602 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1603 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1604 env->regwptr[i + x * 8]);
1605 cpu_fprintf(f, "\n");
1606 for (; i < 8; i++)
1607 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1608 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1609 env->regwptr[i + x * 8]);
1610 cpu_fprintf(f, "\n");
1612 cpu_fprintf(f, "\nFloating Point Registers:\n");
1613 for (i = 0; i < 32; i++) {
1614 if ((i & 3) == 0)
1615 cpu_fprintf(f, "%%f%02d:", i);
1616 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1617 if ((i & 3) == 3)
1618 cpu_fprintf(f, "\n");
1620 #ifdef TARGET_SPARC64
1621 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1622 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1623 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1624 "cleanwin %d cwp %d\n",
1625 env->cansave, env->canrestore, env->otherwin, env->wstate,
1626 env->cleanwin, env->nwindows - 1 - env->cwp);
1627 #else
1628 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1629 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1630 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1631 env->psrs?'S':'-', env->psrps?'P':'-',
1632 env->psret?'E':'-', env->wim);
1633 #endif
1634 cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
1637 #ifdef TARGET_SPARC64
1638 #if !defined(CONFIG_USER_ONLY)
1639 #include "qemu-common.h"
1640 #include "hw/irq.h"
1641 #include "qemu-timer.h"
1642 #endif
1644 void helper_tick_set_count(void *opaque, uint64_t count)
1646 #if !defined(CONFIG_USER_ONLY)
1647 ptimer_set_count(opaque, -count);
1648 #endif
1651 uint64_t helper_tick_get_count(void *opaque)
1653 #if !defined(CONFIG_USER_ONLY)
1654 return -ptimer_get_count(opaque);
1655 #else
1656 return 0;
1657 #endif
1660 void helper_tick_set_limit(void *opaque, uint64_t limit)
1662 #if !defined(CONFIG_USER_ONLY)
1663 ptimer_set_limit(opaque, -limit, 0);
1664 #endif
1666 #endif