]> git.proxmox.com Git - qemu.git/blobdiff - target-sparc/helper.c
audio: fix comment
[qemu.git] / target-sparc / helper.c
index 04513f82d55a88c7ea9301dfe91957a565c3d313..ffe93e3d44dd216f9ed5798c32a05b028733b072 100644 (file)
@@ -107,12 +107,10 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
     int access_perms = 0;
     target_phys_addr_t pde_ptr;
     uint32_t pde;
-    target_ulong virt_addr;
     int error_code = 0, is_dirty, is_user;
     unsigned long page_offset;
 
     is_user = mmu_idx == MMU_USER_IDX;
-    virt_addr = address & TARGET_PAGE_MASK;
 
     if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
         // Boot mode: instruction fetches are taken from PROM
@@ -174,22 +172,25 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
                 case 3: /* Reserved */
                     return (3 << 8) | (4 << 2);
                 case 2: /* L3 PTE */
-                    virt_addr = address & TARGET_PAGE_MASK;
                     page_offset = (address & TARGET_PAGE_MASK) &
                         (TARGET_PAGE_SIZE - 1);
                 }
                 break;
             case 2: /* L2 PTE */
-                virt_addr = address & ~0x3ffff;
                 page_offset = address & 0x3ffff;
             }
             break;
         case 2: /* L1 PTE */
-            virt_addr = address & ~0xffffff;
             page_offset = address & 0xffffff;
         }
     }
 
+    /* check access */
+    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
+    error_code = access_table[*access_index][access_perms];
+    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
+        return error_code;
+
     /* update page modified and dirty bits */
     is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
     if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
@@ -198,11 +199,6 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
             pde |= PG_MODIFIED_MASK;
         stl_phys_notdirty(pde_ptr, pde);
     }
-    /* check access */
-    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
-    error_code = access_table[*access_index][access_perms];
-    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
-        return error_code;
 
     /* the page can be put in the TLB */
     *prot = perm_table[is_user][access_perms];
@@ -386,13 +382,14 @@ static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
 
 // Returns true if TTE tag is valid and matches virtual address value in context
 // requires virtual address mask value calculated from TTE entry size
-static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte,
+static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
                                        uint64_t address, uint64_t context,
-                                       target_phys_addr_t *physical)
+                                       target_phys_addr_t *physical,
+                                       int is_nucleus)
 {
     uint64_t mask;
 
-    switch ((tlb_tte >> 61) & 3) {
+    switch ((tlb->tte >> 61) & 3) {
     default:
     case 0x0: // 8k
         mask = 0xffffffffffffe000ULL;
@@ -409,12 +406,13 @@ static inline int ultrasparc_tag_match(uint64_t tlb_tag, uint64_t tlb_tte,
     }
 
     // valid, context match, virtual address match?
-    if ((tlb_tte & 0x8000000000000000ULL) &&
-            compare_masked(context, tlb_tag, 0x1fff) &&
-            compare_masked(address, tlb_tag, mask))
+    if (TTE_IS_VALID(tlb->tte) &&
+        ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
+         || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag, 0x1fff))
+        && compare_masked(address, tlb->tag, mask))
     {
         // decode physical address
-        *physical = ((tlb_tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
+        *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
         return 1;
     }
 
@@ -427,6 +425,7 @@ static int get_physical_address_data(CPUState *env,
 {
     unsigned int i;
     uint64_t context;
+    int is_nucleus;
 
     if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
         *physical = ultrasparc_truncate_physical(address);
@@ -434,21 +433,32 @@ static int get_physical_address_data(CPUState *env,
         return 0;
     }
 
-    context = env->dmmuregs[1] & 0x1fff;
+    context = env->dmmu.mmu_primary_context & 0x1fff;
+    is_nucleus = env->tl > 0;
 
     for (i = 0; i < 64; i++) {
         // ctx match, vaddr match, valid?
-        if (ultrasparc_tag_match(env->dtlb_tag[i], env->dtlb_tte[i],
-                                 address, context, physical)
-        ) {
+        if (ultrasparc_tag_match(&env->dtlb[i],
+                                 address, context, physical,
+                                 is_nucleus)) {
             // access ok?
-            if (((env->dtlb_tte[i] & 0x4) && is_user) ||
-                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
-                if (env->dmmuregs[3]) /* Fault status register */
-                    env->dmmuregs[3] = 2; /* overflow (not read before
+            if (((env->dtlb[i].tte & 0x4) && is_user) ||
+                (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
+                uint8_t fault_type = 0;
+
+                if ((env->dtlb[i].tte & 0x4) && is_user) {
+                    fault_type |= 1; /* privilege violation */
+                }
+
+                if (env->dmmu.sfsr & 1) /* Fault status register */
+                    env->dmmu.sfsr = 2; /* overflow (not read before
                                              another fault) */
-                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
-                env->dmmuregs[4] = address; /* Fault address register */
+
+                env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
+
+                env->dmmu.sfsr |= (fault_type << 7);
+
+                env->dmmu.sfar = address; /* Fault address register */
                 env->exception_index = TT_DFAULT;
 #ifdef DEBUG_MMU
                 printf("DFAULT at 0x%" PRIx64 "\n", address);
@@ -456,15 +466,16 @@ static int get_physical_address_data(CPUState *env,
                 return 1;
             }
             *prot = PAGE_READ;
-            if (env->dtlb_tte[i] & 0x2)
+            if (env->dtlb[i].tte & 0x2)
                 *prot |= PAGE_WRITE;
+            TTE_SET_USED(env->dtlb[i].tte);
             return 0;
         }
     }
 #ifdef DEBUG_MMU
     printf("DMISS at 0x%" PRIx64 "\n", address);
 #endif
-    env->dmmuregs[6] = (address & ~0x1fffULL) | context;
+    env->dmmu.tag_access = (address & ~0x1fffULL) | context;
     env->exception_index = TT_DMISS;
     return 1;
 }
@@ -475,6 +486,7 @@ static int get_physical_address_code(CPUState *env,
 {
     unsigned int i;
     uint64_t context;
+    int is_nucleus;
 
     if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
         /* IMMU disabled */
@@ -483,19 +495,20 @@ static int get_physical_address_code(CPUState *env,
         return 0;
     }
 
-    context = env->dmmuregs[1] & 0x1fff;
+    context = env->dmmu.mmu_primary_context & 0x1fff;
+    is_nucleus = env->tl > 0;
 
     for (i = 0; i < 64; i++) {
         // ctx match, vaddr match, valid?
-        if (ultrasparc_tag_match(env->itlb_tag[i], env->itlb_tte[i],
-                                 address, context, physical)
-        ) {
+        if (ultrasparc_tag_match(&env->itlb[i],
+                                 address, context, physical,
+                                 is_nucleus)) {
             // access ok?
-            if ((env->itlb_tte[i] & 0x4) && is_user) {
-                if (env->immuregs[3]) /* Fault status register */
-                    env->immuregs[3] = 2; /* overflow (not read before
+            if ((env->itlb[i].tte & 0x4) && is_user) {
+                if (env->immu.sfsr) /* Fault status register */
+                    env->immu.sfsr = 2; /* overflow (not read before
                                              another fault) */
-                env->immuregs[3] |= (is_user << 3) | 1;
+                env->immu.sfsr |= (is_user << 3) | 1;
                 env->exception_index = TT_TFAULT;
 #ifdef DEBUG_MMU
                 printf("TFAULT at 0x%" PRIx64 "\n", address);
@@ -503,6 +516,7 @@ static int get_physical_address_code(CPUState *env,
                 return 1;
             }
             *prot = PAGE_EXEC;
+            TTE_SET_USED(env->itlb[i].tte);
             return 0;
         }
     }
@@ -510,7 +524,7 @@ static int get_physical_address_code(CPUState *env,
     printf("TMISS at 0x%" PRIx64 "\n", address);
 #endif
     /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
-    env->immuregs[6] = (address & ~0x1fffULL) | context;
+    env->immu.tag_access = (address & ~0x1fffULL) | context;
     env->exception_index = TT_TMISS;
     return 1;
 }
@@ -561,13 +575,13 @@ void dump_mmu(CPUState *env)
     const char *mask;
 
     printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
-           env->dmmuregs[1], env->dmmuregs[2]);
+           env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
     if ((env->lsu & DMMU_E) == 0) {
         printf("DMMU disabled\n");
     } else {
         printf("DMMU dump:\n");
         for (i = 0; i < 64; i++) {
-            switch ((env->dtlb_tte[i] >> 61) & 3) {
+            switch ((env->dtlb[i].tte >> 61) & 3) {
             default:
             case 0x0:
                 mask = "  8k";
@@ -582,16 +596,18 @@ void dump_mmu(CPUState *env)
                 mask = "  4M";
                 break;
             }
-            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
-                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
-                       ", %s, %s, %s, %s, ctx %" PRId64 "\n",
-                       env->dtlb_tag[i] & ~0x1fffULL,
-                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
+            if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
+                printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
+                       ", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
+                       i,
+                       env->dtlb[i].tag & (uint64_t)~0x1fffULL,
+                       env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
                        mask,
-                       env->dtlb_tte[i] & 0x4? "priv": "user",
-                       env->dtlb_tte[i] & 0x2? "RW": "RO",
-                       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
-                       env->dtlb_tag[i] & 0x1fffULL);
+                       env->dtlb[i].tte & 0x4? "priv": "user",
+                       env->dtlb[i].tte & 0x2? "RW": "RO",
+                       env->dtlb[i].tte & 0x40? "locked": "unlocked",
+                       env->dtlb[i].tag & (uint64_t)0x1fffULL,
+                       TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
             }
         }
     }
@@ -600,7 +616,7 @@ void dump_mmu(CPUState *env)
     } else {
         printf("IMMU dump:\n");
         for (i = 0; i < 64; i++) {
-            switch ((env->itlb_tte[i] >> 61) & 3) {
+            switch ((env->itlb[i].tte >> 61) & 3) {
             default:
             case 0x0:
                 mask = "  8k";
@@ -615,15 +631,17 @@ void dump_mmu(CPUState *env)
                 mask = "  4M";
                 break;
             }
-            if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
-                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
-                       ", %s, %s, %s, ctx %" PRId64 "\n",
-                       env->itlb_tag[i] & ~0x1fffULL,
-                       env->itlb_tte[i] & 0x1ffffffe000ULL,
+            if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
+                printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
+                       ", %s, %s, %s, ctx %" PRId64 " %s\n",
+                       i,
+                       env->itlb[i].tag & (uint64_t)~0x1fffULL,
+                       env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
                        mask,
-                       env->itlb_tte[i] & 0x4? "priv": "user",
-                       env->itlb_tte[i] & 0x40? "locked": "unlocked",
-                       env->itlb_tag[i] & 0x1fffULL);
+                       env->itlb[i].tte & 0x4? "priv": "user",
+                       env->itlb[i].tte & 0x40? "locked": "unlocked",
+                       env->itlb[i].tag & (uint64_t)0x1fffULL,
+                       TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
             }
         }
     }
@@ -670,6 +688,7 @@ void cpu_reset(CPUSPARCState *env)
     env->wim = 1;
 #endif
     env->regwptr = env->regbase + (env->cwp * 16);
+    CC_OP = CC_OP_FLAGS;
 #if defined(CONFIG_USER_ONLY)
 #ifdef TARGET_SPARC64
     env->cleanwin = env->nwindows - 2;
@@ -683,11 +702,11 @@ void cpu_reset(CPUSPARCState *env)
 #endif
     env->psrs = 1;
     env->psrps = 1;
-    CC_OP = CC_OP_FLAGS;
 #ifdef TARGET_SPARC64
-    env->pstate = PS_PRIV;
+    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
     env->hpstate = HS_PRIV;
-    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
+    env->tl = env->maxtl;
+    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
     env->lsu = 0;
 #else
     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
@@ -747,7 +766,6 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model)
         cpu_sparc_close(env);
         return NULL;
     }
-    cpu_reset(env);
     qemu_init_vcpu(env);
 
     return env;
@@ -1314,7 +1332,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
                 }
                 cpu_def->fpu_version = fpu_version;
 #ifdef DEBUG_FEATURES
-                fprintf(stderr, "fpu_version %llx\n", fpu_version);
+                fprintf(stderr, "fpu_version %x\n", fpu_version);
 #endif
             } else if (!strcmp(featurestr, "mmu_version")) {
                 char *err;
@@ -1326,7 +1344,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
                 }
                 cpu_def->mmu_version = mmu_version;
 #ifdef DEBUG_FEATURES
-                fprintf(stderr, "mmu_version %llx\n", mmu_version);
+                fprintf(stderr, "mmu_version %x\n", mmu_version);
 #endif
             } else if (!strcmp(featurestr, "nwindows")) {
                 char *err;
@@ -1392,6 +1410,21 @@ void sparc_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
                    "fpu_version mmu_version nwindows\n");
 }
 
+static void cpu_print_cc(FILE *f,
+                         int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                         uint32_t cc)
+{
+    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
+                cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
+                cc & PSR_CARRY? 'C' : '-');
+}
+
+#ifdef TARGET_SPARC64
+#define REGS_PER_LINE 4
+#else
+#define REGS_PER_LINE 8
+#endif
+
 void cpu_dump_state(CPUState *env, FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
@@ -1401,26 +1434,32 @@ void cpu_dump_state(CPUState *env, FILE *f,
     cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
                 env->npc);
     cpu_fprintf(f, "General Registers:\n");
-    for (i = 0; i < 4; i++)
-        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
-    cpu_fprintf(f, "\n");
-    for (; i < 8; i++)
-        cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
+
+    for (i = 0; i < 8; i++) {
+        if (i % REGS_PER_LINE == 0) {
+            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
+        }
+        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
+        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+            cpu_fprintf(f, "\n");
+        }
+    }
     cpu_fprintf(f, "\nCurrent Register Window:\n");
     for (x = 0; x < 3; x++) {
-        for (i = 0; i < 4; i++)
-            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
-                    (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
-                    env->regwptr[i + x * 8]);
-        cpu_fprintf(f, "\n");
-        for (; i < 8; i++)
-            cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
-                    (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
-                    env->regwptr[i + x * 8]);
-        cpu_fprintf(f, "\n");
+        for (i = 0; i < 8; i++) {
+            if (i % REGS_PER_LINE == 0) {
+                cpu_fprintf(f, "%%%c%d-%d: ",
+                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
+                            i, i + REGS_PER_LINE - 1);
+            }
+            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
+            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+                cpu_fprintf(f, "\n");
+            }
+        }
     }
     cpu_fprintf(f, "\nFloating Point Registers:\n");
-    for (i = 0; i < 32; i++) {
+    for (i = 0; i < TARGET_FPREGS; i++) {
         if ((i & 3) == 0)
             cpu_fprintf(f, "%%f%02d:", i);
         cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
@@ -1428,21 +1467,26 @@ void cpu_dump_state(CPUState *env, FILE *f,
             cpu_fprintf(f, "\n");
     }
 #ifdef TARGET_SPARC64
-    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
-                env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
-    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
-                "cleanwin %d cwp %d\n",
+    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
+                GET_CCR(env));
+    cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << PSR_CARRY_SHIFT);
+    cpu_fprintf(f, " xcc: ");
+    cpu_print_cc(f, cpu_fprintf, GET_CCR(env) << (PSR_CARRY_SHIFT - 4));
+    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
+                env->psrpil);
+    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
+                "cleanwin: %d cwp: %d\n",
                 env->cansave, env->canrestore, env->otherwin, env->wstate,
                 env->cleanwin, env->nwindows - 1 - env->cwp);
+    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
+                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
 #else
-
-#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
-
-    cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
-                GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
-                GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
-                env->psrs?'S':'-', env->psrps?'P':'-',
-                env->psret?'E':'-', env->wim);
+    cpu_fprintf(f, "psr: %08x (icc: ", GET_PSR(env));
+    cpu_print_cc(f, cpu_fprintf, GET_PSR(env));
+    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
+                env->psrps? 'P' : '-', env->psret? 'E' : '-',
+                env->wim);
+    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
+                env->fsr, env->y);
 #endif
-    cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
 }