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