提交 6fbe23d5 编写于 作者: P pbrook

ARM N=Z=1 flag fix.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4156 c046a42c-6fe2-441c-8c8c-71466251a162
上级 f5d28393
...@@ -86,7 +86,8 @@ typedef struct CPUARMState { ...@@ -86,7 +86,8 @@ typedef struct CPUARMState {
/* cpsr flag cache for faster execution */ /* cpsr flag cache for faster execution */
uint32_t CF; /* 0 or 1 */ uint32_t CF; /* 0 or 1 */
uint32_t VF; /* V is the bit 31. All other bits are undefined */ 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 QF; /* 0 or 1 */
uint32_t GE; /* cpsr[19:16] */ uint32_t GE; /* cpsr[19:16] */
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */ uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
...@@ -254,8 +255,8 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask); ...@@ -254,8 +255,8 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask);
static inline uint32_t xpsr_read(CPUARMState *env) static inline uint32_t xpsr_read(CPUARMState *env)
{ {
int ZF; int ZF;
ZF = (env->NZF == 0); ZF = (env->ZF == 0);
return (env->NZF & 0x80000000) | (ZF << 30) return (env->NF & 0x80000000) | (ZF << 30)
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
| (env->thumb << 24) | ((env->condexec_bits & 3) << 25) | (env->thumb << 24) | ((env->condexec_bits & 3) << 25)
| ((env->condexec_bits & 0xfc) << 8) | ((env->condexec_bits & 0xfc) << 8)
...@@ -265,9 +266,9 @@ static inline uint32_t xpsr_read(CPUARMState *env) ...@@ -265,9 +266,9 @@ static inline uint32_t xpsr_read(CPUARMState *env)
/* Set the xPSR. Note that some bits of mask must be all-set or all-clear. */ /* 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) 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) { if (mask & CPSR_NZCV) {
env->NZF = (val & 0xc0000000) ^ 0x40000000; env->ZF = (~val) & CPSR_Z;
env->NF = val;
env->CF = (val >> 29) & 1; env->CF = (val >> 29) & 1;
env->VF = (val << 3) & 0x80000000; env->VF = (val << 3) & 0x80000000;
} }
......
...@@ -259,8 +259,8 @@ void cpu_arm_close(CPUARMState *env) ...@@ -259,8 +259,8 @@ void cpu_arm_close(CPUARMState *env)
uint32_t cpsr_read(CPUARMState *env) uint32_t cpsr_read(CPUARMState *env)
{ {
int ZF; int ZF;
ZF = (env->NZF == 0); ZF = (env->ZF == 0);
return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) | return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) |
(env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
| (env->thumb << 5) | ((env->condexec_bits & 3) << 25) | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
| ((env->condexec_bits & 0xfc) << 8) | ((env->condexec_bits & 0xfc) << 8)
...@@ -269,9 +269,9 @@ uint32_t cpsr_read(CPUARMState *env) ...@@ -269,9 +269,9 @@ uint32_t cpsr_read(CPUARMState *env)
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) 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) { if (mask & CPSR_NZCV) {
env->NZF = (val & 0xc0000000) ^ 0x40000000; env->ZF = (~val) & CPSR_Z;
env->NF = val;
env->CF = (val >> 29) & 1; env->CF = (val >> 29) & 1;
env->VF = (val << 3) & 0x80000000; env->VF = (val << 3) & 0x80000000;
} }
...@@ -1690,10 +1690,8 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn) ...@@ -1690,10 +1690,8 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
} }
} }
case 7: /* Cache control. */ case 7: /* Cache control. */
/* ??? This is for test, clean and invaidate operations that set the /* FIXME: Should only clear Z flag if destination is r15. */
Z flag. We can't represent N = Z = 1, so it also clears env->ZF = 0;
the N flag. Oh well. */
env->NZF = 0;
return 0; return 0;
case 8: /* MMU TLB control. */ case 8: /* MMU TLB control. */
goto bad_reg; goto bad_reg;
......
...@@ -315,7 +315,7 @@ uint32_t HELPER (add_cc)(uint32_t a, uint32_t b) ...@@ -315,7 +315,7 @@ uint32_t HELPER (add_cc)(uint32_t a, uint32_t b)
{ {
uint32_t result; uint32_t result;
result = T0 + T1; result = T0 + T1;
env->NZF = result; env->NF = env->ZF = result;
env->CF = result < a; env->CF = result < a;
env->VF = (a ^ b ^ -1) & (a ^ result); env->VF = (a ^ b ^ -1) & (a ^ result);
return result; return result;
...@@ -332,7 +332,7 @@ uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) ...@@ -332,7 +332,7 @@ uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
env->CF = result <= a; env->CF = result <= a;
} }
env->VF = (a ^ b ^ -1) & (a ^ result); env->VF = (a ^ b ^ -1) & (a ^ result);
env->NZF = result; env->NF = env->ZF = result;
return result; return result;
} }
...@@ -340,7 +340,7 @@ uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) ...@@ -340,7 +340,7 @@ uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
{ {
uint32_t result; uint32_t result;
result = a - b; result = a - b;
env->NZF = result; env->NF = env->ZF = result;
env->CF = a >= b; env->CF = a >= b;
env->VF = (a ^ b) & (a ^ result); env->VF = (a ^ b) & (a ^ result);
return result; return result;
...@@ -357,7 +357,7 @@ uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b) ...@@ -357,7 +357,7 @@ uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
env->CF = a >= b; env->CF = a >= b;
} }
env->VF = (a ^ b) & (a ^ result); env->VF = (a ^ b) & (a ^ result);
env->NZF = result; env->NF = env->ZF = result;
return result; return result;
} }
......
...@@ -423,7 +423,8 @@ static void gen_set_CF_bit31(TCGv var) ...@@ -423,7 +423,8 @@ static void gen_set_CF_bit31(TCGv var)
/* Set N and Z flags from var. */ /* Set N and Z flags from var. */
static inline void gen_logic_CC(TCGv 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. */ /* T0 += T1 + CF. */
...@@ -679,11 +680,11 @@ static void gen_test_cc(int cc, int label) ...@@ -679,11 +680,11 @@ static void gen_test_cc(int cc, int label)
zero = tcg_const_i32(0); zero = tcg_const_i32(0);
switch (cc) { switch (cc) {
case 0: /* eq: Z */ case 0: /* eq: Z */
tmp = load_cpu_field(NZF); tmp = load_cpu_field(ZF);
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
break; break;
case 1: /* ne: !Z */ case 1: /* ne: !Z */
tmp = load_cpu_field(NZF); tmp = load_cpu_field(ZF);
tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
break; break;
case 2: /* cs: C */ case 2: /* cs: C */
...@@ -695,11 +696,11 @@ static void gen_test_cc(int cc, int label) ...@@ -695,11 +696,11 @@ static void gen_test_cc(int cc, int label)
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
break; break;
case 4: /* mi: N */ case 4: /* mi: N */
tmp = load_cpu_field(NZF); tmp = load_cpu_field(NF);
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
break; break;
case 5: /* pl: !N */ case 5: /* pl: !N */
tmp = load_cpu_field(NZF); tmp = load_cpu_field(NF);
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
break; break;
case 6: /* vs: V */ case 6: /* vs: V */
...@@ -715,7 +716,7 @@ static void gen_test_cc(int cc, int label) ...@@ -715,7 +716,7 @@ static void gen_test_cc(int cc, int label)
tmp = load_cpu_field(CF); tmp = load_cpu_field(CF);
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
dead_tmp(tmp); dead_tmp(tmp);
tmp = load_cpu_field(NZF); tmp = load_cpu_field(ZF);
tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
gen_set_label(inv); gen_set_label(inv);
break; break;
...@@ -723,41 +724,41 @@ static void gen_test_cc(int cc, int label) ...@@ -723,41 +724,41 @@ static void gen_test_cc(int cc, int label)
tmp = load_cpu_field(CF); tmp = load_cpu_field(CF);
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
dead_tmp(tmp); dead_tmp(tmp);
tmp = load_cpu_field(NZF); tmp = load_cpu_field(ZF);
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
break; break;
case 10: /* ge: N == V -> N ^ V == 0 */ case 10: /* ge: N == V -> N ^ V == 0 */
tmp = load_cpu_field(VF); tmp = load_cpu_field(VF);
tmp2 = load_cpu_field(NZF); tmp2 = load_cpu_field(NF);
tcg_gen_xor_i32(tmp, tmp, tmp2); tcg_gen_xor_i32(tmp, tmp, tmp2);
dead_tmp(tmp2); dead_tmp(tmp2);
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
break; break;
case 11: /* lt: N != V -> N ^ V != 0 */ case 11: /* lt: N != V -> N ^ V != 0 */
tmp = load_cpu_field(VF); tmp = load_cpu_field(VF);
tmp2 = load_cpu_field(NZF); tmp2 = load_cpu_field(NF);
tcg_gen_xor_i32(tmp, tmp, tmp2); tcg_gen_xor_i32(tmp, tmp, tmp2);
dead_tmp(tmp2); dead_tmp(tmp2);
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
break; break;
case 12: /* gt: !Z && N == V */ case 12: /* gt: !Z && N == V */
inv = gen_new_label(); inv = gen_new_label();
tmp = load_cpu_field(NZF); tmp = load_cpu_field(ZF);
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
dead_tmp(tmp); dead_tmp(tmp);
tmp = load_cpu_field(VF); tmp = load_cpu_field(VF);
tmp2 = load_cpu_field(NZF); tmp2 = load_cpu_field(NF);
tcg_gen_xor_i32(tmp, tmp, tmp2); tcg_gen_xor_i32(tmp, tmp, tmp2);
dead_tmp(tmp2); dead_tmp(tmp2);
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
gen_set_label(inv); gen_set_label(inv);
break; break;
case 13: /* le: Z || N != V */ 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); tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
dead_tmp(tmp); dead_tmp(tmp);
tmp = load_cpu_field(VF); tmp = load_cpu_field(VF);
tmp2 = load_cpu_field(NZF); tmp2 = load_cpu_field(NF);
tcg_gen_xor_i32(tmp, tmp, tmp2); tcg_gen_xor_i32(tmp, tmp, tmp2);
dead_tmp(tmp2); dead_tmp(tmp2);
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
...@@ -5641,7 +5642,8 @@ static void gen_logicq_cc(TCGv val) ...@@ -5641,7 +5642,8 @@ static void gen_logicq_cc(TCGv val)
{ {
TCGv tmp = new_tmp(); TCGv tmp = new_tmp();
gen_helper_logicq_cc(tmp, val); 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) static void disas_arm_insn(CPUState * env, DisasContext *s)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册