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