summaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-06-04 22:17:59 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-06-04 22:17:59 +0000
commitd094807b9bfe39401e82dce6b7e97a70eb5931be (patch)
treecb19bb3637ec81733b5c18fc48add5771b66770d /target-ppc
parent6d506e6dc2994030427e185bf44f0020c37ac086 (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.c71
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__