Blame 0117-MIPS-user-Fix-reset-CPU-state-initialization.patch

5544c1
From 608a36df28b4db83124d06081029023e01901fc9 Mon Sep 17 00:00:00 2001
5544c1
From: "Maciej W. Rozycki" <macro@codesourcery.com>
5544c1
Date: Fri, 8 Jun 2012 02:04:40 +0100
5544c1
Subject: [PATCH] MIPS/user: Fix reset CPU state initialization
5544c1
5544c1
 This change updates the CPU reset sequence to use a common piece of code
5544c1
that figures out CPU state flags, fixing the problem with MIPS_HFLAG_COP1X
5544c1
not being set where applicable that causes floating-point MADD family
5544c1
instructions (and other instructions from the MIPS IV FP subset) to trap.
5544c1
5544c1
 As compute_hflags is now shared between op_helper.c and translate.c, the
5544c1
function is now moved to a common header.  There are no changes to this
5544c1
function.
5544c1
5544c1
 The problem was seen with the 24Kf MIPS32r2 processor in user emulation.
5544c1
The new approach prevents system and user emulation from diverging -- all
5544c1
the hflags state is initialized in one place now.
5544c1
5544c1
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
5544c1
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
5544c1
(cherry picked from commit 03e6e5017757645f00b2f3b4f3a257973985e455)
5544c1
5544c1
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
5544c1
---
5544c1
 target-mips/cpu.h       | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
5544c1
 target-mips/op_helper.c | 49 -------------------------------------------------
5544c1
 target-mips/translate.c | 16 +++-------------
5544c1
 3 files changed, 52 insertions(+), 62 deletions(-)
5544c1
5544c1
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
5544c1
index be4f805..b7a5112 100644
5544c1
--- a/target-mips/cpu.h
5544c1
+++ b/target-mips/cpu.h
5544c1
@@ -742,4 +742,53 @@ static inline void cpu_pc_from_tb(CPUMIPSState *env, TranslationBlock *tb)
5544c1
     env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
5544c1
 }
5544c1
 
5544c1
+static inline void compute_hflags(CPUMIPSState *env)
5544c1
+{
5544c1
+    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
5544c1
+                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
5544c1
+                     MIPS_HFLAG_UX);
5544c1
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
5544c1
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
5544c1
+        !(env->hflags & MIPS_HFLAG_DM)) {
5544c1
+        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
5544c1
+    }
5544c1
+#if defined(TARGET_MIPS64)
5544c1
+    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
5544c1
+        (env->CP0_Status & (1 << CP0St_PX)) ||
5544c1
+        (env->CP0_Status & (1 << CP0St_UX))) {
5544c1
+        env->hflags |= MIPS_HFLAG_64;
5544c1
+    }
5544c1
+    if (env->CP0_Status & (1 << CP0St_UX)) {
5544c1
+        env->hflags |= MIPS_HFLAG_UX;
5544c1
+    }
5544c1
+#endif
5544c1
+    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
5544c1
+        !(env->hflags & MIPS_HFLAG_KSU)) {
5544c1
+        env->hflags |= MIPS_HFLAG_CP0;
5544c1
+    }
5544c1
+    if (env->CP0_Status & (1 << CP0St_CU1)) {
5544c1
+        env->hflags |= MIPS_HFLAG_FPU;
5544c1
+    }
5544c1
+    if (env->CP0_Status & (1 << CP0St_FR)) {
5544c1
+        env->hflags |= MIPS_HFLAG_F64;
5544c1
+    }
5544c1
+    if (env->insn_flags & ISA_MIPS32R2) {
5544c1
+        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
5544c1
+            env->hflags |= MIPS_HFLAG_COP1X;
5544c1
+        }
5544c1
+    } else if (env->insn_flags & ISA_MIPS32) {
5544c1
+        if (env->hflags & MIPS_HFLAG_64) {
5544c1
+            env->hflags |= MIPS_HFLAG_COP1X;
5544c1
+        }
5544c1
+    } else if (env->insn_flags & ISA_MIPS4) {
5544c1
+        /* All supported MIPS IV CPUs use the XX (CU3) to enable
5544c1
+           and disable the MIPS IV extensions to the MIPS III ISA.
5544c1
+           Some other MIPS IV CPUs ignore the bit, so the check here
5544c1
+           would be too restrictive for them.  */
5544c1
+        if (env->CP0_Status & (1 << CP0St_CU3)) {
5544c1
+            env->hflags |= MIPS_HFLAG_COP1X;
5544c1
+        }
5544c1
+    }
5544c1
+}
5544c1
+
5544c1
 #endif /* !defined (__MIPS_CPU_H__) */
5544c1
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
5544c1
index d2a8a55..ce5ddaf 100644
5544c1
--- a/target-mips/op_helper.c
5544c1
+++ b/target-mips/op_helper.c
5544c1
@@ -30,55 +30,6 @@
5544c1
 static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global);
5544c1
 #endif
5544c1
 
5544c1
-static inline void compute_hflags(CPUMIPSState *env)
5544c1
-{
5544c1
-    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
5544c1
-                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
5544c1
-                     MIPS_HFLAG_UX);
5544c1
-    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
5544c1
-        !(env->CP0_Status & (1 << CP0St_ERL)) &&
5544c1
-        !(env->hflags & MIPS_HFLAG_DM)) {
5544c1
-        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
5544c1
-    }
5544c1
-#if defined(TARGET_MIPS64)
5544c1
-    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
5544c1
-        (env->CP0_Status & (1 << CP0St_PX)) ||
5544c1
-        (env->CP0_Status & (1 << CP0St_UX))) {
5544c1
-        env->hflags |= MIPS_HFLAG_64;
5544c1
-    }
5544c1
-    if (env->CP0_Status & (1 << CP0St_UX)) {
5544c1
-        env->hflags |= MIPS_HFLAG_UX;
5544c1
-    }
5544c1
-#endif
5544c1
-    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
5544c1
-        !(env->hflags & MIPS_HFLAG_KSU)) {
5544c1
-        env->hflags |= MIPS_HFLAG_CP0;
5544c1
-    }
5544c1
-    if (env->CP0_Status & (1 << CP0St_CU1)) {
5544c1
-        env->hflags |= MIPS_HFLAG_FPU;
5544c1
-    }
5544c1
-    if (env->CP0_Status & (1 << CP0St_FR)) {
5544c1
-        env->hflags |= MIPS_HFLAG_F64;
5544c1
-    }
5544c1
-    if (env->insn_flags & ISA_MIPS32R2) {
5544c1
-        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
5544c1
-            env->hflags |= MIPS_HFLAG_COP1X;
5544c1
-        }
5544c1
-    } else if (env->insn_flags & ISA_MIPS32) {
5544c1
-        if (env->hflags & MIPS_HFLAG_64) {
5544c1
-            env->hflags |= MIPS_HFLAG_COP1X;
5544c1
-        }
5544c1
-    } else if (env->insn_flags & ISA_MIPS4) {
5544c1
-        /* All supported MIPS IV CPUs use the XX (CU3) to enable
5544c1
-           and disable the MIPS IV extensions to the MIPS III ISA.
5544c1
-           Some other MIPS IV CPUs ignore the bit, so the check here
5544c1
-           would be too restrictive for them.  */
5544c1
-        if (env->CP0_Status & (1 << CP0St_CU3)) {
5544c1
-            env->hflags |= MIPS_HFLAG_COP1X;
5544c1
-        }
5544c1
-    }
5544c1
-}
5544c1
-
5544c1
 /*****************************************************************************/
5544c1
 /* Exceptions processing helpers */
5544c1
 
5544c1
diff --git a/target-mips/translate.c b/target-mips/translate.c
5544c1
index aba7935..4e04e97 100644
5544c1
--- a/target-mips/translate.c
5544c1
+++ b/target-mips/translate.c
5544c1
@@ -12816,18 +12816,13 @@ void cpu_state_reset(CPUMIPSState *env)
5544c1
     env->insn_flags = env->cpu_model->insn_flags;
5544c1
 
5544c1
 #if defined(CONFIG_USER_ONLY)
5544c1
-    env->hflags = MIPS_HFLAG_UM;
5544c1
+    env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
5544c1
     /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
5544c1
        hardware registers.  */
5544c1
     env->CP0_HWREna |= 0x0000000F;
5544c1
     if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5544c1
-        env->hflags |= MIPS_HFLAG_FPU;
5544c1
+        env->CP0_Status |= (1 << CP0St_CU1);
5544c1
     }
5544c1
-#ifdef TARGET_MIPS64
5544c1
-    if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
5544c1
-        env->hflags |= MIPS_HFLAG_F64;
5544c1
-    }
5544c1
-#endif
5544c1
 #else
5544c1
     if (env->hflags & MIPS_HFLAG_BMASK) {
5544c1
         /* If the exception was raised from a delay slot,
5544c1
@@ -12857,7 +12852,6 @@ void cpu_state_reset(CPUMIPSState *env)
5544c1
     }
5544c1
     /* Count register increments in debug mode, EJTAG version 1 */
5544c1
     env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
5544c1
-    env->hflags = MIPS_HFLAG_CP0;
5544c1
 
5544c1
     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
5544c1
         int i;
5544c1
@@ -12885,11 +12879,7 @@ void cpu_state_reset(CPUMIPSState *env)
5544c1
         }
5544c1
     }
5544c1
 #endif
5544c1
-#if defined(TARGET_MIPS64)
5544c1
-    if (env->cpu_model->insn_flags & ISA_MIPS3) {
5544c1
-        env->hflags |= MIPS_HFLAG_64;
5544c1
-    }
5544c1
-#endif
5544c1
+    compute_hflags(env);
5544c1
     env->exception_index = EXCP_NONE;
5544c1
 }
5544c1
 
5544c1
-- 
5544c1
1.7.12.1
5544c1