ARM N=Z=1 flag fix.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4156 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 1feec83..9e93c24 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -86,7 +86,8 @@
     /* cpsr flag cache for faster execution */
     uint32_t CF; /* 0 or 1 */
     uint32_t VF; /* V is the bit 31. All other bits are undefined */
-    uint32_t NZF; /* N is bit 31. Z is computed from NZF */
+    uint32_t NF; /* N is bit 31. All other bits are undefined.  */
+    uint32_t ZF; /* Z set if zero.  */
     uint32_t QF; /* 0 or 1 */
     uint32_t GE; /* cpsr[19:16] */
     uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
@@ -254,8 +255,8 @@
 static inline uint32_t xpsr_read(CPUARMState *env)
 {
     int ZF;
-    ZF = (env->NZF == 0);
-    return (env->NZF & 0x80000000) | (ZF << 30)
+    ZF = (env->ZF == 0);
+    return (env->NF & 0x80000000) | (ZF << 30)
         | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
         | (env->thumb << 24) | ((env->condexec_bits & 3) << 25)
         | ((env->condexec_bits & 0xfc) << 8)
@@ -265,9 +266,9 @@
 /* Set the xPSR.  Note that some bits of mask must be all-set or all-clear.  */
 static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 {
-    /* NOTE: N = 1 and Z = 1 cannot be stored currently */
     if (mask & CPSR_NZCV) {
-        env->NZF = (val & 0xc0000000) ^ 0x40000000;
+        env->ZF = (~val) & CPSR_Z;
+        env->NF = val;
         env->CF = (val >> 29) & 1;
         env->VF = (val << 3) & 0x80000000;
     }
diff --git a/target-arm/helper.c b/target-arm/helper.c
index a2dd7b1..3f7a01d 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -259,8 +259,8 @@
 uint32_t cpsr_read(CPUARMState *env)
 {
     int ZF;
-    ZF = (env->NZF == 0);
-    return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
+    ZF = (env->ZF == 0);
+    return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) |
         (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
         | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
         | ((env->condexec_bits & 0xfc) << 8)
@@ -269,9 +269,9 @@
 
 void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
 {
-    /* NOTE: N = 1 and Z = 1 cannot be stored currently */
     if (mask & CPSR_NZCV) {
-        env->NZF = (val & 0xc0000000) ^ 0x40000000;
+        env->ZF = (~val) & CPSR_Z;
+        env->NF = val;
         env->CF = (val >> 29) & 1;
         env->VF = (val << 3) & 0x80000000;
     }
@@ -1690,10 +1690,8 @@
 	    }
         }
     case 7: /* Cache control.  */
-        /* ??? This is for test, clean and invaidate operations that set the
-           Z flag.  We can't represent N = Z = 1, so it also clears
-           the N flag.  Oh well.  */
-        env->NZF = 0;
+        /* FIXME: Should only clear Z flag if destination is r15.  */
+        env->ZF = 0;
         return 0;
     case 8: /* MMU TLB control.  */
         goto bad_reg;
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 20dafae..555b55c 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -315,7 +315,7 @@
 {
     uint32_t result;
     result = T0 + T1;
-    env->NZF = result;
+    env->NF = env->ZF = result;
     env->CF = result < a;
     env->VF = (a ^ b ^ -1) & (a ^ result);
     return result;
@@ -332,7 +332,7 @@
         env->CF = result <= a;
     }
     env->VF = (a ^ b ^ -1) & (a ^ result);
-    env->NZF = result;
+    env->NF = env->ZF = result;
     return result;
 }
 
@@ -340,7 +340,7 @@
 {
     uint32_t result;
     result = a - b;
-    env->NZF = result;
+    env->NF = env->ZF = result;
     env->CF = a >= b;
     env->VF = (a ^ b) & (a ^ result);
     return result;
@@ -357,7 +357,7 @@
         env->CF = a >= b;
     }
     env->VF = (a ^ b) & (a ^ result);
-    env->NZF = result;
+    env->NF = env->ZF = result;
     return result;
 }
 
diff --git a/target-arm/translate.c b/target-arm/translate.c
index fdba7dd..9ff3ff8 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -423,7 +423,8 @@
 /* Set N and Z flags from var.  */
 static inline void gen_logic_CC(TCGv var)
 {
-    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF));
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
+    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
 }
 
 /* T0 += T1 + CF.  */
@@ -679,11 +680,11 @@
     zero = tcg_const_i32(0);
     switch (cc) {
     case 0: /* eq: Z */
-        tmp = load_cpu_field(NZF);
+        tmp = load_cpu_field(ZF);
         tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
         break;
     case 1: /* ne: !Z */
-        tmp = load_cpu_field(NZF);
+        tmp = load_cpu_field(ZF);
         tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
         break;
     case 2: /* cs: C */
@@ -695,11 +696,11 @@
         tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
         break;
     case 4: /* mi: N */
-        tmp = load_cpu_field(NZF);
+        tmp = load_cpu_field(NF);
         tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
         break;
     case 5: /* pl: !N */
-        tmp = load_cpu_field(NZF);
+        tmp = load_cpu_field(NF);
         tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
         break;
     case 6: /* vs: V */
@@ -715,7 +716,7 @@
         tmp = load_cpu_field(CF);
         tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
         dead_tmp(tmp);
-        tmp = load_cpu_field(NZF);
+        tmp = load_cpu_field(ZF);
         tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
         gen_set_label(inv);
         break;
@@ -723,41 +724,41 @@
         tmp = load_cpu_field(CF);
         tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
         dead_tmp(tmp);
-        tmp = load_cpu_field(NZF);
+        tmp = load_cpu_field(ZF);
         tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
         break;
     case 10: /* ge: N == V -> N ^ V == 0 */
         tmp = load_cpu_field(VF);
-        tmp2 = load_cpu_field(NZF);
+        tmp2 = load_cpu_field(NF);
         tcg_gen_xor_i32(tmp, tmp, tmp2);
         dead_tmp(tmp2);
         tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
         break;
     case 11: /* lt: N != V -> N ^ V != 0 */
         tmp = load_cpu_field(VF);
-        tmp2 = load_cpu_field(NZF);
+        tmp2 = load_cpu_field(NF);
         tcg_gen_xor_i32(tmp, tmp, tmp2);
         dead_tmp(tmp2);
         tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
         break;
     case 12: /* gt: !Z && N == V */
         inv = gen_new_label();
-        tmp = load_cpu_field(NZF);
+        tmp = load_cpu_field(ZF);
         tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
         dead_tmp(tmp);
         tmp = load_cpu_field(VF);
-        tmp2 = load_cpu_field(NZF);
+        tmp2 = load_cpu_field(NF);
         tcg_gen_xor_i32(tmp, tmp, tmp2);
         dead_tmp(tmp2);
         tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
         gen_set_label(inv);
         break;
     case 13: /* le: Z || N != V */
-        tmp = load_cpu_field(NZF);
+        tmp = load_cpu_field(ZF);
         tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
         dead_tmp(tmp);
         tmp = load_cpu_field(VF);
-        tmp2 = load_cpu_field(NZF);
+        tmp2 = load_cpu_field(NF);
         tcg_gen_xor_i32(tmp, tmp, tmp2);
         dead_tmp(tmp2);
         tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
@@ -5641,7 +5642,8 @@
 {
     TCGv tmp = new_tmp();
     gen_helper_logicq_cc(tmp, val);
-    store_cpu_field(tmp, NZF);
+    gen_logic_CC(tmp);
+    dead_tmp(tmp);
 }
 
 static void disas_arm_insn(CPUState * env, DisasContext *s)