Annotation of qemu/target-sparc/helper.c, revision 1.1.1.5

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.