Commit 6fbe23d50ed24044ac2d12281b0e7d580a2374d9
1 parent
f5d28393
ARM N=Z=1 flag fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4156 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
32 additions
and
31 deletions
target-arm/cpu.h
@@ -86,7 +86,8 @@ typedef struct CPUARMState { | @@ -86,7 +86,8 @@ typedef struct CPUARMState { | ||
86 | /* cpsr flag cache for faster execution */ | 86 | /* cpsr flag cache for faster execution */ |
87 | uint32_t CF; /* 0 or 1 */ | 87 | uint32_t CF; /* 0 or 1 */ |
88 | uint32_t VF; /* V is the bit 31. All other bits are undefined */ | 88 | uint32_t VF; /* V is the bit 31. All other bits are undefined */ |
89 | - uint32_t NZF; /* N is bit 31. Z is computed from NZF */ | 89 | + uint32_t NF; /* N is bit 31. All other bits are undefined. */ |
90 | + uint32_t ZF; /* Z set if zero. */ | ||
90 | uint32_t QF; /* 0 or 1 */ | 91 | uint32_t QF; /* 0 or 1 */ |
91 | uint32_t GE; /* cpsr[19:16] */ | 92 | uint32_t GE; /* cpsr[19:16] */ |
92 | uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */ | 93 | 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); | ||
254 | static inline uint32_t xpsr_read(CPUARMState *env) | 255 | static inline uint32_t xpsr_read(CPUARMState *env) |
255 | { | 256 | { |
256 | int ZF; | 257 | int ZF; |
257 | - ZF = (env->NZF == 0); | ||
258 | - return (env->NZF & 0x80000000) | (ZF << 30) | 258 | + ZF = (env->ZF == 0); |
259 | + return (env->NF & 0x80000000) | (ZF << 30) | ||
259 | | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) | 260 | | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) |
260 | | (env->thumb << 24) | ((env->condexec_bits & 3) << 25) | 261 | | (env->thumb << 24) | ((env->condexec_bits & 3) << 25) |
261 | | ((env->condexec_bits & 0xfc) << 8) | 262 | | ((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) | ||
265 | /* Set the xPSR. Note that some bits of mask must be all-set or all-clear. */ | 266 | /* Set the xPSR. Note that some bits of mask must be all-set or all-clear. */ |
266 | static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) | 267 | static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) |
267 | { | 268 | { |
268 | - /* NOTE: N = 1 and Z = 1 cannot be stored currently */ | ||
269 | if (mask & CPSR_NZCV) { | 269 | if (mask & CPSR_NZCV) { |
270 | - env->NZF = (val & 0xc0000000) ^ 0x40000000; | 270 | + env->ZF = (~val) & CPSR_Z; |
271 | + env->NF = val; | ||
271 | env->CF = (val >> 29) & 1; | 272 | env->CF = (val >> 29) & 1; |
272 | env->VF = (val << 3) & 0x80000000; | 273 | env->VF = (val << 3) & 0x80000000; |
273 | } | 274 | } |
target-arm/helper.c
@@ -259,8 +259,8 @@ void cpu_arm_close(CPUARMState *env) | @@ -259,8 +259,8 @@ void cpu_arm_close(CPUARMState *env) | ||
259 | uint32_t cpsr_read(CPUARMState *env) | 259 | uint32_t cpsr_read(CPUARMState *env) |
260 | { | 260 | { |
261 | int ZF; | 261 | int ZF; |
262 | - ZF = (env->NZF == 0); | ||
263 | - return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) | | 262 | + ZF = (env->ZF == 0); |
263 | + return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) | | ||
264 | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) | 264 | (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) |
265 | | (env->thumb << 5) | ((env->condexec_bits & 3) << 25) | 265 | | (env->thumb << 5) | ((env->condexec_bits & 3) << 25) |
266 | | ((env->condexec_bits & 0xfc) << 8) | 266 | | ((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) | ||
269 | 269 | ||
270 | void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) | 270 | void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) |
271 | { | 271 | { |
272 | - /* NOTE: N = 1 and Z = 1 cannot be stored currently */ | ||
273 | if (mask & CPSR_NZCV) { | 272 | if (mask & CPSR_NZCV) { |
274 | - env->NZF = (val & 0xc0000000) ^ 0x40000000; | 273 | + env->ZF = (~val) & CPSR_Z; |
274 | + env->NF = val; | ||
275 | env->CF = (val >> 29) & 1; | 275 | env->CF = (val >> 29) & 1; |
276 | env->VF = (val << 3) & 0x80000000; | 276 | env->VF = (val << 3) & 0x80000000; |
277 | } | 277 | } |
@@ -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) | ||
1690 | } | 1690 | } |
1691 | } | 1691 | } |
1692 | case 7: /* Cache control. */ | 1692 | case 7: /* Cache control. */ |
1693 | - /* ??? This is for test, clean and invaidate operations that set the | ||
1694 | - Z flag. We can't represent N = Z = 1, so it also clears | ||
1695 | - the N flag. Oh well. */ | ||
1696 | - env->NZF = 0; | 1693 | + /* FIXME: Should only clear Z flag if destination is r15. */ |
1694 | + env->ZF = 0; | ||
1697 | return 0; | 1695 | return 0; |
1698 | case 8: /* MMU TLB control. */ | 1696 | case 8: /* MMU TLB control. */ |
1699 | goto bad_reg; | 1697 | goto bad_reg; |
target-arm/op_helper.c
@@ -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) | ||
315 | { | 315 | { |
316 | uint32_t result; | 316 | uint32_t result; |
317 | result = T0 + T1; | 317 | result = T0 + T1; |
318 | - env->NZF = result; | 318 | + env->NF = env->ZF = result; |
319 | env->CF = result < a; | 319 | env->CF = result < a; |
320 | env->VF = (a ^ b ^ -1) & (a ^ result); | 320 | env->VF = (a ^ b ^ -1) & (a ^ result); |
321 | return result; | 321 | 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) | ||
332 | env->CF = result <= a; | 332 | env->CF = result <= a; |
333 | } | 333 | } |
334 | env->VF = (a ^ b ^ -1) & (a ^ result); | 334 | env->VF = (a ^ b ^ -1) & (a ^ result); |
335 | - env->NZF = result; | 335 | + env->NF = env->ZF = result; |
336 | return result; | 336 | return result; |
337 | } | 337 | } |
338 | 338 | ||
@@ -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) | ||
340 | { | 340 | { |
341 | uint32_t result; | 341 | uint32_t result; |
342 | result = a - b; | 342 | result = a - b; |
343 | - env->NZF = result; | 343 | + env->NF = env->ZF = result; |
344 | env->CF = a >= b; | 344 | env->CF = a >= b; |
345 | env->VF = (a ^ b) & (a ^ result); | 345 | env->VF = (a ^ b) & (a ^ result); |
346 | return result; | 346 | 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) | ||
357 | env->CF = a >= b; | 357 | env->CF = a >= b; |
358 | } | 358 | } |
359 | env->VF = (a ^ b) & (a ^ result); | 359 | env->VF = (a ^ b) & (a ^ result); |
360 | - env->NZF = result; | 360 | + env->NF = env->ZF = result; |
361 | return result; | 361 | return result; |
362 | } | 362 | } |
363 | 363 |
target-arm/translate.c
@@ -423,7 +423,8 @@ static void gen_set_CF_bit31(TCGv var) | @@ -423,7 +423,8 @@ static void gen_set_CF_bit31(TCGv var) | ||
423 | /* Set N and Z flags from var. */ | 423 | /* Set N and Z flags from var. */ |
424 | static inline void gen_logic_CC(TCGv var) | 424 | static inline void gen_logic_CC(TCGv var) |
425 | { | 425 | { |
426 | - tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF)); | 426 | + tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF)); |
427 | + tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF)); | ||
427 | } | 428 | } |
428 | 429 | ||
429 | /* T0 += T1 + CF. */ | 430 | /* 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) | ||
679 | zero = tcg_const_i32(0); | 680 | zero = tcg_const_i32(0); |
680 | switch (cc) { | 681 | switch (cc) { |
681 | case 0: /* eq: Z */ | 682 | case 0: /* eq: Z */ |
682 | - tmp = load_cpu_field(NZF); | 683 | + tmp = load_cpu_field(ZF); |
683 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); | 684 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
684 | break; | 685 | break; |
685 | case 1: /* ne: !Z */ | 686 | case 1: /* ne: !Z */ |
686 | - tmp = load_cpu_field(NZF); | 687 | + tmp = load_cpu_field(ZF); |
687 | tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); | 688 | tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); |
688 | break; | 689 | break; |
689 | case 2: /* cs: C */ | 690 | 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) | ||
695 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); | 696 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
696 | break; | 697 | break; |
697 | case 4: /* mi: N */ | 698 | case 4: /* mi: N */ |
698 | - tmp = load_cpu_field(NZF); | 699 | + tmp = load_cpu_field(NF); |
699 | tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); | 700 | tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
700 | break; | 701 | break; |
701 | case 5: /* pl: !N */ | 702 | case 5: /* pl: !N */ |
702 | - tmp = load_cpu_field(NZF); | 703 | + tmp = load_cpu_field(NF); |
703 | tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); | 704 | tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
704 | break; | 705 | break; |
705 | case 6: /* vs: V */ | 706 | 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) | ||
715 | tmp = load_cpu_field(CF); | 716 | tmp = load_cpu_field(CF); |
716 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); | 717 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); |
717 | dead_tmp(tmp); | 718 | dead_tmp(tmp); |
718 | - tmp = load_cpu_field(NZF); | 719 | + tmp = load_cpu_field(ZF); |
719 | tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); | 720 | tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); |
720 | gen_set_label(inv); | 721 | gen_set_label(inv); |
721 | break; | 722 | 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) | ||
723 | tmp = load_cpu_field(CF); | 724 | tmp = load_cpu_field(CF); |
724 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); | 725 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
725 | dead_tmp(tmp); | 726 | dead_tmp(tmp); |
726 | - tmp = load_cpu_field(NZF); | 727 | + tmp = load_cpu_field(ZF); |
727 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); | 728 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
728 | break; | 729 | break; |
729 | case 10: /* ge: N == V -> N ^ V == 0 */ | 730 | case 10: /* ge: N == V -> N ^ V == 0 */ |
730 | tmp = load_cpu_field(VF); | 731 | tmp = load_cpu_field(VF); |
731 | - tmp2 = load_cpu_field(NZF); | 732 | + tmp2 = load_cpu_field(NF); |
732 | tcg_gen_xor_i32(tmp, tmp, tmp2); | 733 | tcg_gen_xor_i32(tmp, tmp, tmp2); |
733 | dead_tmp(tmp2); | 734 | dead_tmp(tmp2); |
734 | tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); | 735 | tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
735 | break; | 736 | break; |
736 | case 11: /* lt: N != V -> N ^ V != 0 */ | 737 | case 11: /* lt: N != V -> N ^ V != 0 */ |
737 | tmp = load_cpu_field(VF); | 738 | tmp = load_cpu_field(VF); |
738 | - tmp2 = load_cpu_field(NZF); | 739 | + tmp2 = load_cpu_field(NF); |
739 | tcg_gen_xor_i32(tmp, tmp, tmp2); | 740 | tcg_gen_xor_i32(tmp, tmp, tmp2); |
740 | dead_tmp(tmp2); | 741 | dead_tmp(tmp2); |
741 | tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); | 742 | tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
742 | break; | 743 | break; |
743 | case 12: /* gt: !Z && N == V */ | 744 | case 12: /* gt: !Z && N == V */ |
744 | inv = gen_new_label(); | 745 | inv = gen_new_label(); |
745 | - tmp = load_cpu_field(NZF); | 746 | + tmp = load_cpu_field(ZF); |
746 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); | 747 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); |
747 | dead_tmp(tmp); | 748 | dead_tmp(tmp); |
748 | tmp = load_cpu_field(VF); | 749 | tmp = load_cpu_field(VF); |
749 | - tmp2 = load_cpu_field(NZF); | 750 | + tmp2 = load_cpu_field(NF); |
750 | tcg_gen_xor_i32(tmp, tmp, tmp2); | 751 | tcg_gen_xor_i32(tmp, tmp, tmp2); |
751 | dead_tmp(tmp2); | 752 | dead_tmp(tmp2); |
752 | tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); | 753 | tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
753 | gen_set_label(inv); | 754 | gen_set_label(inv); |
754 | break; | 755 | break; |
755 | case 13: /* le: Z || N != V */ | 756 | case 13: /* le: Z || N != V */ |
756 | - tmp = load_cpu_field(NZF); | 757 | + tmp = load_cpu_field(ZF); |
757 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); | 758 | tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
758 | dead_tmp(tmp); | 759 | dead_tmp(tmp); |
759 | tmp = load_cpu_field(VF); | 760 | tmp = load_cpu_field(VF); |
760 | - tmp2 = load_cpu_field(NZF); | 761 | + tmp2 = load_cpu_field(NF); |
761 | tcg_gen_xor_i32(tmp, tmp, tmp2); | 762 | tcg_gen_xor_i32(tmp, tmp, tmp2); |
762 | dead_tmp(tmp2); | 763 | dead_tmp(tmp2); |
763 | tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); | 764 | 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) | ||
5641 | { | 5642 | { |
5642 | TCGv tmp = new_tmp(); | 5643 | TCGv tmp = new_tmp(); |
5643 | gen_helper_logicq_cc(tmp, val); | 5644 | gen_helper_logicq_cc(tmp, val); |
5644 | - store_cpu_field(tmp, NZF); | 5645 | + gen_logic_CC(tmp); |
5646 | + dead_tmp(tmp); | ||
5645 | } | 5647 | } |
5646 | 5648 | ||
5647 | static void disas_arm_insn(CPUState * env, DisasContext *s) | 5649 | static void disas_arm_insn(CPUState * env, DisasContext *s) |