Merge "Change requested in launchpad bug #1288352" into 5.0
[packages/centos6/qemu.git] / 0117-MIPS-user-Fix-reset-CPU-state-initialization.patch
1 From 608a36df28b4db83124d06081029023e01901fc9 Mon Sep 17 00:00:00 2001
2 From: "Maciej W. Rozycki" <macro@codesourcery.com>
3 Date: Fri, 8 Jun 2012 02:04:40 +0100
4 Subject: [PATCH] MIPS/user: Fix reset CPU state initialization
5
6  This change updates the CPU reset sequence to use a common piece of code
7 that figures out CPU state flags, fixing the problem with MIPS_HFLAG_COP1X
8 not being set where applicable that causes floating-point MADD family
9 instructions (and other instructions from the MIPS IV FP subset) to trap.
10
11  As compute_hflags is now shared between op_helper.c and translate.c, the
12 function is now moved to a common header.  There are no changes to this
13 function.
14
15  The problem was seen with the 24Kf MIPS32r2 processor in user emulation.
16 The new approach prevents system and user emulation from diverging -- all
17 the hflags state is initialized in one place now.
18
19 Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
20 Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
21 (cherry picked from commit 03e6e5017757645f00b2f3b4f3a257973985e455)
22
23 Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
24 ---
25  target-mips/cpu.h       | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
26  target-mips/op_helper.c | 49 -------------------------------------------------
27  target-mips/translate.c | 16 +++-------------
28  3 files changed, 52 insertions(+), 62 deletions(-)
29
30 diff --git a/target-mips/cpu.h b/target-mips/cpu.h
31 index be4f805..b7a5112 100644
32 --- a/target-mips/cpu.h
33 +++ b/target-mips/cpu.h
34 @@ -742,4 +742,53 @@ static inline void cpu_pc_from_tb(CPUMIPSState *env, TranslationBlock *tb)
35      env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
36  }
37  
38 +static inline void compute_hflags(CPUMIPSState *env)
39 +{
40 +    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
41 +                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
42 +                     MIPS_HFLAG_UX);
43 +    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
44 +        !(env->CP0_Status & (1 << CP0St_ERL)) &&
45 +        !(env->hflags & MIPS_HFLAG_DM)) {
46 +        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
47 +    }
48 +#if defined(TARGET_MIPS64)
49 +    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
50 +        (env->CP0_Status & (1 << CP0St_PX)) ||
51 +        (env->CP0_Status & (1 << CP0St_UX))) {
52 +        env->hflags |= MIPS_HFLAG_64;
53 +    }
54 +    if (env->CP0_Status & (1 << CP0St_UX)) {
55 +        env->hflags |= MIPS_HFLAG_UX;
56 +    }
57 +#endif
58 +    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
59 +        !(env->hflags & MIPS_HFLAG_KSU)) {
60 +        env->hflags |= MIPS_HFLAG_CP0;
61 +    }
62 +    if (env->CP0_Status & (1 << CP0St_CU1)) {
63 +        env->hflags |= MIPS_HFLAG_FPU;
64 +    }
65 +    if (env->CP0_Status & (1 << CP0St_FR)) {
66 +        env->hflags |= MIPS_HFLAG_F64;
67 +    }
68 +    if (env->insn_flags & ISA_MIPS32R2) {
69 +        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
70 +            env->hflags |= MIPS_HFLAG_COP1X;
71 +        }
72 +    } else if (env->insn_flags & ISA_MIPS32) {
73 +        if (env->hflags & MIPS_HFLAG_64) {
74 +            env->hflags |= MIPS_HFLAG_COP1X;
75 +        }
76 +    } else if (env->insn_flags & ISA_MIPS4) {
77 +        /* All supported MIPS IV CPUs use the XX (CU3) to enable
78 +           and disable the MIPS IV extensions to the MIPS III ISA.
79 +           Some other MIPS IV CPUs ignore the bit, so the check here
80 +           would be too restrictive for them.  */
81 +        if (env->CP0_Status & (1 << CP0St_CU3)) {
82 +            env->hflags |= MIPS_HFLAG_COP1X;
83 +        }
84 +    }
85 +}
86 +
87  #endif /* !defined (__MIPS_CPU_H__) */
88 diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
89 index d2a8a55..ce5ddaf 100644
90 --- a/target-mips/op_helper.c
91 +++ b/target-mips/op_helper.c
92 @@ -30,55 +30,6 @@
93  static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global);
94  #endif
95  
96 -static inline void compute_hflags(CPUMIPSState *env)
97 -{
98 -    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
99 -                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
100 -                     MIPS_HFLAG_UX);
101 -    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
102 -        !(env->CP0_Status & (1 << CP0St_ERL)) &&
103 -        !(env->hflags & MIPS_HFLAG_DM)) {
104 -        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
105 -    }
106 -#if defined(TARGET_MIPS64)
107 -    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
108 -        (env->CP0_Status & (1 << CP0St_PX)) ||
109 -        (env->CP0_Status & (1 << CP0St_UX))) {
110 -        env->hflags |= MIPS_HFLAG_64;
111 -    }
112 -    if (env->CP0_Status & (1 << CP0St_UX)) {
113 -        env->hflags |= MIPS_HFLAG_UX;
114 -    }
115 -#endif
116 -    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
117 -        !(env->hflags & MIPS_HFLAG_KSU)) {
118 -        env->hflags |= MIPS_HFLAG_CP0;
119 -    }
120 -    if (env->CP0_Status & (1 << CP0St_CU1)) {
121 -        env->hflags |= MIPS_HFLAG_FPU;
122 -    }
123 -    if (env->CP0_Status & (1 << CP0St_FR)) {
124 -        env->hflags |= MIPS_HFLAG_F64;
125 -    }
126 -    if (env->insn_flags & ISA_MIPS32R2) {
127 -        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
128 -            env->hflags |= MIPS_HFLAG_COP1X;
129 -        }
130 -    } else if (env->insn_flags & ISA_MIPS32) {
131 -        if (env->hflags & MIPS_HFLAG_64) {
132 -            env->hflags |= MIPS_HFLAG_COP1X;
133 -        }
134 -    } else if (env->insn_flags & ISA_MIPS4) {
135 -        /* All supported MIPS IV CPUs use the XX (CU3) to enable
136 -           and disable the MIPS IV extensions to the MIPS III ISA.
137 -           Some other MIPS IV CPUs ignore the bit, so the check here
138 -           would be too restrictive for them.  */
139 -        if (env->CP0_Status & (1 << CP0St_CU3)) {
140 -            env->hflags |= MIPS_HFLAG_COP1X;
141 -        }
142 -    }
143 -}
144 -
145  /*****************************************************************************/
146  /* Exceptions processing helpers */
147  
148 diff --git a/target-mips/translate.c b/target-mips/translate.c
149 index aba7935..4e04e97 100644
150 --- a/target-mips/translate.c
151 +++ b/target-mips/translate.c
152 @@ -12816,18 +12816,13 @@ void cpu_state_reset(CPUMIPSState *env)
153      env->insn_flags = env->cpu_model->insn_flags;
154  
155  #if defined(CONFIG_USER_ONLY)
156 -    env->hflags = MIPS_HFLAG_UM;
157 +    env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
158      /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
159         hardware registers.  */
160      env->CP0_HWREna |= 0x0000000F;
161      if (env->CP0_Config1 & (1 << CP0C1_FP)) {
162 -        env->hflags |= MIPS_HFLAG_FPU;
163 +        env->CP0_Status |= (1 << CP0St_CU1);
164      }
165 -#ifdef TARGET_MIPS64
166 -    if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
167 -        env->hflags |= MIPS_HFLAG_F64;
168 -    }
169 -#endif
170  #else
171      if (env->hflags & MIPS_HFLAG_BMASK) {
172          /* If the exception was raised from a delay slot,
173 @@ -12857,7 +12852,6 @@ void cpu_state_reset(CPUMIPSState *env)
174      }
175      /* Count register increments in debug mode, EJTAG version 1 */
176      env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
177 -    env->hflags = MIPS_HFLAG_CP0;
178  
179      if (env->CP0_Config3 & (1 << CP0C3_MT)) {
180          int i;
181 @@ -12885,11 +12879,7 @@ void cpu_state_reset(CPUMIPSState *env)
182          }
183      }
184  #endif
185 -#if defined(TARGET_MIPS64)
186 -    if (env->cpu_model->insn_flags & ISA_MIPS3) {
187 -        env->hflags |= MIPS_HFLAG_64;
188 -    }
189 -#endif
190 +    compute_hflags(env);
191      env->exception_index = EXCP_NONE;
192  }
193  
194 -- 
195 1.7.12.1
196