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

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

unix.superglobalmegacorp.com

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