Remove leftover from previous way to load 64 bit constants
[qemu/mini2440.git] / target-sparc / helper.c
blob811de01a3e7523fabc57127cf4cae169585027d3
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;
51 uint32_t maxtl;
54 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
56 /* Sparc MMU emulation */
58 /* thread support */
60 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
62 void cpu_lock(void)
64 spin_lock(&global_cpu_lock);
67 void cpu_unlock(void)
69 spin_unlock(&global_cpu_lock);
72 #if defined(CONFIG_USER_ONLY)
74 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
75 int mmu_idx, int is_softmmu)
77 if (rw & 2)
78 env1->exception_index = TT_TFAULT;
79 else
80 env1->exception_index = TT_DFAULT;
81 return 1;
84 #else
86 #ifndef TARGET_SPARC64
88 * Sparc V8 Reference MMU (SRMMU)
90 static const int access_table[8][8] = {
91 { 0, 0, 0, 0, 8, 0, 12, 12 },
92 { 0, 0, 0, 0, 8, 0, 0, 0 },
93 { 8, 8, 0, 0, 0, 8, 12, 12 },
94 { 8, 8, 0, 0, 0, 8, 0, 0 },
95 { 8, 0, 8, 0, 8, 8, 12, 12 },
96 { 8, 0, 8, 0, 8, 0, 8, 0 },
97 { 8, 8, 8, 0, 8, 8, 12, 12 },
98 { 8, 8, 8, 0, 8, 8, 8, 0 }
101 static const int perm_table[2][8] = {
103 PAGE_READ,
104 PAGE_READ | PAGE_WRITE,
105 PAGE_READ | PAGE_EXEC,
106 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
107 PAGE_EXEC,
108 PAGE_READ | PAGE_WRITE,
109 PAGE_READ | PAGE_EXEC,
110 PAGE_READ | PAGE_WRITE | PAGE_EXEC
113 PAGE_READ,
114 PAGE_READ | PAGE_WRITE,
115 PAGE_READ | PAGE_EXEC,
116 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
117 PAGE_EXEC,
118 PAGE_READ,
124 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
125 int *prot, int *access_index,
126 target_ulong address, int rw, int mmu_idx)
128 int access_perms = 0;
129 target_phys_addr_t pde_ptr;
130 uint32_t pde;
131 target_ulong virt_addr;
132 int error_code = 0, is_dirty, is_user;
133 unsigned long page_offset;
135 is_user = mmu_idx == MMU_USER_IDX;
136 virt_addr = address & TARGET_PAGE_MASK;
138 if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
139 // Boot mode: instruction fetches are taken from PROM
140 if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
141 *physical = env->prom_addr | (address & 0x7ffffULL);
142 *prot = PAGE_READ | PAGE_EXEC;
143 return 0;
145 *physical = address;
146 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
147 return 0;
150 *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
151 *physical = 0xffffffffffff0000ULL;
153 /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
154 /* Context base + context number */
155 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
156 pde = ldl_phys(pde_ptr);
158 /* Ctx pde */
159 switch (pde & PTE_ENTRYTYPE_MASK) {
160 default:
161 case 0: /* Invalid */
162 return 1 << 2;
163 case 2: /* L0 PTE, maybe should not happen? */
164 case 3: /* Reserved */
165 return 4 << 2;
166 case 1: /* L0 PDE */
167 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
168 pde = ldl_phys(pde_ptr);
170 switch (pde & PTE_ENTRYTYPE_MASK) {
171 default:
172 case 0: /* Invalid */
173 return (1 << 8) | (1 << 2);
174 case 3: /* Reserved */
175 return (1 << 8) | (4 << 2);
176 case 1: /* L1 PDE */
177 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
178 pde = ldl_phys(pde_ptr);
180 switch (pde & PTE_ENTRYTYPE_MASK) {
181 default:
182 case 0: /* Invalid */
183 return (2 << 8) | (1 << 2);
184 case 3: /* Reserved */
185 return (2 << 8) | (4 << 2);
186 case 1: /* L2 PDE */
187 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
188 pde = ldl_phys(pde_ptr);
190 switch (pde & PTE_ENTRYTYPE_MASK) {
191 default:
192 case 0: /* Invalid */
193 return (3 << 8) | (1 << 2);
194 case 1: /* PDE, should not happen */
195 case 3: /* Reserved */
196 return (3 << 8) | (4 << 2);
197 case 2: /* L3 PTE */
198 virt_addr = address & TARGET_PAGE_MASK;
199 page_offset = (address & TARGET_PAGE_MASK) &
200 (TARGET_PAGE_SIZE - 1);
202 break;
203 case 2: /* L2 PTE */
204 virt_addr = address & ~0x3ffff;
205 page_offset = address & 0x3ffff;
207 break;
208 case 2: /* L1 PTE */
209 virt_addr = address & ~0xffffff;
210 page_offset = address & 0xffffff;
214 /* update page modified and dirty bits */
215 is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
216 if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
217 pde |= PG_ACCESSED_MASK;
218 if (is_dirty)
219 pde |= PG_MODIFIED_MASK;
220 stl_phys_notdirty(pde_ptr, pde);
222 /* check access */
223 access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
224 error_code = access_table[*access_index][access_perms];
225 if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
226 return error_code;
228 /* the page can be put in the TLB */
229 *prot = perm_table[is_user][access_perms];
230 if (!(pde & PG_MODIFIED_MASK)) {
231 /* only set write access if already dirty... otherwise wait
232 for dirty access */
233 *prot &= ~PAGE_WRITE;
236 /* Even if large ptes, we map only one 4KB page in the cache to
237 avoid filling it too fast */
238 *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
239 return error_code;
242 /* Perform address translation */
243 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
244 int mmu_idx, int is_softmmu)
246 target_phys_addr_t paddr;
247 target_ulong vaddr;
248 int error_code = 0, prot, ret = 0, access_index;
250 error_code = get_physical_address(env, &paddr, &prot, &access_index,
251 address, rw, mmu_idx);
252 if (error_code == 0) {
253 vaddr = address & TARGET_PAGE_MASK;
254 paddr &= TARGET_PAGE_MASK;
255 #ifdef DEBUG_MMU
256 printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
257 TARGET_FMT_lx "\n", address, paddr, vaddr);
258 #endif
259 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
260 return ret;
263 if (env->mmuregs[3]) /* Fault status register */
264 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
265 env->mmuregs[3] |= (access_index << 5) | error_code | 2;
266 env->mmuregs[4] = address; /* Fault address register */
268 if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
269 // No fault mode: if a mapping is available, just override
270 // permissions. If no mapping is available, redirect accesses to
271 // neverland. Fake/overridden mappings will be flushed when
272 // switching to normal mode.
273 vaddr = address & TARGET_PAGE_MASK;
274 prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
275 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
276 return ret;
277 } else {
278 if (rw & 2)
279 env->exception_index = TT_TFAULT;
280 else
281 env->exception_index = TT_DFAULT;
282 return 1;
286 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
288 target_phys_addr_t pde_ptr;
289 uint32_t pde;
291 /* Context base + context number */
292 pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
293 (env->mmuregs[2] << 2);
294 pde = ldl_phys(pde_ptr);
296 switch (pde & PTE_ENTRYTYPE_MASK) {
297 default:
298 case 0: /* Invalid */
299 case 2: /* PTE, maybe should not happen? */
300 case 3: /* Reserved */
301 return 0;
302 case 1: /* L1 PDE */
303 if (mmulev == 3)
304 return pde;
305 pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
306 pde = ldl_phys(pde_ptr);
308 switch (pde & PTE_ENTRYTYPE_MASK) {
309 default:
310 case 0: /* Invalid */
311 case 3: /* Reserved */
312 return 0;
313 case 2: /* L1 PTE */
314 return pde;
315 case 1: /* L2 PDE */
316 if (mmulev == 2)
317 return pde;
318 pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
319 pde = ldl_phys(pde_ptr);
321 switch (pde & PTE_ENTRYTYPE_MASK) {
322 default:
323 case 0: /* Invalid */
324 case 3: /* Reserved */
325 return 0;
326 case 2: /* L2 PTE */
327 return pde;
328 case 1: /* L3 PDE */
329 if (mmulev == 1)
330 return pde;
331 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
332 pde = ldl_phys(pde_ptr);
334 switch (pde & PTE_ENTRYTYPE_MASK) {
335 default:
336 case 0: /* Invalid */
337 case 1: /* PDE, should not happen */
338 case 3: /* Reserved */
339 return 0;
340 case 2: /* L3 PTE */
341 return pde;
346 return 0;
349 #ifdef DEBUG_MMU
350 void dump_mmu(CPUState *env)
352 target_ulong va, va1, va2;
353 unsigned int n, m, o;
354 target_phys_addr_t pde_ptr, pa;
355 uint32_t pde;
357 printf("MMU dump:\n");
358 pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
359 pde = ldl_phys(pde_ptr);
360 printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
361 (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
362 for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
363 pde = mmu_probe(env, va, 2);
364 if (pde) {
365 pa = cpu_get_phys_page_debug(env, va);
366 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
367 " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
368 for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
369 pde = mmu_probe(env, va1, 1);
370 if (pde) {
371 pa = cpu_get_phys_page_debug(env, va1);
372 printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
373 " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
374 for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
375 pde = mmu_probe(env, va2, 0);
376 if (pde) {
377 pa = cpu_get_phys_page_debug(env, va2);
378 printf(" VA: " TARGET_FMT_lx ", PA: "
379 TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
380 va2, pa, pde);
387 printf("MMU dump ends\n");
389 #endif /* DEBUG_MMU */
391 #else /* !TARGET_SPARC64 */
393 * UltraSparc IIi I/DMMUs
395 static int get_physical_address_data(CPUState *env,
396 target_phys_addr_t *physical, int *prot,
397 target_ulong address, int rw, int is_user)
399 target_ulong mask;
400 unsigned int i;
402 if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
403 *physical = address;
404 *prot = PAGE_READ | PAGE_WRITE;
405 return 0;
408 for (i = 0; i < 64; i++) {
409 switch ((env->dtlb_tte[i] >> 61) & 3) {
410 default:
411 case 0x0: // 8k
412 mask = 0xffffffffffffe000ULL;
413 break;
414 case 0x1: // 64k
415 mask = 0xffffffffffff0000ULL;
416 break;
417 case 0x2: // 512k
418 mask = 0xfffffffffff80000ULL;
419 break;
420 case 0x3: // 4M
421 mask = 0xffffffffffc00000ULL;
422 break;
424 // ctx match, vaddr match?
425 if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
426 (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
427 // valid, access ok?
428 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
429 ((env->dtlb_tte[i] & 0x4) && is_user) ||
430 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
431 if (env->dmmuregs[3]) /* Fault status register */
432 env->dmmuregs[3] = 2; /* overflow (not read before
433 another fault) */
434 env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
435 env->dmmuregs[4] = address; /* Fault address register */
436 env->exception_index = TT_DFAULT;
437 #ifdef DEBUG_MMU
438 printf("DFAULT at 0x%" PRIx64 "\n", address);
439 #endif
440 return 1;
442 *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
443 (address & ~mask & 0x1fffffff000ULL);
444 *prot = PAGE_READ;
445 if (env->dtlb_tte[i] & 0x2)
446 *prot |= PAGE_WRITE;
447 return 0;
450 #ifdef DEBUG_MMU
451 printf("DMISS at 0x%" PRIx64 "\n", address);
452 #endif
453 env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
454 env->exception_index = TT_DMISS;
455 return 1;
458 static int get_physical_address_code(CPUState *env,
459 target_phys_addr_t *physical, int *prot,
460 target_ulong address, int is_user)
462 target_ulong mask;
463 unsigned int i;
465 if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
466 *physical = address;
467 *prot = PAGE_EXEC;
468 return 0;
471 for (i = 0; i < 64; i++) {
472 switch ((env->itlb_tte[i] >> 61) & 3) {
473 default:
474 case 0x0: // 8k
475 mask = 0xffffffffffffe000ULL;
476 break;
477 case 0x1: // 64k
478 mask = 0xffffffffffff0000ULL;
479 break;
480 case 0x2: // 512k
481 mask = 0xfffffffffff80000ULL;
482 break;
483 case 0x3: // 4M
484 mask = 0xffffffffffc00000ULL;
485 break;
487 // ctx match, vaddr match?
488 if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
489 (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
490 // valid, access ok?
491 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
492 ((env->itlb_tte[i] & 0x4) && is_user)) {
493 if (env->immuregs[3]) /* Fault status register */
494 env->immuregs[3] = 2; /* overflow (not read before
495 another fault) */
496 env->immuregs[3] |= (is_user << 3) | 1;
497 env->exception_index = TT_TFAULT;
498 #ifdef DEBUG_MMU
499 printf("TFAULT at 0x%" PRIx64 "\n", address);
500 #endif
501 return 1;
503 *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
504 (address & ~mask & 0x1fffffff000ULL);
505 *prot = PAGE_EXEC;
506 return 0;
509 #ifdef DEBUG_MMU
510 printf("TMISS at 0x%" PRIx64 "\n", address);
511 #endif
512 env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
513 env->exception_index = TT_TMISS;
514 return 1;
517 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
518 int *prot, int *access_index,
519 target_ulong address, int rw, int mmu_idx)
521 int is_user = mmu_idx == MMU_USER_IDX;
523 if (rw == 2)
524 return get_physical_address_code(env, physical, prot, address,
525 is_user);
526 else
527 return get_physical_address_data(env, physical, prot, address, rw,
528 is_user);
531 /* Perform address translation */
532 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
533 int mmu_idx, int is_softmmu)
535 target_ulong virt_addr, vaddr;
536 target_phys_addr_t paddr;
537 int error_code = 0, prot, ret = 0, access_index;
539 error_code = get_physical_address(env, &paddr, &prot, &access_index,
540 address, rw, mmu_idx);
541 if (error_code == 0) {
542 virt_addr = address & TARGET_PAGE_MASK;
543 vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
544 (TARGET_PAGE_SIZE - 1));
545 #ifdef DEBUG_MMU
546 printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
547 "\n", address, paddr, vaddr);
548 #endif
549 ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
550 return ret;
552 // XXX
553 return 1;
556 #ifdef DEBUG_MMU
557 void dump_mmu(CPUState *env)
559 unsigned int i;
560 const char *mask;
562 printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
563 env->dmmuregs[1], env->dmmuregs[2]);
564 if ((env->lsu & DMMU_E) == 0) {
565 printf("DMMU disabled\n");
566 } else {
567 printf("DMMU dump:\n");
568 for (i = 0; i < 64; i++) {
569 switch ((env->dtlb_tte[i] >> 61) & 3) {
570 default:
571 case 0x0:
572 mask = " 8k";
573 break;
574 case 0x1:
575 mask = " 64k";
576 break;
577 case 0x2:
578 mask = "512k";
579 break;
580 case 0x3:
581 mask = " 4M";
582 break;
584 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
585 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
586 ", %s, %s, %s, %s, ctx %" PRId64 "\n",
587 env->dtlb_tag[i] & ~0x1fffULL,
588 env->dtlb_tte[i] & 0x1ffffffe000ULL,
589 mask,
590 env->dtlb_tte[i] & 0x4? "priv": "user",
591 env->dtlb_tte[i] & 0x2? "RW": "RO",
592 env->dtlb_tte[i] & 0x40? "locked": "unlocked",
593 env->dtlb_tag[i] & 0x1fffULL);
597 if ((env->lsu & IMMU_E) == 0) {
598 printf("IMMU disabled\n");
599 } else {
600 printf("IMMU dump:\n");
601 for (i = 0; i < 64; i++) {
602 switch ((env->itlb_tte[i] >> 61) & 3) {
603 default:
604 case 0x0:
605 mask = " 8k";
606 break;
607 case 0x1:
608 mask = " 64k";
609 break;
610 case 0x2:
611 mask = "512k";
612 break;
613 case 0x3:
614 mask = " 4M";
615 break;
617 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
618 printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
619 ", %s, %s, %s, ctx %" PRId64 "\n",
620 env->itlb_tag[i] & ~0x1fffULL,
621 env->itlb_tte[i] & 0x1ffffffe000ULL,
622 mask,
623 env->itlb_tte[i] & 0x4? "priv": "user",
624 env->itlb_tte[i] & 0x40? "locked": "unlocked",
625 env->itlb_tag[i] & 0x1fffULL);
630 #endif /* DEBUG_MMU */
632 #endif /* TARGET_SPARC64 */
633 #endif /* !CONFIG_USER_ONLY */
636 #if defined(CONFIG_USER_ONLY)
637 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
639 return addr;
642 #else
643 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
645 target_phys_addr_t phys_addr;
646 int prot, access_index;
648 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
649 MMU_KERNEL_IDX) != 0)
650 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
651 0, MMU_KERNEL_IDX) != 0)
652 return -1;
653 if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
654 return -1;
655 return phys_addr;
657 #endif
659 #ifdef TARGET_SPARC64
660 #ifdef DEBUG_PCALL
661 static const char * const excp_names[0x80] = {
662 [TT_TFAULT] = "Instruction Access Fault",
663 [TT_TMISS] = "Instruction Access MMU Miss",
664 [TT_CODE_ACCESS] = "Instruction Access Error",
665 [TT_ILL_INSN] = "Illegal Instruction",
666 [TT_PRIV_INSN] = "Privileged Instruction",
667 [TT_NFPU_INSN] = "FPU Disabled",
668 [TT_FP_EXCP] = "FPU Exception",
669 [TT_TOVF] = "Tag Overflow",
670 [TT_CLRWIN] = "Clean Windows",
671 [TT_DIV_ZERO] = "Division By Zero",
672 [TT_DFAULT] = "Data Access Fault",
673 [TT_DMISS] = "Data Access MMU Miss",
674 [TT_DATA_ACCESS] = "Data Access Error",
675 [TT_DPROT] = "Data Protection Error",
676 [TT_UNALIGNED] = "Unaligned Memory Access",
677 [TT_PRIV_ACT] = "Privileged Action",
678 [TT_EXTINT | 0x1] = "External Interrupt 1",
679 [TT_EXTINT | 0x2] = "External Interrupt 2",
680 [TT_EXTINT | 0x3] = "External Interrupt 3",
681 [TT_EXTINT | 0x4] = "External Interrupt 4",
682 [TT_EXTINT | 0x5] = "External Interrupt 5",
683 [TT_EXTINT | 0x6] = "External Interrupt 6",
684 [TT_EXTINT | 0x7] = "External Interrupt 7",
685 [TT_EXTINT | 0x8] = "External Interrupt 8",
686 [TT_EXTINT | 0x9] = "External Interrupt 9",
687 [TT_EXTINT | 0xa] = "External Interrupt 10",
688 [TT_EXTINT | 0xb] = "External Interrupt 11",
689 [TT_EXTINT | 0xc] = "External Interrupt 12",
690 [TT_EXTINT | 0xd] = "External Interrupt 13",
691 [TT_EXTINT | 0xe] = "External Interrupt 14",
692 [TT_EXTINT | 0xf] = "External Interrupt 15",
694 #endif
696 void do_interrupt(CPUState *env)
698 int intno = env->exception_index;
700 #ifdef DEBUG_PCALL
701 if (loglevel & CPU_LOG_INT) {
702 static int count;
703 const char *name;
705 if (intno < 0 || intno >= 0x180)
706 name = "Unknown";
707 else if (intno >= 0x100)
708 name = "Trap Instruction";
709 else if (intno >= 0xc0)
710 name = "Window Fill";
711 else if (intno >= 0x80)
712 name = "Window Spill";
713 else {
714 name = excp_names[intno];
715 if (!name)
716 name = "Unknown";
719 fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
720 " SP=%016" PRIx64 "\n",
721 count, name, intno,
722 env->pc,
723 env->npc, env->regwptr[6]);
724 cpu_dump_state(env, logfile, fprintf, 0);
725 #if 0
727 int i;
728 uint8_t *ptr;
730 fprintf(logfile, " code=");
731 ptr = (uint8_t *)env->pc;
732 for(i = 0; i < 16; i++) {
733 fprintf(logfile, " %02x", ldub(ptr + i));
735 fprintf(logfile, "\n");
737 #endif
738 count++;
740 #endif
741 #if !defined(CONFIG_USER_ONLY)
742 if (env->tl >= env->maxtl) {
743 cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
744 " Error state", env->exception_index, env->tl, env->maxtl);
745 return;
747 #endif
748 if (env->tl < env->maxtl - 1) {
749 env->tl++;
750 } else {
751 env->pstate |= PS_RED;
752 if (env->tl < env->maxtl)
753 env->tl++;
755 env->tsptr = &env->ts[env->tl & MAXTL_MASK];
756 env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
757 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
758 GET_CWP64(env);
759 env->tsptr->tpc = env->pc;
760 env->tsptr->tnpc = env->npc;
761 env->tsptr->tt = intno;
762 if (!(env->features & CPU_FEATURE_GL)) {
763 switch (intno) {
764 case TT_IVEC:
765 change_pstate(PS_PEF | PS_PRIV | PS_IG);
766 break;
767 case TT_TFAULT:
768 case TT_TMISS:
769 case TT_DFAULT:
770 case TT_DMISS:
771 case TT_DPROT:
772 change_pstate(PS_PEF | PS_PRIV | PS_MG);
773 break;
774 default:
775 change_pstate(PS_PEF | PS_PRIV | PS_AG);
776 break;
779 if (intno == TT_CLRWIN)
780 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
781 else if ((intno & 0x1c0) == TT_SPILL)
782 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
783 else if ((intno & 0x1c0) == TT_FILL)
784 cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
785 env->tbr &= ~0x7fffULL;
786 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
787 env->pc = env->tbr;
788 env->npc = env->pc + 4;
789 env->exception_index = 0;
791 #else
792 #ifdef DEBUG_PCALL
793 static const char * const excp_names[0x80] = {
794 [TT_TFAULT] = "Instruction Access Fault",
795 [TT_ILL_INSN] = "Illegal Instruction",
796 [TT_PRIV_INSN] = "Privileged Instruction",
797 [TT_NFPU_INSN] = "FPU Disabled",
798 [TT_WIN_OVF] = "Window Overflow",
799 [TT_WIN_UNF] = "Window Underflow",
800 [TT_UNALIGNED] = "Unaligned Memory Access",
801 [TT_FP_EXCP] = "FPU Exception",
802 [TT_DFAULT] = "Data Access Fault",
803 [TT_TOVF] = "Tag Overflow",
804 [TT_EXTINT | 0x1] = "External Interrupt 1",
805 [TT_EXTINT | 0x2] = "External Interrupt 2",
806 [TT_EXTINT | 0x3] = "External Interrupt 3",
807 [TT_EXTINT | 0x4] = "External Interrupt 4",
808 [TT_EXTINT | 0x5] = "External Interrupt 5",
809 [TT_EXTINT | 0x6] = "External Interrupt 6",
810 [TT_EXTINT | 0x7] = "External Interrupt 7",
811 [TT_EXTINT | 0x8] = "External Interrupt 8",
812 [TT_EXTINT | 0x9] = "External Interrupt 9",
813 [TT_EXTINT | 0xa] = "External Interrupt 10",
814 [TT_EXTINT | 0xb] = "External Interrupt 11",
815 [TT_EXTINT | 0xc] = "External Interrupt 12",
816 [TT_EXTINT | 0xd] = "External Interrupt 13",
817 [TT_EXTINT | 0xe] = "External Interrupt 14",
818 [TT_EXTINT | 0xf] = "External Interrupt 15",
819 [TT_TOVF] = "Tag Overflow",
820 [TT_CODE_ACCESS] = "Instruction Access Error",
821 [TT_DATA_ACCESS] = "Data Access Error",
822 [TT_DIV_ZERO] = "Division By Zero",
823 [TT_NCP_INSN] = "Coprocessor Disabled",
825 #endif
827 void do_interrupt(CPUState *env)
829 int cwp, intno = env->exception_index;
831 #ifdef DEBUG_PCALL
832 if (loglevel & CPU_LOG_INT) {
833 static int count;
834 const char *name;
836 if (intno < 0 || intno >= 0x100)
837 name = "Unknown";
838 else if (intno >= 0x80)
839 name = "Trap Instruction";
840 else {
841 name = excp_names[intno];
842 if (!name)
843 name = "Unknown";
846 fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
847 count, name, intno,
848 env->pc,
849 env->npc, env->regwptr[6]);
850 cpu_dump_state(env, logfile, fprintf, 0);
851 #if 0
853 int i;
854 uint8_t *ptr;
856 fprintf(logfile, " code=");
857 ptr = (uint8_t *)env->pc;
858 for(i = 0; i < 16; i++) {
859 fprintf(logfile, " %02x", ldub(ptr + i));
861 fprintf(logfile, "\n");
863 #endif
864 count++;
866 #endif
867 #if !defined(CONFIG_USER_ONLY)
868 if (env->psret == 0) {
869 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
870 env->exception_index);
871 return;
873 #endif
874 env->psret = 0;
875 cwp = cpu_cwp_dec(env, env->cwp - 1);
876 cpu_set_cwp(env, cwp);
877 env->regwptr[9] = env->pc;
878 env->regwptr[10] = env->npc;
879 env->psrps = env->psrs;
880 env->psrs = 1;
881 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
882 env->pc = env->tbr;
883 env->npc = env->pc + 4;
884 env->exception_index = 0;
886 #endif
888 void memcpy32(target_ulong *dst, const target_ulong *src)
890 dst[0] = src[0];
891 dst[1] = src[1];
892 dst[2] = src[2];
893 dst[3] = src[3];
894 dst[4] = src[4];
895 dst[5] = src[5];
896 dst[6] = src[6];
897 dst[7] = src[7];
900 void cpu_reset(CPUSPARCState *env)
902 tlb_flush(env, 1);
903 env->cwp = 0;
904 env->wim = 1;
905 env->regwptr = env->regbase + (env->cwp * 16);
906 #if defined(CONFIG_USER_ONLY)
907 env->user_mode_only = 1;
908 #ifdef TARGET_SPARC64
909 env->cleanwin = env->nwindows - 2;
910 env->cansave = env->nwindows - 2;
911 env->pstate = PS_RMO | PS_PEF | PS_IE;
912 env->asi = 0x82; // Primary no-fault
913 #endif
914 #else
915 env->psret = 0;
916 env->psrs = 1;
917 env->psrps = 1;
918 #ifdef TARGET_SPARC64
919 env->pstate = PS_PRIV;
920 env->hpstate = HS_PRIV;
921 env->pc = 0x1fff0000020ULL; // XXX should be different for system_reset
922 env->tsptr = &env->ts[env->tl & MAXTL_MASK];
923 #else
924 env->pc = 0;
925 env->mmuregs[0] &= ~(MMU_E | MMU_NF);
926 env->mmuregs[0] |= env->mmu_bm;
927 #endif
928 env->npc = env->pc + 4;
929 #endif
932 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
934 sparc_def_t def1, *def = &def1;
936 if (cpu_sparc_find_by_name(def, cpu_model) < 0)
937 return -1;
939 env->features = def->features;
940 env->cpu_model_str = cpu_model;
941 env->version = def->iu_version;
942 env->fsr = def->fpu_version;
943 env->nwindows = def->nwindows;
944 #if !defined(TARGET_SPARC64)
945 env->mmu_bm = def->mmu_bm;
946 env->mmu_ctpr_mask = def->mmu_ctpr_mask;
947 env->mmu_cxr_mask = def->mmu_cxr_mask;
948 env->mmu_sfsr_mask = def->mmu_sfsr_mask;
949 env->mmu_trcr_mask = def->mmu_trcr_mask;
950 env->mmuregs[0] |= def->mmu_version;
951 cpu_sparc_set_id(env, 0);
952 #else
953 env->mmu_version = def->mmu_version;
954 env->maxtl = def->maxtl;
955 env->version |= def->maxtl << 8;
956 env->version |= def->nwindows - 1;
957 #endif
958 return 0;
961 static void cpu_sparc_close(CPUSPARCState *env)
963 free(env);
966 CPUSPARCState *cpu_sparc_init(const char *cpu_model)
968 CPUSPARCState *env;
970 env = qemu_mallocz(sizeof(CPUSPARCState));
971 if (!env)
972 return NULL;
973 cpu_exec_init(env);
975 gen_intermediate_code_init(env);
977 if (cpu_sparc_register(env, cpu_model) < 0) {
978 cpu_sparc_close(env);
979 return NULL;
981 cpu_reset(env);
983 return env;
986 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
988 #if !defined(TARGET_SPARC64)
989 env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
990 #endif
993 static const sparc_def_t sparc_defs[] = {
994 #ifdef TARGET_SPARC64
996 .name = "Fujitsu Sparc64",
997 .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
998 .fpu_version = 0x00000000,
999 .mmu_version = mmu_us_12,
1000 .nwindows = 4,
1001 .maxtl = 4,
1002 .features = CPU_DEFAULT_FEATURES,
1005 .name = "Fujitsu Sparc64 III",
1006 .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
1007 .fpu_version = 0x00000000,
1008 .mmu_version = mmu_us_12,
1009 .nwindows = 5,
1010 .maxtl = 4,
1011 .features = CPU_DEFAULT_FEATURES,
1014 .name = "Fujitsu Sparc64 IV",
1015 .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
1016 .fpu_version = 0x00000000,
1017 .mmu_version = mmu_us_12,
1018 .nwindows = 8,
1019 .maxtl = 5,
1020 .features = CPU_DEFAULT_FEATURES,
1023 .name = "Fujitsu Sparc64 V",
1024 .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
1025 .fpu_version = 0x00000000,
1026 .mmu_version = mmu_us_12,
1027 .nwindows = 8,
1028 .maxtl = 5,
1029 .features = CPU_DEFAULT_FEATURES,
1032 .name = "TI UltraSparc I",
1033 .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1034 .fpu_version = 0x00000000,
1035 .mmu_version = mmu_us_12,
1036 .nwindows = 8,
1037 .maxtl = 5,
1038 .features = CPU_DEFAULT_FEATURES,
1041 .name = "TI UltraSparc II",
1042 .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
1043 .fpu_version = 0x00000000,
1044 .mmu_version = mmu_us_12,
1045 .nwindows = 8,
1046 .maxtl = 5,
1047 .features = CPU_DEFAULT_FEATURES,
1050 .name = "TI UltraSparc IIi",
1051 .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
1052 .fpu_version = 0x00000000,
1053 .mmu_version = mmu_us_12,
1054 .nwindows = 8,
1055 .maxtl = 5,
1056 .features = CPU_DEFAULT_FEATURES,
1059 .name = "TI UltraSparc IIe",
1060 .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
1061 .fpu_version = 0x00000000,
1062 .mmu_version = mmu_us_12,
1063 .nwindows = 8,
1064 .maxtl = 5,
1065 .features = CPU_DEFAULT_FEATURES,
1068 .name = "Sun UltraSparc III",
1069 .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
1070 .fpu_version = 0x00000000,
1071 .mmu_version = mmu_us_12,
1072 .nwindows = 8,
1073 .maxtl = 5,
1074 .features = CPU_DEFAULT_FEATURES,
1077 .name = "Sun UltraSparc III Cu",
1078 .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
1079 .fpu_version = 0x00000000,
1080 .mmu_version = mmu_us_3,
1081 .nwindows = 8,
1082 .maxtl = 5,
1083 .features = CPU_DEFAULT_FEATURES,
1086 .name = "Sun UltraSparc IIIi",
1087 .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
1088 .fpu_version = 0x00000000,
1089 .mmu_version = mmu_us_12,
1090 .nwindows = 8,
1091 .maxtl = 5,
1092 .features = CPU_DEFAULT_FEATURES,
1095 .name = "Sun UltraSparc IV",
1096 .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
1097 .fpu_version = 0x00000000,
1098 .mmu_version = mmu_us_4,
1099 .nwindows = 8,
1100 .maxtl = 5,
1101 .features = CPU_DEFAULT_FEATURES,
1104 .name = "Sun UltraSparc IV+",
1105 .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
1106 .fpu_version = 0x00000000,
1107 .mmu_version = mmu_us_12,
1108 .nwindows = 8,
1109 .maxtl = 5,
1110 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
1113 .name = "Sun UltraSparc IIIi+",
1114 .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
1115 .fpu_version = 0x00000000,
1116 .mmu_version = mmu_us_3,
1117 .nwindows = 8,
1118 .maxtl = 5,
1119 .features = CPU_DEFAULT_FEATURES,
1122 .name = "Sun UltraSparc T1",
1123 // defined in sparc_ifu_fdp.v and ctu.h
1124 .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
1125 .fpu_version = 0x00000000,
1126 .mmu_version = mmu_sun4v,
1127 .nwindows = 8,
1128 .maxtl = 6,
1129 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1130 | CPU_FEATURE_GL,
1133 .name = "Sun UltraSparc T2",
1134 // defined in tlu_asi_ctl.v and n2_revid_cust.v
1135 .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
1136 .fpu_version = 0x00000000,
1137 .mmu_version = mmu_sun4v,
1138 .nwindows = 8,
1139 .maxtl = 6,
1140 .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
1141 | CPU_FEATURE_GL,
1144 .name = "NEC UltraSparc I",
1145 .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
1146 .fpu_version = 0x00000000,
1147 .mmu_version = mmu_us_12,
1148 .nwindows = 8,
1149 .maxtl = 5,
1150 .features = CPU_DEFAULT_FEATURES,
1152 #else
1154 .name = "Fujitsu MB86900",
1155 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
1156 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1157 .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
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 = 7,
1164 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
1167 .name = "Fujitsu MB86904",
1168 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
1169 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1170 .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
1171 .mmu_bm = 0x00004000,
1172 .mmu_ctpr_mask = 0x00ffffc0,
1173 .mmu_cxr_mask = 0x000000ff,
1174 .mmu_sfsr_mask = 0x00016fff,
1175 .mmu_trcr_mask = 0x00ffffff,
1176 .nwindows = 8,
1177 .features = CPU_DEFAULT_FEATURES,
1180 .name = "Fujitsu MB86907",
1181 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
1182 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1183 .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
1184 .mmu_bm = 0x00004000,
1185 .mmu_ctpr_mask = 0xffffffc0,
1186 .mmu_cxr_mask = 0x000000ff,
1187 .mmu_sfsr_mask = 0x00016fff,
1188 .mmu_trcr_mask = 0xffffffff,
1189 .nwindows = 8,
1190 .features = CPU_DEFAULT_FEATURES,
1193 .name = "LSI L64811",
1194 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
1195 .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
1196 .mmu_version = 0x10 << 24,
1197 .mmu_bm = 0x00004000,
1198 .mmu_ctpr_mask = 0x007ffff0,
1199 .mmu_cxr_mask = 0x0000003f,
1200 .mmu_sfsr_mask = 0xffffffff,
1201 .mmu_trcr_mask = 0xffffffff,
1202 .nwindows = 8,
1203 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1204 CPU_FEATURE_FSMULD,
1207 .name = "Cypress CY7C601",
1208 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
1209 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1210 .mmu_version = 0x10 << 24,
1211 .mmu_bm = 0x00004000,
1212 .mmu_ctpr_mask = 0x007ffff0,
1213 .mmu_cxr_mask = 0x0000003f,
1214 .mmu_sfsr_mask = 0xffffffff,
1215 .mmu_trcr_mask = 0xffffffff,
1216 .nwindows = 8,
1217 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1218 CPU_FEATURE_FSMULD,
1221 .name = "Cypress CY7C611",
1222 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
1223 .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
1224 .mmu_version = 0x10 << 24,
1225 .mmu_bm = 0x00004000,
1226 .mmu_ctpr_mask = 0x007ffff0,
1227 .mmu_cxr_mask = 0x0000003f,
1228 .mmu_sfsr_mask = 0xffffffff,
1229 .mmu_trcr_mask = 0xffffffff,
1230 .nwindows = 8,
1231 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1232 CPU_FEATURE_FSMULD,
1235 .name = "TI SuperSparc II",
1236 .iu_version = 0x40000000,
1237 .fpu_version = 0 << 17,
1238 .mmu_version = 0x04000000,
1239 .mmu_bm = 0x00002000,
1240 .mmu_ctpr_mask = 0xffffffc0,
1241 .mmu_cxr_mask = 0x0000ffff,
1242 .mmu_sfsr_mask = 0xffffffff,
1243 .mmu_trcr_mask = 0xffffffff,
1244 .nwindows = 8,
1245 .features = CPU_DEFAULT_FEATURES,
1248 .name = "TI MicroSparc I",
1249 .iu_version = 0x41000000,
1250 .fpu_version = 4 << 17,
1251 .mmu_version = 0x41000000,
1252 .mmu_bm = 0x00004000,
1253 .mmu_ctpr_mask = 0x007ffff0,
1254 .mmu_cxr_mask = 0x0000003f,
1255 .mmu_sfsr_mask = 0x00016fff,
1256 .mmu_trcr_mask = 0x0000003f,
1257 .nwindows = 7,
1258 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
1259 CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
1260 CPU_FEATURE_FMUL,
1263 .name = "TI MicroSparc II",
1264 .iu_version = 0x42000000,
1265 .fpu_version = 4 << 17,
1266 .mmu_version = 0x02000000,
1267 .mmu_bm = 0x00004000,
1268 .mmu_ctpr_mask = 0x00ffffc0,
1269 .mmu_cxr_mask = 0x000000ff,
1270 .mmu_sfsr_mask = 0x00016fff,
1271 .mmu_trcr_mask = 0x00ffffff,
1272 .nwindows = 8,
1273 .features = CPU_DEFAULT_FEATURES,
1276 .name = "TI MicroSparc IIep",
1277 .iu_version = 0x42000000,
1278 .fpu_version = 4 << 17,
1279 .mmu_version = 0x04000000,
1280 .mmu_bm = 0x00004000,
1281 .mmu_ctpr_mask = 0x00ffffc0,
1282 .mmu_cxr_mask = 0x000000ff,
1283 .mmu_sfsr_mask = 0x00016bff,
1284 .mmu_trcr_mask = 0x00ffffff,
1285 .nwindows = 8,
1286 .features = CPU_DEFAULT_FEATURES,
1289 .name = "TI SuperSparc 40", // STP1020NPGA
1290 .iu_version = 0x41000000,
1291 .fpu_version = 0 << 17,
1292 .mmu_version = 0x00000000,
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 50", // STP1020PGA
1303 .iu_version = 0x40000000,
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 = "TI SuperSparc 51",
1316 .iu_version = 0x43000000,
1317 .fpu_version = 0 << 17,
1318 .mmu_version = 0x04000000,
1319 .mmu_bm = 0x00002000,
1320 .mmu_ctpr_mask = 0xffffffc0,
1321 .mmu_cxr_mask = 0x0000ffff,
1322 .mmu_sfsr_mask = 0xffffffff,
1323 .mmu_trcr_mask = 0xffffffff,
1324 .nwindows = 8,
1325 .features = CPU_DEFAULT_FEATURES,
1328 .name = "TI SuperSparc 60", // STP1020APGA
1329 .iu_version = 0x40000000,
1330 .fpu_version = 0 << 17,
1331 .mmu_version = 0x03000000,
1332 .mmu_bm = 0x00002000,
1333 .mmu_ctpr_mask = 0xffffffc0,
1334 .mmu_cxr_mask = 0x0000ffff,
1335 .mmu_sfsr_mask = 0xffffffff,
1336 .mmu_trcr_mask = 0xffffffff,
1337 .nwindows = 8,
1338 .features = CPU_DEFAULT_FEATURES,
1341 .name = "TI SuperSparc 61",
1342 .iu_version = 0x44000000,
1343 .fpu_version = 0 << 17,
1344 .mmu_version = 0x04000000,
1345 .mmu_bm = 0x00002000,
1346 .mmu_ctpr_mask = 0xffffffc0,
1347 .mmu_cxr_mask = 0x0000ffff,
1348 .mmu_sfsr_mask = 0xffffffff,
1349 .mmu_trcr_mask = 0xffffffff,
1350 .nwindows = 8,
1351 .features = CPU_DEFAULT_FEATURES,
1354 .name = "Ross RT625",
1355 .iu_version = 0x1e000000,
1356 .fpu_version = 1 << 17,
1357 .mmu_version = 0x1e000000,
1358 .mmu_bm = 0x00004000,
1359 .mmu_ctpr_mask = 0x007ffff0,
1360 .mmu_cxr_mask = 0x0000003f,
1361 .mmu_sfsr_mask = 0xffffffff,
1362 .mmu_trcr_mask = 0xffffffff,
1363 .nwindows = 8,
1364 .features = CPU_DEFAULT_FEATURES,
1367 .name = "Ross RT620",
1368 .iu_version = 0x1f000000,
1369 .fpu_version = 1 << 17,
1370 .mmu_version = 0x1f000000,
1371 .mmu_bm = 0x00004000,
1372 .mmu_ctpr_mask = 0x007ffff0,
1373 .mmu_cxr_mask = 0x0000003f,
1374 .mmu_sfsr_mask = 0xffffffff,
1375 .mmu_trcr_mask = 0xffffffff,
1376 .nwindows = 8,
1377 .features = CPU_DEFAULT_FEATURES,
1380 .name = "BIT B5010",
1381 .iu_version = 0x20000000,
1382 .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
1383 .mmu_version = 0x20000000,
1384 .mmu_bm = 0x00004000,
1385 .mmu_ctpr_mask = 0x007ffff0,
1386 .mmu_cxr_mask = 0x0000003f,
1387 .mmu_sfsr_mask = 0xffffffff,
1388 .mmu_trcr_mask = 0xffffffff,
1389 .nwindows = 8,
1390 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
1391 CPU_FEATURE_FSMULD,
1394 .name = "Matsushita MN10501",
1395 .iu_version = 0x50000000,
1396 .fpu_version = 0 << 17,
1397 .mmu_version = 0x50000000,
1398 .mmu_bm = 0x00004000,
1399 .mmu_ctpr_mask = 0x007ffff0,
1400 .mmu_cxr_mask = 0x0000003f,
1401 .mmu_sfsr_mask = 0xffffffff,
1402 .mmu_trcr_mask = 0xffffffff,
1403 .nwindows = 8,
1404 .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
1405 CPU_FEATURE_FSMULD,
1408 .name = "Weitek W8601",
1409 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
1410 .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
1411 .mmu_version = 0x10 << 24,
1412 .mmu_bm = 0x00004000,
1413 .mmu_ctpr_mask = 0x007ffff0,
1414 .mmu_cxr_mask = 0x0000003f,
1415 .mmu_sfsr_mask = 0xffffffff,
1416 .mmu_trcr_mask = 0xffffffff,
1417 .nwindows = 8,
1418 .features = CPU_DEFAULT_FEATURES,
1421 .name = "LEON2",
1422 .iu_version = 0xf2000000,
1423 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1424 .mmu_version = 0xf2000000,
1425 .mmu_bm = 0x00004000,
1426 .mmu_ctpr_mask = 0x007ffff0,
1427 .mmu_cxr_mask = 0x0000003f,
1428 .mmu_sfsr_mask = 0xffffffff,
1429 .mmu_trcr_mask = 0xffffffff,
1430 .nwindows = 8,
1431 .features = CPU_DEFAULT_FEATURES,
1434 .name = "LEON3",
1435 .iu_version = 0xf3000000,
1436 .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
1437 .mmu_version = 0xf3000000,
1438 .mmu_bm = 0x00004000,
1439 .mmu_ctpr_mask = 0x007ffff0,
1440 .mmu_cxr_mask = 0x0000003f,
1441 .mmu_sfsr_mask = 0xffffffff,
1442 .mmu_trcr_mask = 0xffffffff,
1443 .nwindows = 8,
1444 .features = CPU_DEFAULT_FEATURES,
1446 #endif
1449 static const char * const feature_name[] = {
1450 "float",
1451 "float128",
1452 "swap",
1453 "mul",
1454 "div",
1455 "flush",
1456 "fsqrt",
1457 "fmul",
1458 "vis1",
1459 "vis2",
1460 "fsmuld",
1461 "hypv",
1462 "cmt",
1463 "gl",
1466 static void print_features(FILE *f,
1467 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1468 uint32_t features, const char *prefix)
1470 unsigned int i;
1472 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1473 if (feature_name[i] && (features & (1 << i))) {
1474 if (prefix)
1475 (*cpu_fprintf)(f, "%s", prefix);
1476 (*cpu_fprintf)(f, "%s ", feature_name[i]);
1480 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1482 unsigned int i;
1484 for (i = 0; i < ARRAY_SIZE(feature_name); i++)
1485 if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
1486 *features |= 1 << i;
1487 return;
1489 fprintf(stderr, "CPU feature %s not found\n", flagname);
1492 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
1494 unsigned int i;
1495 const sparc_def_t *def = NULL;
1496 char *s = strdup(cpu_model);
1497 char *featurestr, *name = strtok(s, ",");
1498 uint32_t plus_features = 0;
1499 uint32_t minus_features = 0;
1500 long long iu_version;
1501 uint32_t fpu_version, mmu_version, nwindows;
1503 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1504 if (strcasecmp(name, sparc_defs[i].name) == 0) {
1505 def = &sparc_defs[i];
1508 if (!def)
1509 goto error;
1510 memcpy(cpu_def, def, sizeof(*def));
1512 featurestr = strtok(NULL, ",");
1513 while (featurestr) {
1514 char *val;
1516 if (featurestr[0] == '+') {
1517 add_flagname_to_bitmaps(featurestr + 1, &plus_features);
1518 } else if (featurestr[0] == '-') {
1519 add_flagname_to_bitmaps(featurestr + 1, &minus_features);
1520 } else if ((val = strchr(featurestr, '='))) {
1521 *val = 0; val++;
1522 if (!strcmp(featurestr, "iu_version")) {
1523 char *err;
1525 iu_version = strtoll(val, &err, 0);
1526 if (!*val || *err) {
1527 fprintf(stderr, "bad numerical value %s\n", val);
1528 goto error;
1530 cpu_def->iu_version = iu_version;
1531 #ifdef DEBUG_FEATURES
1532 fprintf(stderr, "iu_version %llx\n", iu_version);
1533 #endif
1534 } else if (!strcmp(featurestr, "fpu_version")) {
1535 char *err;
1537 fpu_version = strtol(val, &err, 0);
1538 if (!*val || *err) {
1539 fprintf(stderr, "bad numerical value %s\n", val);
1540 goto error;
1542 cpu_def->fpu_version = fpu_version;
1543 #ifdef DEBUG_FEATURES
1544 fprintf(stderr, "fpu_version %llx\n", fpu_version);
1545 #endif
1546 } else if (!strcmp(featurestr, "mmu_version")) {
1547 char *err;
1549 mmu_version = strtol(val, &err, 0);
1550 if (!*val || *err) {
1551 fprintf(stderr, "bad numerical value %s\n", val);
1552 goto error;
1554 cpu_def->mmu_version = mmu_version;
1555 #ifdef DEBUG_FEATURES
1556 fprintf(stderr, "mmu_version %llx\n", mmu_version);
1557 #endif
1558 } else if (!strcmp(featurestr, "nwindows")) {
1559 char *err;
1561 nwindows = strtol(val, &err, 0);
1562 if (!*val || *err || nwindows > MAX_NWINDOWS ||
1563 nwindows < MIN_NWINDOWS) {
1564 fprintf(stderr, "bad numerical value %s\n", val);
1565 goto error;
1567 cpu_def->nwindows = nwindows;
1568 #ifdef DEBUG_FEATURES
1569 fprintf(stderr, "nwindows %d\n", nwindows);
1570 #endif
1571 } else {
1572 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1573 goto error;
1575 } else {
1576 fprintf(stderr, "feature string `%s' not in format "
1577 "(+feature|-feature|feature=xyz)\n", featurestr);
1578 goto error;
1580 featurestr = strtok(NULL, ",");
1582 cpu_def->features |= plus_features;
1583 cpu_def->features &= ~minus_features;
1584 #ifdef DEBUG_FEATURES
1585 print_features(stderr, fprintf, cpu_def->features, NULL);
1586 #endif
1587 free(s);
1588 return 0;
1590 error:
1591 free(s);
1592 return -1;
1595 void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1597 unsigned int i;
1599 for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
1600 (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
1601 sparc_defs[i].name,
1602 sparc_defs[i].iu_version,
1603 sparc_defs[i].fpu_version,
1604 sparc_defs[i].mmu_version,
1605 sparc_defs[i].nwindows);
1606 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
1607 ~sparc_defs[i].features, "-");
1608 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
1609 sparc_defs[i].features, "+");
1610 (*cpu_fprintf)(f, "\n");
1612 (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
1613 print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
1614 (*cpu_fprintf)(f, "\n");
1615 (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
1616 print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
1617 (*cpu_fprintf)(f, "\n");
1618 (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
1619 "fpu_version mmu_version nwindows\n");
1622 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
1624 void cpu_dump_state(CPUState *env, FILE *f,
1625 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1626 int flags)
1628 int i, x;
1630 cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
1631 env->npc);
1632 cpu_fprintf(f, "General Registers:\n");
1633 for (i = 0; i < 4; i++)
1634 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1635 cpu_fprintf(f, "\n");
1636 for (; i < 8; i++)
1637 cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1638 cpu_fprintf(f, "\nCurrent Register Window:\n");
1639 for (x = 0; x < 3; x++) {
1640 for (i = 0; i < 4; i++)
1641 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1642 (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
1643 env->regwptr[i + x * 8]);
1644 cpu_fprintf(f, "\n");
1645 for (; i < 8; i++)
1646 cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
1647 (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
1648 env->regwptr[i + x * 8]);
1649 cpu_fprintf(f, "\n");
1651 cpu_fprintf(f, "\nFloating Point Registers:\n");
1652 for (i = 0; i < 32; i++) {
1653 if ((i & 3) == 0)
1654 cpu_fprintf(f, "%%f%02d:", i);
1655 cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
1656 if ((i & 3) == 3)
1657 cpu_fprintf(f, "\n");
1659 #ifdef TARGET_SPARC64
1660 cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
1661 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1662 cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
1663 "cleanwin %d cwp %d\n",
1664 env->cansave, env->canrestore, env->otherwin, env->wstate,
1665 env->cleanwin, env->nwindows - 1 - env->cwp);
1666 #else
1667 cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
1668 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
1669 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
1670 env->psrs?'S':'-', env->psrps?'P':'-',
1671 env->psret?'E':'-', env->wim);
1672 #endif
1673 cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
1676 #ifdef TARGET_SPARC64
1677 #if !defined(CONFIG_USER_ONLY)
1678 #include "qemu-common.h"
1679 #include "hw/irq.h"
1680 #include "qemu-timer.h"
1681 #endif
1683 void helper_tick_set_count(void *opaque, uint64_t count)
1685 #if !defined(CONFIG_USER_ONLY)
1686 ptimer_set_count(opaque, -count);
1687 #endif
1690 uint64_t helper_tick_get_count(void *opaque)
1692 #if !defined(CONFIG_USER_ONLY)
1693 return -ptimer_get_count(opaque);
1694 #else
1695 return 0;
1696 #endif
1699 void helper_tick_set_limit(void *opaque, uint64_t limit)
1701 #if !defined(CONFIG_USER_ONLY)
1702 ptimer_set_limit(opaque, -limit, 0);
1703 #endif
1705 #endif