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