diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-06-04 22:17:59 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-06-04 22:17:59 +0000 |
commit | d094807b9bfe39401e82dce6b7e97a70eb5931be (patch) | |
tree | cb19bb3637ec81733b5c18fc48add5771b66770d /target-ppc | |
parent | 6d506e6dc2994030427e185bf44f0020c37ac086 (diff) |
MMU fix - temporary osi_call support - xec_bc mask fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1437 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/helper.c | 71 |
1 files changed, 35 insertions, 36 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c index b54b5d205..52aad9532 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -22,6 +22,8 @@ //#define DEBUG_MMU //#define DEBUG_BATS //#define DEBUG_EXCEPTIONS +/* accurate but slower TLB flush in exceptions */ +//#define ACCURATE_TLB_FLUSH /*****************************************************************************/ /* PPC MMU emulation */ @@ -128,7 +130,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, pte0 = ldl_phys(base + (i * 8)); pte1 = ldl_phys(base + (i * 8) + 4); #if defined (DEBUG_MMU) - if (loglevel > 0) { + if (loglevel > 0) { fprintf(logfile, "Load pte from 0x%08x => 0x%08x 0x%08x " "%d %d %d 0x%08x\n", base + (i * 8), pte0, pte1, pte0 >> 31, h, (pte0 >> 6) & 1, va); @@ -175,17 +177,17 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, if (loglevel > 0) fprintf(logfile, "PTE access granted !\n"); #endif - good = i; - keep = pte1; - ret = 0; + good = i; + keep = pte1; + ret = 0; } else { /* Access right violation */ - ret = -2; + ret = -2; #if defined (DEBUG_MMU) if (loglevel > 0) fprintf(logfile, "PTE access rejected\n"); #endif - } + } *prot = access; } } @@ -194,7 +196,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, if (good != -1) { *RPN = keep & 0xFFFFF000; #if defined (DEBUG_MMU) - if (loglevel > 0) { + if (loglevel > 0) { fprintf(logfile, "found PTE at addr 0x%08x prot=0x%01x ret=%d\n", *RPN, *prot, ret); } @@ -205,7 +207,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, keep |= 0x00000100; store = 1; } - if (!(keep & 0x00000080)) { + if (!(keep & 0x00000080)) { if (rw && ret == 0) { /* Change flag */ keep |= 0x00000080; @@ -251,7 +253,7 @@ static int get_segment (CPUState *env, uint32_t *real, int *prot, ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0; if ((sr & 0x80000000) == 0) { #if defined (DEBUG_MMU) - if (loglevel > 0) + if (loglevel > 0) fprintf(logfile, "pte segment: key=%d n=0x%08x\n", key, sr & 0x10000000); #endif @@ -604,7 +606,7 @@ void _store_xer (CPUState *env, uint32_t value) xer_so = (value >> XER_SO) & 0x01; xer_ov = (value >> XER_OV) & 0x01; xer_ca = (value >> XER_CA) & 0x01; - xer_bc = (value >> XER_BC) & 0x1f; + xer_bc = (value >> XER_BC) & 0x3f; } uint32_t _load_msr (CPUState *env) @@ -628,12 +630,12 @@ uint32_t _load_msr (CPUState *env) void _store_msr (CPUState *env, uint32_t value) { -#if 0 // TRY +#ifdef ACCURATE_TLB_FLUSH if (((value >> MSR_IR) & 0x01) != msr_ir || ((value >> MSR_DR) & 0x01) != msr_dr) { /* Flush all tlb when changing translation mode or privilege level */ - tlb_flush(env, 1); + tlb_flush(env, 1); } #endif msr_pow = (value >> MSR_POW) & 0x03; @@ -660,6 +662,13 @@ void do_interrupt (CPUState *env) env->exception_index = -1; } #else +static void dump_syscall(CPUState *env) +{ + fprintf(logfile, "syscall r0=0x%08x r3=0x%08x r4=0x%08x r5=0x%08x r6=0x%08x nip=0x%08x\n", + env->gpr[0], env->gpr[3], env->gpr[4], + env->gpr[5], env->gpr[6], env->nip); +} + void do_interrupt (CPUState *env) { uint32_t msr; @@ -707,11 +716,11 @@ void do_interrupt (CPUState *env) */ msr &= ~0xFFFF0000; env->spr[DSISR] = 0; - if (env->error_code & EXCP_DSI_TRANSLATE) + if ((env->error_code & 0x0f) == EXCP_DSI_TRANSLATE) env->spr[DSISR] |= 0x40000000; - else if (env->error_code & EXCP_DSI_PROT) + else if ((env->error_code & 0x0f) == EXCP_DSI_PROT) env->spr[DSISR] |= 0x08000000; - else if (env->error_code & EXCP_DSI_NOTSUP) { + else if ((env->error_code & 0x0f) == EXCP_DSI_NOTSUP) { env->spr[DSISR] |= 0x80000000; if (env->error_code & EXCP_DSI_DIRECT) env->spr[DSISR] |= 0x04000000; @@ -819,28 +828,15 @@ void do_interrupt (CPUState *env) } goto store_next; case EXCP_SYSCALL: + /* NOTE: this is a temporary hack to support graphics OSI + calls from the MOL driver */ + if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b && + env->osi_call) { + if (env->osi_call(env) != 0) + return; + } if (loglevel & CPU_LOG_INT) { - fprintf(logfile, "syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", - env->gpr[0], env->gpr[3], env->gpr[4], - env->gpr[5], env->gpr[6]); - if (env->gpr[0] == 4 && env->gpr[3] == 1) { - int len, addr, i; - uint8_t c; - - fprintf(logfile, "write: "); - addr = env->gpr[4]; - len = env->gpr[5]; - if (len > 64) - len = 64; - for(i = 0; i < len; i++) { - c = 0; - cpu_memory_rw_debug(env, addr + i, &c, 1, 0); - if (c < 32 || c > 126) - c = '.'; - fprintf(logfile, "%c", c); - } - fprintf(logfile, "\n"); - } + dump_syscall(env); } goto store_next; case EXCP_TRACE: @@ -887,6 +883,9 @@ void do_interrupt (CPUState *env) env->nip = excp << 8; env->exception_index = EXCP_NONE; /* Invalidate all TLB as we may have changed translation mode */ +#ifdef ACCURATE_TLB_FLUSH + tlb_flush(env, 1); +#endif /* ensure that no TB jump will be modified as the program flow was changed */ #ifdef __sparc__ |