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

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
1.1.1.7 ! root      389: static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
1.1.1.6   root      390:                                        uint64_t address, uint64_t context,
1.1.1.7 ! root      391:                                        target_phys_addr_t *physical,
        !           392:                                        int is_nucleus)
1.1.1.6   root      393: {
                    394:     uint64_t mask;
                    395: 
1.1.1.7 ! root      396:     switch ((tlb->tte >> 61) & 3) {
1.1.1.6   root      397:     default:
                    398:     case 0x0: // 8k
                    399:         mask = 0xffffffffffffe000ULL;
                    400:         break;
                    401:     case 0x1: // 64k
                    402:         mask = 0xffffffffffff0000ULL;
                    403:         break;
                    404:     case 0x2: // 512k
                    405:         mask = 0xfffffffffff80000ULL;
                    406:         break;
                    407:     case 0x3: // 4M
                    408:         mask = 0xffffffffffc00000ULL;
                    409:         break;
                    410:     }
                    411: 
                    412:     // valid, context match, virtual address match?
1.1.1.7 ! root      413:     if (TTE_IS_VALID(tlb->tte) &&
        !           414:         ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
        !           415:          || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag, 0x1fff))
        !           416:         && compare_masked(address, tlb->tag, mask))
1.1.1.6   root      417:     {
                    418:         // decode physical address
1.1.1.7 ! root      419:         *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
1.1.1.6   root      420:         return 1;
                    421:     }
                    422: 
                    423:     return 0;
                    424: }
                    425: 
1.1.1.5   root      426: static int get_physical_address_data(CPUState *env,
                    427:                                      target_phys_addr_t *physical, int *prot,
                    428:                                      target_ulong address, int rw, int is_user)
1.1       root      429: {
                    430:     unsigned int i;
1.1.1.6   root      431:     uint64_t context;
1.1.1.7 ! root      432:     int is_nucleus;
1.1       root      433: 
                    434:     if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
1.1.1.6   root      435:         *physical = ultrasparc_truncate_physical(address);
1.1.1.4   root      436:         *prot = PAGE_READ | PAGE_WRITE;
1.1       root      437:         return 0;
                    438:     }
                    439: 
1.1.1.7 ! root      440:     context = env->dmmu.mmu_primary_context & 0x1fff;
        !           441:     is_nucleus = env->tl > 0;
1.1.1.6   root      442: 
1.1       root      443:     for (i = 0; i < 64; i++) {
1.1.1.5   root      444:         // ctx match, vaddr match, valid?
1.1.1.7 ! root      445:         if (ultrasparc_tag_match(&env->dtlb[i],
        !           446:                                  address, context, physical,
        !           447:                                  is_nucleus)) {
1.1.1.5   root      448:             // access ok?
1.1.1.7 ! root      449:             if (((env->dtlb[i].tte & 0x4) && is_user) ||
        !           450:                 (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
        !           451:                 uint8_t fault_type = 0;
        !           452: 
        !           453:                 if ((env->dtlb[i].tte & 0x4) && is_user) {
        !           454:                     fault_type |= 1; /* privilege violation */
        !           455:                 }
        !           456: 
        !           457:                 if (env->dmmu.sfsr & 1) /* Fault status register */
        !           458:                     env->dmmu.sfsr = 2; /* overflow (not read before
1.1.1.5   root      459:                                              another fault) */
1.1.1.7 ! root      460: 
        !           461:                 env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
        !           462: 
        !           463:                 env->dmmu.sfsr |= (fault_type << 7);
        !           464: 
        !           465:                 env->dmmu.sfar = address; /* Fault address register */
1.1.1.4   root      466:                 env->exception_index = TT_DFAULT;
1.1       root      467: #ifdef DEBUG_MMU
1.1.1.4   root      468:                 printf("DFAULT at 0x%" PRIx64 "\n", address);
1.1       root      469: #endif
1.1.1.4   root      470:                 return 1;
                    471:             }
                    472:             *prot = PAGE_READ;
1.1.1.7 ! root      473:             if (env->dtlb[i].tte & 0x2)
1.1.1.4   root      474:                 *prot |= PAGE_WRITE;
1.1.1.7 ! root      475:             TTE_SET_USED(env->dtlb[i].tte);
1.1.1.4   root      476:             return 0;
                    477:         }
1.1       root      478:     }
                    479: #ifdef DEBUG_MMU
1.1.1.3   root      480:     printf("DMISS at 0x%" PRIx64 "\n", address);
1.1       root      481: #endif
1.1.1.7 ! root      482:     env->dmmu.tag_access = (address & ~0x1fffULL) | context;
1.1       root      483:     env->exception_index = TT_DMISS;
                    484:     return 1;
                    485: }
                    486: 
1.1.1.5   root      487: static int get_physical_address_code(CPUState *env,
                    488:                                      target_phys_addr_t *physical, int *prot,
                    489:                                      target_ulong address, int is_user)
1.1       root      490: {
                    491:     unsigned int i;
1.1.1.6   root      492:     uint64_t context;
1.1.1.7 ! root      493:     int is_nucleus;
1.1       root      494: 
1.1.1.6   root      495:     if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
                    496:         /* IMMU disabled */
                    497:         *physical = ultrasparc_truncate_physical(address);
1.1.1.4   root      498:         *prot = PAGE_EXEC;
1.1       root      499:         return 0;
                    500:     }
                    501: 
1.1.1.7 ! root      502:     context = env->dmmu.mmu_primary_context & 0x1fff;
        !           503:     is_nucleus = env->tl > 0;
1.1.1.6   root      504: 
1.1       root      505:     for (i = 0; i < 64; i++) {
1.1.1.5   root      506:         // ctx match, vaddr match, valid?
1.1.1.7 ! root      507:         if (ultrasparc_tag_match(&env->itlb[i],
        !           508:                                  address, context, physical,
        !           509:                                  is_nucleus)) {
1.1.1.5   root      510:             // access ok?
1.1.1.7 ! root      511:             if ((env->itlb[i].tte & 0x4) && is_user) {
        !           512:                 if (env->immu.sfsr) /* Fault status register */
        !           513:                     env->immu.sfsr = 2; /* overflow (not read before
1.1.1.5   root      514:                                              another fault) */
1.1.1.7 ! root      515:                 env->immu.sfsr |= (is_user << 3) | 1;
1.1.1.4   root      516:                 env->exception_index = TT_TFAULT;
1.1       root      517: #ifdef DEBUG_MMU
1.1.1.4   root      518:                 printf("TFAULT at 0x%" PRIx64 "\n", address);
1.1       root      519: #endif
1.1.1.4   root      520:                 return 1;
                    521:             }
                    522:             *prot = PAGE_EXEC;
1.1.1.7 ! root      523:             TTE_SET_USED(env->itlb[i].tte);
1.1.1.4   root      524:             return 0;
                    525:         }
1.1       root      526:     }
                    527: #ifdef DEBUG_MMU
1.1.1.3   root      528:     printf("TMISS at 0x%" PRIx64 "\n", address);
1.1       root      529: #endif
1.1.1.6   root      530:     /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
1.1.1.7 ! root      531:     env->immu.tag_access = (address & ~0x1fffULL) | context;
1.1       root      532:     env->exception_index = TT_TMISS;
                    533:     return 1;
                    534: }
                    535: 
1.1.1.5   root      536: static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
                    537:                                 int *prot, int *access_index,
                    538:                                 target_ulong address, int rw, int mmu_idx)
1.1       root      539: {
1.1.1.4   root      540:     int is_user = mmu_idx == MMU_USER_IDX;
                    541: 
1.1       root      542:     if (rw == 2)
1.1.1.5   root      543:         return get_physical_address_code(env, physical, prot, address,
                    544:                                          is_user);
1.1       root      545:     else
1.1.1.5   root      546:         return get_physical_address_data(env, physical, prot, address, rw,
                    547:                                          is_user);
1.1       root      548: }
                    549: 
                    550: /* Perform address translation */
                    551: int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1.1.1.4   root      552:                               int mmu_idx, int is_softmmu)
1.1       root      553: {
                    554:     target_ulong virt_addr, vaddr;
                    555:     target_phys_addr_t paddr;
                    556:     int error_code = 0, prot, ret = 0, access_index;
                    557: 
1.1.1.5   root      558:     error_code = get_physical_address(env, &paddr, &prot, &access_index,
                    559:                                       address, rw, mmu_idx);
1.1       root      560:     if (error_code == 0) {
1.1.1.4   root      561:         virt_addr = address & TARGET_PAGE_MASK;
1.1.1.5   root      562:         vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
                    563:                              (TARGET_PAGE_SIZE - 1));
1.1       root      564: #ifdef DEBUG_MMU
1.1.1.5   root      565:         printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
                    566:                "\n", address, paddr, vaddr);
1.1       root      567: #endif
1.1.1.4   root      568:         ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
                    569:         return ret;
1.1       root      570:     }
                    571:     // XXX
                    572:     return 1;
                    573: }
                    574: 
                    575: #ifdef DEBUG_MMU
                    576: void dump_mmu(CPUState *env)
                    577: {
                    578:     unsigned int i;
                    579:     const char *mask;
                    580: 
1.1.1.5   root      581:     printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
1.1.1.7 ! root      582:            env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
1.1       root      583:     if ((env->lsu & DMMU_E) == 0) {
1.1.1.4   root      584:         printf("DMMU disabled\n");
1.1       root      585:     } else {
1.1.1.4   root      586:         printf("DMMU dump:\n");
                    587:         for (i = 0; i < 64; i++) {
1.1.1.7 ! root      588:             switch ((env->dtlb[i].tte >> 61) & 3) {
1.1.1.4   root      589:             default:
                    590:             case 0x0:
                    591:                 mask = "  8k";
                    592:                 break;
                    593:             case 0x1:
                    594:                 mask = " 64k";
                    595:                 break;
                    596:             case 0x2:
                    597:                 mask = "512k";
                    598:                 break;
                    599:             case 0x3:
                    600:                 mask = "  4M";
                    601:                 break;
                    602:             }
1.1.1.7 ! root      603:             if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
        !           604:                 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
        !           605:                        ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
        !           606:                        i,
        !           607:                        env->dtlb[i].tag & (uint64_t)~0x1fffULL,
        !           608:                        env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
1.1.1.4   root      609:                        mask,
1.1.1.7 ! root      610:                        env->dtlb[i].tte & 0x4? "priv": "user",
        !           611:                        env->dtlb[i].tte & 0x2? "RW": "RO",
        !           612:                        env->dtlb[i].tte & 0x40? "locked": "unlocked",
        !           613:                        env->dtlb[i].tag & (uint64_t)0x1fffULL,
        !           614:                        TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
1.1.1.4   root      615:             }
                    616:         }
1.1       root      617:     }
                    618:     if ((env->lsu & IMMU_E) == 0) {
1.1.1.4   root      619:         printf("IMMU disabled\n");
1.1       root      620:     } else {
1.1.1.4   root      621:         printf("IMMU dump:\n");
                    622:         for (i = 0; i < 64; i++) {
1.1.1.7 ! root      623:             switch ((env->itlb[i].tte >> 61) & 3) {
1.1.1.4   root      624:             default:
                    625:             case 0x0:
                    626:                 mask = "  8k";
                    627:                 break;
                    628:             case 0x1:
                    629:                 mask = " 64k";
                    630:                 break;
                    631:             case 0x2:
                    632:                 mask = "512k";
                    633:                 break;
                    634:             case 0x3:
                    635:                 mask = "  4M";
                    636:                 break;
                    637:             }
1.1.1.7 ! root      638:             if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
        !           639:                 printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
        !           640:                        ", %s, %s, %s, ctx %" PRId64 " %s\n",
        !           641:                        i,
        !           642:                        env->itlb[i].tag & (uint64_t)~0x1fffULL,
        !           643:                        env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
1.1.1.4   root      644:                        mask,
1.1.1.7 ! root      645:                        env->itlb[i].tte & 0x4? "priv": "user",
        !           646:                        env->itlb[i].tte & 0x40? "locked": "unlocked",
        !           647:                        env->itlb[i].tag & (uint64_t)0x1fffULL,
        !           648:                        TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
1.1.1.4   root      649:             }
                    650:         }
1.1       root      651:     }
                    652: }
1.1.1.2   root      653: #endif /* DEBUG_MMU */
                    654: 
                    655: #endif /* TARGET_SPARC64 */
                    656: #endif /* !CONFIG_USER_ONLY */
                    657: 
1.1.1.5   root      658: 
                    659: #if defined(CONFIG_USER_ONLY)
                    660: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1.1.1.2   root      661: {
1.1.1.5   root      662:     return addr;
1.1.1.2   root      663: }
1.1.1.4   root      664: 
1.1.1.5   root      665: #else
                    666: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
                    667: {
                    668:     target_phys_addr_t phys_addr;
                    669:     int prot, access_index;
                    670: 
                    671:     if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
                    672:                              MMU_KERNEL_IDX) != 0)
                    673:         if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
                    674:                                  0, MMU_KERNEL_IDX) != 0)
                    675:             return -1;
                    676:     if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
                    677:         return -1;
                    678:     return phys_addr;
                    679: }
1.1.1.4   root      680: #endif
                    681: 
1.1.1.5   root      682: void cpu_reset(CPUSPARCState *env)
1.1.1.4   root      683: {
1.1.1.5   root      684:     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
                    685:         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
                    686:         log_cpu_state(env, 0);
                    687:     }
                    688: 
                    689:     tlb_flush(env, 1);
                    690:     env->cwp = 0;
1.1.1.6   root      691: #ifndef TARGET_SPARC64
1.1.1.5   root      692:     env->wim = 1;
1.1.1.6   root      693: #endif
1.1.1.5   root      694:     env->regwptr = env->regbase + (env->cwp * 16);
1.1.1.7 ! root      695:     CC_OP = CC_OP_FLAGS;
1.1.1.5   root      696: #if defined(CONFIG_USER_ONLY)
                    697: #ifdef TARGET_SPARC64
                    698:     env->cleanwin = env->nwindows - 2;
                    699:     env->cansave = env->nwindows - 2;
                    700:     env->pstate = PS_RMO | PS_PEF | PS_IE;
                    701:     env->asi = 0x82; // Primary no-fault
                    702: #endif
                    703: #else
1.1.1.6   root      704: #if !defined(TARGET_SPARC64)
1.1.1.5   root      705:     env->psret = 0;
1.1.1.6   root      706: #endif
1.1.1.5   root      707:     env->psrs = 1;
                    708:     env->psrps = 1;
                    709: #ifdef TARGET_SPARC64
1.1.1.7 ! root      710:     env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
1.1.1.5   root      711:     env->hpstate = HS_PRIV;
1.1.1.7 ! root      712:     env->tl = env->maxtl;
        !           713:     cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
1.1.1.5   root      714:     env->lsu = 0;
                    715: #else
                    716:     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
                    717:     env->mmuregs[0] |= env->def->mmu_bm;
                    718: #endif
                    719:     env->pc = 0;
                    720:     env->npc = env->pc + 4;
1.1.1.4   root      721: #endif
                    722: }
                    723: 
1.1.1.5   root      724: static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
1.1.1.4   root      725: {
1.1.1.5   root      726:     sparc_def_t def1, *def = &def1;
                    727: 
                    728:     if (cpu_sparc_find_by_name(def, cpu_model) < 0)
                    729:         return -1;
                    730: 
                    731:     env->def = qemu_mallocz(sizeof(*def));
                    732:     memcpy(env->def, def, sizeof(*def));
                    733: #if defined(CONFIG_USER_ONLY)
                    734:     if ((env->def->features & CPU_FEATURE_FLOAT))
                    735:         env->def->features |= CPU_FEATURE_FLOAT128;
                    736: #endif
                    737:     env->cpu_model_str = cpu_model;
                    738:     env->version = def->iu_version;
                    739:     env->fsr = def->fpu_version;
                    740:     env->nwindows = def->nwindows;
                    741: #if !defined(TARGET_SPARC64)
                    742:     env->mmuregs[0] |= def->mmu_version;
                    743:     cpu_sparc_set_id(env, 0);
                    744:     env->mxccregs[7] |= def->mxcc_version;
1.1.1.4   root      745: #else
1.1.1.5   root      746:     env->mmu_version = def->mmu_version;
                    747:     env->maxtl = def->maxtl;
                    748:     env->version |= def->maxtl << 8;
                    749:     env->version |= def->nwindows - 1;
                    750: #endif
1.1.1.4   root      751:     return 0;
1.1.1.5   root      752: }
                    753: 
                    754: static void cpu_sparc_close(CPUSPARCState *env)
                    755: {
                    756:     free(env->def);
                    757:     free(env);
                    758: }
                    759: 
                    760: CPUSPARCState *cpu_sparc_init(const char *cpu_model)
                    761: {
                    762:     CPUSPARCState *env;
                    763: 
                    764:     env = qemu_mallocz(sizeof(CPUSPARCState));
                    765:     cpu_exec_init(env);
                    766: 
                    767:     gen_intermediate_code_init(env);
                    768: 
                    769:     if (cpu_sparc_register(env, cpu_model) < 0) {
                    770:         cpu_sparc_close(env);
                    771:         return NULL;
                    772:     }
1.1.1.6   root      773:     qemu_init_vcpu(env);
1.1.1.5   root      774: 
                    775:     return env;
                    776: }
                    777: 
                    778: void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
                    779: {
                    780: #if !defined(TARGET_SPARC64)
                    781:     env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
                    782: #endif
                    783: }
                    784: 
                    785: static const sparc_def_t sparc_defs[] = {
                    786: #ifdef TARGET_SPARC64
                    787:     {
                    788:         .name = "Fujitsu Sparc64",
                    789:         .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
                    790:         .fpu_version = 0x00000000,
                    791:         .mmu_version = mmu_us_12,
                    792:         .nwindows = 4,
                    793:         .maxtl = 4,
                    794:         .features = CPU_DEFAULT_FEATURES,
                    795:     },
                    796:     {
                    797:         .name = "Fujitsu Sparc64 III",
                    798:         .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
                    799:         .fpu_version = 0x00000000,
                    800:         .mmu_version = mmu_us_12,
                    801:         .nwindows = 5,
                    802:         .maxtl = 4,
                    803:         .features = CPU_DEFAULT_FEATURES,
                    804:     },
                    805:     {
                    806:         .name = "Fujitsu Sparc64 IV",
                    807:         .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
                    808:         .fpu_version = 0x00000000,
                    809:         .mmu_version = mmu_us_12,
                    810:         .nwindows = 8,
                    811:         .maxtl = 5,
                    812:         .features = CPU_DEFAULT_FEATURES,
                    813:     },
                    814:     {
                    815:         .name = "Fujitsu Sparc64 V",
                    816:         .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
                    817:         .fpu_version = 0x00000000,
                    818:         .mmu_version = mmu_us_12,
                    819:         .nwindows = 8,
                    820:         .maxtl = 5,
                    821:         .features = CPU_DEFAULT_FEATURES,
                    822:     },
                    823:     {
                    824:         .name = "TI UltraSparc I",
                    825:         .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
                    826:         .fpu_version = 0x00000000,
                    827:         .mmu_version = mmu_us_12,
                    828:         .nwindows = 8,
                    829:         .maxtl = 5,
                    830:         .features = CPU_DEFAULT_FEATURES,
                    831:     },
                    832:     {
                    833:         .name = "TI UltraSparc II",
                    834:         .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
                    835:         .fpu_version = 0x00000000,
                    836:         .mmu_version = mmu_us_12,
                    837:         .nwindows = 8,
                    838:         .maxtl = 5,
                    839:         .features = CPU_DEFAULT_FEATURES,
                    840:     },
                    841:     {
                    842:         .name = "TI UltraSparc IIi",
                    843:         .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
                    844:         .fpu_version = 0x00000000,
                    845:         .mmu_version = mmu_us_12,
                    846:         .nwindows = 8,
                    847:         .maxtl = 5,
                    848:         .features = CPU_DEFAULT_FEATURES,
                    849:     },
                    850:     {
                    851:         .name = "TI UltraSparc IIe",
                    852:         .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
                    853:         .fpu_version = 0x00000000,
                    854:         .mmu_version = mmu_us_12,
                    855:         .nwindows = 8,
                    856:         .maxtl = 5,
                    857:         .features = CPU_DEFAULT_FEATURES,
                    858:     },
                    859:     {
                    860:         .name = "Sun UltraSparc III",
                    861:         .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
                    862:         .fpu_version = 0x00000000,
                    863:         .mmu_version = mmu_us_12,
                    864:         .nwindows = 8,
                    865:         .maxtl = 5,
                    866:         .features = CPU_DEFAULT_FEATURES,
                    867:     },
                    868:     {
                    869:         .name = "Sun UltraSparc III Cu",
                    870:         .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
                    871:         .fpu_version = 0x00000000,
                    872:         .mmu_version = mmu_us_3,
                    873:         .nwindows = 8,
                    874:         .maxtl = 5,
                    875:         .features = CPU_DEFAULT_FEATURES,
                    876:     },
                    877:     {
                    878:         .name = "Sun UltraSparc IIIi",
                    879:         .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
                    880:         .fpu_version = 0x00000000,
                    881:         .mmu_version = mmu_us_12,
                    882:         .nwindows = 8,
                    883:         .maxtl = 5,
                    884:         .features = CPU_DEFAULT_FEATURES,
                    885:     },
                    886:     {
                    887:         .name = "Sun UltraSparc IV",
                    888:         .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
                    889:         .fpu_version = 0x00000000,
                    890:         .mmu_version = mmu_us_4,
                    891:         .nwindows = 8,
                    892:         .maxtl = 5,
                    893:         .features = CPU_DEFAULT_FEATURES,
                    894:     },
                    895:     {
                    896:         .name = "Sun UltraSparc IV+",
                    897:         .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
                    898:         .fpu_version = 0x00000000,
                    899:         .mmu_version = mmu_us_12,
                    900:         .nwindows = 8,
                    901:         .maxtl = 5,
                    902:         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
                    903:     },
                    904:     {
                    905:         .name = "Sun UltraSparc IIIi+",
                    906:         .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
                    907:         .fpu_version = 0x00000000,
                    908:         .mmu_version = mmu_us_3,
                    909:         .nwindows = 8,
                    910:         .maxtl = 5,
                    911:         .features = CPU_DEFAULT_FEATURES,
                    912:     },
                    913:     {
                    914:         .name = "Sun UltraSparc T1",
                    915:         // defined in sparc_ifu_fdp.v and ctu.h
                    916:         .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
                    917:         .fpu_version = 0x00000000,
                    918:         .mmu_version = mmu_sun4v,
                    919:         .nwindows = 8,
                    920:         .maxtl = 6,
                    921:         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
                    922:         | CPU_FEATURE_GL,
                    923:     },
                    924:     {
                    925:         .name = "Sun UltraSparc T2",
                    926:         // defined in tlu_asi_ctl.v and n2_revid_cust.v
                    927:         .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
                    928:         .fpu_version = 0x00000000,
                    929:         .mmu_version = mmu_sun4v,
                    930:         .nwindows = 8,
                    931:         .maxtl = 6,
                    932:         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
                    933:         | CPU_FEATURE_GL,
                    934:     },
                    935:     {
                    936:         .name = "NEC UltraSparc I",
                    937:         .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
                    938:         .fpu_version = 0x00000000,
                    939:         .mmu_version = mmu_us_12,
                    940:         .nwindows = 8,
                    941:         .maxtl = 5,
                    942:         .features = CPU_DEFAULT_FEATURES,
                    943:     },
                    944: #else
                    945:     {
                    946:         .name = "Fujitsu MB86900",
                    947:         .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
                    948:         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
                    949:         .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
                    950:         .mmu_bm = 0x00004000,
                    951:         .mmu_ctpr_mask = 0x007ffff0,
                    952:         .mmu_cxr_mask = 0x0000003f,
                    953:         .mmu_sfsr_mask = 0xffffffff,
                    954:         .mmu_trcr_mask = 0xffffffff,
                    955:         .nwindows = 7,
                    956:         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
                    957:     },
                    958:     {
                    959:         .name = "Fujitsu MB86904",
                    960:         .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
                    961:         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
                    962:         .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
                    963:         .mmu_bm = 0x00004000,
                    964:         .mmu_ctpr_mask = 0x00ffffc0,
                    965:         .mmu_cxr_mask = 0x000000ff,
                    966:         .mmu_sfsr_mask = 0x00016fff,
                    967:         .mmu_trcr_mask = 0x00ffffff,
                    968:         .nwindows = 8,
                    969:         .features = CPU_DEFAULT_FEATURES,
                    970:     },
                    971:     {
                    972:         .name = "Fujitsu MB86907",
                    973:         .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
                    974:         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
                    975:         .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
                    976:         .mmu_bm = 0x00004000,
                    977:         .mmu_ctpr_mask = 0xffffffc0,
                    978:         .mmu_cxr_mask = 0x000000ff,
                    979:         .mmu_sfsr_mask = 0x00016fff,
                    980:         .mmu_trcr_mask = 0xffffffff,
                    981:         .nwindows = 8,
                    982:         .features = CPU_DEFAULT_FEATURES,
                    983:     },
                    984:     {
                    985:         .name = "LSI L64811",
                    986:         .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
                    987:         .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
                    988:         .mmu_version = 0x10 << 24,
                    989:         .mmu_bm = 0x00004000,
                    990:         .mmu_ctpr_mask = 0x007ffff0,
                    991:         .mmu_cxr_mask = 0x0000003f,
                    992:         .mmu_sfsr_mask = 0xffffffff,
                    993:         .mmu_trcr_mask = 0xffffffff,
                    994:         .nwindows = 8,
                    995:         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
                    996:         CPU_FEATURE_FSMULD,
                    997:     },
                    998:     {
                    999:         .name = "Cypress CY7C601",
                   1000:         .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
                   1001:         .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
                   1002:         .mmu_version = 0x10 << 24,
                   1003:         .mmu_bm = 0x00004000,
                   1004:         .mmu_ctpr_mask = 0x007ffff0,
                   1005:         .mmu_cxr_mask = 0x0000003f,
                   1006:         .mmu_sfsr_mask = 0xffffffff,
                   1007:         .mmu_trcr_mask = 0xffffffff,
                   1008:         .nwindows = 8,
                   1009:         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
                   1010:         CPU_FEATURE_FSMULD,
                   1011:     },
                   1012:     {
                   1013:         .name = "Cypress CY7C611",
                   1014:         .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
                   1015:         .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
                   1016:         .mmu_version = 0x10 << 24,
                   1017:         .mmu_bm = 0x00004000,
                   1018:         .mmu_ctpr_mask = 0x007ffff0,
                   1019:         .mmu_cxr_mask = 0x0000003f,
                   1020:         .mmu_sfsr_mask = 0xffffffff,
                   1021:         .mmu_trcr_mask = 0xffffffff,
                   1022:         .nwindows = 8,
                   1023:         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
                   1024:         CPU_FEATURE_FSMULD,
                   1025:     },
                   1026:     {
                   1027:         .name = "TI MicroSparc I",
                   1028:         .iu_version = 0x41000000,
                   1029:         .fpu_version = 4 << 17,
                   1030:         .mmu_version = 0x41000000,
                   1031:         .mmu_bm = 0x00004000,
                   1032:         .mmu_ctpr_mask = 0x007ffff0,
                   1033:         .mmu_cxr_mask = 0x0000003f,
                   1034:         .mmu_sfsr_mask = 0x00016fff,
                   1035:         .mmu_trcr_mask = 0x0000003f,
                   1036:         .nwindows = 7,
                   1037:         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
                   1038:         CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
                   1039:         CPU_FEATURE_FMUL,
                   1040:     },
                   1041:     {
                   1042:         .name = "TI MicroSparc II",
                   1043:         .iu_version = 0x42000000,
                   1044:         .fpu_version = 4 << 17,
                   1045:         .mmu_version = 0x02000000,
                   1046:         .mmu_bm = 0x00004000,
                   1047:         .mmu_ctpr_mask = 0x00ffffc0,
                   1048:         .mmu_cxr_mask = 0x000000ff,
                   1049:         .mmu_sfsr_mask = 0x00016fff,
                   1050:         .mmu_trcr_mask = 0x00ffffff,
                   1051:         .nwindows = 8,
                   1052:         .features = CPU_DEFAULT_FEATURES,
                   1053:     },
                   1054:     {
                   1055:         .name = "TI MicroSparc IIep",
                   1056:         .iu_version = 0x42000000,
                   1057:         .fpu_version = 4 << 17,
                   1058:         .mmu_version = 0x04000000,
                   1059:         .mmu_bm = 0x00004000,
                   1060:         .mmu_ctpr_mask = 0x00ffffc0,
                   1061:         .mmu_cxr_mask = 0x000000ff,
                   1062:         .mmu_sfsr_mask = 0x00016bff,
                   1063:         .mmu_trcr_mask = 0x00ffffff,
                   1064:         .nwindows = 8,
                   1065:         .features = CPU_DEFAULT_FEATURES,
                   1066:     },
                   1067:     {
                   1068:         .name = "TI SuperSparc 40", // STP1020NPGA
                   1069:         .iu_version = 0x41000000, // SuperSPARC 2.x
                   1070:         .fpu_version = 0 << 17,
                   1071:         .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
                   1072:         .mmu_bm = 0x00002000,
                   1073:         .mmu_ctpr_mask = 0xffffffc0,
                   1074:         .mmu_cxr_mask = 0x0000ffff,
                   1075:         .mmu_sfsr_mask = 0xffffffff,
                   1076:         .mmu_trcr_mask = 0xffffffff,
                   1077:         .nwindows = 8,
                   1078:         .features = CPU_DEFAULT_FEATURES,
                   1079:     },
                   1080:     {
                   1081:         .name = "TI SuperSparc 50", // STP1020PGA
                   1082:         .iu_version = 0x40000000, // SuperSPARC 3.x
                   1083:         .fpu_version = 0 << 17,
                   1084:         .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
                   1085:         .mmu_bm = 0x00002000,
                   1086:         .mmu_ctpr_mask = 0xffffffc0,
                   1087:         .mmu_cxr_mask = 0x0000ffff,
                   1088:         .mmu_sfsr_mask = 0xffffffff,
                   1089:         .mmu_trcr_mask = 0xffffffff,
                   1090:         .nwindows = 8,
                   1091:         .features = CPU_DEFAULT_FEATURES,
                   1092:     },
                   1093:     {
                   1094:         .name = "TI SuperSparc 51",
                   1095:         .iu_version = 0x40000000, // SuperSPARC 3.x
                   1096:         .fpu_version = 0 << 17,
                   1097:         .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
                   1098:         .mmu_bm = 0x00002000,
                   1099:         .mmu_ctpr_mask = 0xffffffc0,
                   1100:         .mmu_cxr_mask = 0x0000ffff,
                   1101:         .mmu_sfsr_mask = 0xffffffff,
                   1102:         .mmu_trcr_mask = 0xffffffff,
                   1103:         .mxcc_version = 0x00000104,
                   1104:         .nwindows = 8,
                   1105:         .features = CPU_DEFAULT_FEATURES,
                   1106:     },
                   1107:     {
                   1108:         .name = "TI SuperSparc 60", // STP1020APGA
                   1109:         .iu_version = 0x40000000, // SuperSPARC 3.x
                   1110:         .fpu_version = 0 << 17,
                   1111:         .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
                   1112:         .mmu_bm = 0x00002000,
                   1113:         .mmu_ctpr_mask = 0xffffffc0,
                   1114:         .mmu_cxr_mask = 0x0000ffff,
                   1115:         .mmu_sfsr_mask = 0xffffffff,
                   1116:         .mmu_trcr_mask = 0xffffffff,
                   1117:         .nwindows = 8,
                   1118:         .features = CPU_DEFAULT_FEATURES,
                   1119:     },
                   1120:     {
                   1121:         .name = "TI SuperSparc 61",
                   1122:         .iu_version = 0x44000000, // SuperSPARC 3.x
                   1123:         .fpu_version = 0 << 17,
                   1124:         .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
                   1125:         .mmu_bm = 0x00002000,
                   1126:         .mmu_ctpr_mask = 0xffffffc0,
                   1127:         .mmu_cxr_mask = 0x0000ffff,
                   1128:         .mmu_sfsr_mask = 0xffffffff,
                   1129:         .mmu_trcr_mask = 0xffffffff,
                   1130:         .mxcc_version = 0x00000104,
                   1131:         .nwindows = 8,
                   1132:         .features = CPU_DEFAULT_FEATURES,
                   1133:     },
                   1134:     {
                   1135:         .name = "TI SuperSparc II",
                   1136:         .iu_version = 0x40000000, // SuperSPARC II 1.x
                   1137:         .fpu_version = 0 << 17,
                   1138:         .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
                   1139:         .mmu_bm = 0x00002000,
                   1140:         .mmu_ctpr_mask = 0xffffffc0,
                   1141:         .mmu_cxr_mask = 0x0000ffff,
                   1142:         .mmu_sfsr_mask = 0xffffffff,
                   1143:         .mmu_trcr_mask = 0xffffffff,
                   1144:         .mxcc_version = 0x00000104,
                   1145:         .nwindows = 8,
                   1146:         .features = CPU_DEFAULT_FEATURES,
                   1147:     },
                   1148:     {
                   1149:         .name = "Ross RT625",
                   1150:         .iu_version = 0x1e000000,
                   1151:         .fpu_version = 1 << 17,
                   1152:         .mmu_version = 0x1e000000,
                   1153:         .mmu_bm = 0x00004000,
                   1154:         .mmu_ctpr_mask = 0x007ffff0,
                   1155:         .mmu_cxr_mask = 0x0000003f,
                   1156:         .mmu_sfsr_mask = 0xffffffff,
                   1157:         .mmu_trcr_mask = 0xffffffff,
                   1158:         .nwindows = 8,
                   1159:         .features = CPU_DEFAULT_FEATURES,
                   1160:     },
                   1161:     {
                   1162:         .name = "Ross RT620",
                   1163:         .iu_version = 0x1f000000,
                   1164:         .fpu_version = 1 << 17,
                   1165:         .mmu_version = 0x1f000000,
                   1166:         .mmu_bm = 0x00004000,
                   1167:         .mmu_ctpr_mask = 0x007ffff0,
                   1168:         .mmu_cxr_mask = 0x0000003f,
                   1169:         .mmu_sfsr_mask = 0xffffffff,
                   1170:         .mmu_trcr_mask = 0xffffffff,
                   1171:         .nwindows = 8,
                   1172:         .features = CPU_DEFAULT_FEATURES,
                   1173:     },
                   1174:     {
                   1175:         .name = "BIT B5010",
                   1176:         .iu_version = 0x20000000,
                   1177:         .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
                   1178:         .mmu_version = 0x20000000,
                   1179:         .mmu_bm = 0x00004000,
                   1180:         .mmu_ctpr_mask = 0x007ffff0,
                   1181:         .mmu_cxr_mask = 0x0000003f,
                   1182:         .mmu_sfsr_mask = 0xffffffff,
                   1183:         .mmu_trcr_mask = 0xffffffff,
                   1184:         .nwindows = 8,
                   1185:         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
                   1186:         CPU_FEATURE_FSMULD,
                   1187:     },
                   1188:     {
                   1189:         .name = "Matsushita MN10501",
                   1190:         .iu_version = 0x50000000,
                   1191:         .fpu_version = 0 << 17,
                   1192:         .mmu_version = 0x50000000,
                   1193:         .mmu_bm = 0x00004000,
                   1194:         .mmu_ctpr_mask = 0x007ffff0,
                   1195:         .mmu_cxr_mask = 0x0000003f,
                   1196:         .mmu_sfsr_mask = 0xffffffff,
                   1197:         .mmu_trcr_mask = 0xffffffff,
                   1198:         .nwindows = 8,
                   1199:         .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
                   1200:         CPU_FEATURE_FSMULD,
                   1201:     },
                   1202:     {
                   1203:         .name = "Weitek W8601",
                   1204:         .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
                   1205:         .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
                   1206:         .mmu_version = 0x10 << 24,
                   1207:         .mmu_bm = 0x00004000,
                   1208:         .mmu_ctpr_mask = 0x007ffff0,
                   1209:         .mmu_cxr_mask = 0x0000003f,
                   1210:         .mmu_sfsr_mask = 0xffffffff,
                   1211:         .mmu_trcr_mask = 0xffffffff,
                   1212:         .nwindows = 8,
                   1213:         .features = CPU_DEFAULT_FEATURES,
                   1214:     },
                   1215:     {
                   1216:         .name = "LEON2",
                   1217:         .iu_version = 0xf2000000,
                   1218:         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
                   1219:         .mmu_version = 0xf2000000,
                   1220:         .mmu_bm = 0x00004000,
                   1221:         .mmu_ctpr_mask = 0x007ffff0,
                   1222:         .mmu_cxr_mask = 0x0000003f,
                   1223:         .mmu_sfsr_mask = 0xffffffff,
                   1224:         .mmu_trcr_mask = 0xffffffff,
                   1225:         .nwindows = 8,
                   1226:         .features = CPU_DEFAULT_FEATURES,
                   1227:     },
                   1228:     {
                   1229:         .name = "LEON3",
                   1230:         .iu_version = 0xf3000000,
                   1231:         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
                   1232:         .mmu_version = 0xf3000000,
                   1233:         .mmu_bm = 0x00004000,
                   1234:         .mmu_ctpr_mask = 0x007ffff0,
                   1235:         .mmu_cxr_mask = 0x0000003f,
                   1236:         .mmu_sfsr_mask = 0xffffffff,
                   1237:         .mmu_trcr_mask = 0xffffffff,
                   1238:         .nwindows = 8,
                   1239:         .features = CPU_DEFAULT_FEATURES,
                   1240:     },
1.1.1.4   root     1241: #endif
1.1.1.5   root     1242: };
                   1243: 
                   1244: static const char * const feature_name[] = {
                   1245:     "float",
                   1246:     "float128",
                   1247:     "swap",
                   1248:     "mul",
                   1249:     "div",
                   1250:     "flush",
                   1251:     "fsqrt",
                   1252:     "fmul",
                   1253:     "vis1",
                   1254:     "vis2",
                   1255:     "fsmuld",
                   1256:     "hypv",
                   1257:     "cmt",
                   1258:     "gl",
                   1259: };
                   1260: 
                   1261: static void print_features(FILE *f,
                   1262:                            int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                   1263:                            uint32_t features, const char *prefix)
                   1264: {
                   1265:     unsigned int i;
                   1266: 
                   1267:     for (i = 0; i < ARRAY_SIZE(feature_name); i++)
                   1268:         if (feature_name[i] && (features & (1 << i))) {
                   1269:             if (prefix)
                   1270:                 (*cpu_fprintf)(f, "%s", prefix);
                   1271:             (*cpu_fprintf)(f, "%s ", feature_name[i]);
                   1272:         }
1.1.1.4   root     1273: }
                   1274: 
1.1.1.5   root     1275: static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
1.1.1.4   root     1276: {
1.1.1.5   root     1277:     unsigned int i;
                   1278: 
                   1279:     for (i = 0; i < ARRAY_SIZE(feature_name); i++)
                   1280:         if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
                   1281:             *features |= 1 << i;
                   1282:             return;
                   1283:         }
                   1284:     fprintf(stderr, "CPU feature %s not found\n", flagname);
                   1285: }
                   1286: 
                   1287: static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
                   1288: {
                   1289:     unsigned int i;
                   1290:     const sparc_def_t *def = NULL;
                   1291:     char *s = strdup(cpu_model);
                   1292:     char *featurestr, *name = strtok(s, ",");
                   1293:     uint32_t plus_features = 0;
                   1294:     uint32_t minus_features = 0;
                   1295:     long long iu_version;
                   1296:     uint32_t fpu_version, mmu_version, nwindows;
                   1297: 
                   1298:     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
                   1299:         if (strcasecmp(name, sparc_defs[i].name) == 0) {
                   1300:             def = &sparc_defs[i];
                   1301:         }
                   1302:     }
                   1303:     if (!def)
                   1304:         goto error;
                   1305:     memcpy(cpu_def, def, sizeof(*def));
                   1306: 
                   1307:     featurestr = strtok(NULL, ",");
                   1308:     while (featurestr) {
                   1309:         char *val;
                   1310: 
                   1311:         if (featurestr[0] == '+') {
                   1312:             add_flagname_to_bitmaps(featurestr + 1, &plus_features);
                   1313:         } else if (featurestr[0] == '-') {
                   1314:             add_flagname_to_bitmaps(featurestr + 1, &minus_features);
                   1315:         } else if ((val = strchr(featurestr, '='))) {
                   1316:             *val = 0; val++;
                   1317:             if (!strcmp(featurestr, "iu_version")) {
                   1318:                 char *err;
                   1319: 
                   1320:                 iu_version = strtoll(val, &err, 0);
                   1321:                 if (!*val || *err) {
                   1322:                     fprintf(stderr, "bad numerical value %s\n", val);
                   1323:                     goto error;
                   1324:                 }
                   1325:                 cpu_def->iu_version = iu_version;
                   1326: #ifdef DEBUG_FEATURES
                   1327:                 fprintf(stderr, "iu_version %llx\n", iu_version);
                   1328: #endif
                   1329:             } else if (!strcmp(featurestr, "fpu_version")) {
                   1330:                 char *err;
                   1331: 
                   1332:                 fpu_version = strtol(val, &err, 0);
                   1333:                 if (!*val || *err) {
                   1334:                     fprintf(stderr, "bad numerical value %s\n", val);
                   1335:                     goto error;
                   1336:                 }
                   1337:                 cpu_def->fpu_version = fpu_version;
                   1338: #ifdef DEBUG_FEATURES
1.1.1.6   root     1339:                 fprintf(stderr, "fpu_version %x\n", fpu_version);
1.1.1.5   root     1340: #endif
                   1341:             } else if (!strcmp(featurestr, "mmu_version")) {
                   1342:                 char *err;
                   1343: 
                   1344:                 mmu_version = strtol(val, &err, 0);
                   1345:                 if (!*val || *err) {
                   1346:                     fprintf(stderr, "bad numerical value %s\n", val);
                   1347:                     goto error;
                   1348:                 }
                   1349:                 cpu_def->mmu_version = mmu_version;
                   1350: #ifdef DEBUG_FEATURES
1.1.1.6   root     1351:                 fprintf(stderr, "mmu_version %x\n", mmu_version);
1.1.1.5   root     1352: #endif
                   1353:             } else if (!strcmp(featurestr, "nwindows")) {
                   1354:                 char *err;
                   1355: 
                   1356:                 nwindows = strtol(val, &err, 0);
                   1357:                 if (!*val || *err || nwindows > MAX_NWINDOWS ||
                   1358:                     nwindows < MIN_NWINDOWS) {
                   1359:                     fprintf(stderr, "bad numerical value %s\n", val);
                   1360:                     goto error;
                   1361:                 }
                   1362:                 cpu_def->nwindows = nwindows;
                   1363: #ifdef DEBUG_FEATURES
                   1364:                 fprintf(stderr, "nwindows %d\n", nwindows);
1.1.1.4   root     1365: #endif
1.1.1.5   root     1366:             } else {
                   1367:                 fprintf(stderr, "unrecognized feature %s\n", featurestr);
                   1368:                 goto error;
                   1369:             }
                   1370:         } else {
                   1371:             fprintf(stderr, "feature string `%s' not in format "
                   1372:                     "(+feature|-feature|feature=xyz)\n", featurestr);
                   1373:             goto error;
                   1374:         }
                   1375:         featurestr = strtok(NULL, ",");
                   1376:     }
                   1377:     cpu_def->features |= plus_features;
                   1378:     cpu_def->features &= ~minus_features;
                   1379: #ifdef DEBUG_FEATURES
                   1380:     print_features(stderr, fprintf, cpu_def->features, NULL);
                   1381: #endif
                   1382:     free(s);
                   1383:     return 0;
                   1384: 
                   1385:  error:
                   1386:     free(s);
                   1387:     return -1;
1.1.1.4   root     1388: }
1.1.1.5   root     1389: 
                   1390: void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
                   1391: {
                   1392:     unsigned int i;
                   1393: 
                   1394:     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
                   1395:         (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
                   1396:                        sparc_defs[i].name,
                   1397:                        sparc_defs[i].iu_version,
                   1398:                        sparc_defs[i].fpu_version,
                   1399:                        sparc_defs[i].mmu_version,
                   1400:                        sparc_defs[i].nwindows);
                   1401:         print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
                   1402:                        ~sparc_defs[i].features, "-");
                   1403:         print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
                   1404:                        sparc_defs[i].features, "+");
                   1405:         (*cpu_fprintf)(f, "\n");
                   1406:     }
                   1407:     (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
                   1408:     print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
                   1409:     (*cpu_fprintf)(f, "\n");
                   1410:     (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
                   1411:     print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
                   1412:     (*cpu_fprintf)(f, "\n");
                   1413:     (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
                   1414:                    "fpu_version mmu_version nwindows\n");
                   1415: }
                   1416: 
                   1417: void cpu_dump_state(CPUState *env, FILE *f,
                   1418:                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                   1419:                     int flags)
                   1420: {
                   1421:     int i, x;
                   1422: 
                   1423:     cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
                   1424:                 env->npc);
                   1425:     cpu_fprintf(f, "General Registers:\n");
                   1426:     for (i = 0; i < 4; i++)
                   1427:         cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
                   1428:     cpu_fprintf(f, "\n");
                   1429:     for (; i < 8; i++)
                   1430:         cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
                   1431:     cpu_fprintf(f, "\nCurrent Register Window:\n");
                   1432:     for (x = 0; x < 3; x++) {
                   1433:         for (i = 0; i < 4; i++)
                   1434:             cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
                   1435:                     (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
                   1436:                     env->regwptr[i + x * 8]);
                   1437:         cpu_fprintf(f, "\n");
                   1438:         for (; i < 8; i++)
                   1439:             cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
                   1440:                     (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
                   1441:                     env->regwptr[i + x * 8]);
                   1442:         cpu_fprintf(f, "\n");
                   1443:     }
                   1444:     cpu_fprintf(f, "\nFloating Point Registers:\n");
                   1445:     for (i = 0; i < 32; i++) {
                   1446:         if ((i & 3) == 0)
                   1447:             cpu_fprintf(f, "%%f%02d:", i);
                   1448:         cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
                   1449:         if ((i & 3) == 3)
                   1450:             cpu_fprintf(f, "\n");
                   1451:     }
                   1452: #ifdef TARGET_SPARC64
                   1453:     cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
                   1454:                 env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
                   1455:     cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
                   1456:                 "cleanwin %d cwp %d\n",
                   1457:                 env->cansave, env->canrestore, env->otherwin, env->wstate,
                   1458:                 env->cleanwin, env->nwindows - 1 - env->cwp);
                   1459: #else
1.1.1.6   root     1460: 
                   1461: #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
                   1462: 
1.1.1.5   root     1463:     cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
                   1464:                 GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
                   1465:                 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
                   1466:                 env->psrs?'S':'-', env->psrps?'P':'-',
                   1467:                 env->psret?'E':'-', env->wim);
1.1.1.4   root     1468: #endif
1.1.1.5   root     1469:     cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
                   1470: }

unix.superglobalmegacorp.com

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