Revision 6fbe23d5
b/target-arm/cpu.h | ||
---|---|---|
86 | 86 |
/* cpsr flag cache for faster execution */ |
87 | 87 |
uint32_t CF; /* 0 or 1 */ |
88 | 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 | 91 |
uint32_t QF; /* 0 or 1 */ |
91 | 92 |
uint32_t GE; /* cpsr[19:16] */ |
92 | 93 |
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */ |
... | ... | |
254 | 255 |
static inline uint32_t xpsr_read(CPUARMState *env) |
255 | 256 |
{ |
256 | 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 | 260 |
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) |
260 | 261 |
| (env->thumb << 24) | ((env->condexec_bits & 3) << 25) |
261 | 262 |
| ((env->condexec_bits & 0xfc) << 8) |
... | ... | |
265 | 266 |
/* Set the xPSR. Note that some bits of mask must be all-set or all-clear. */ |
266 | 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 | 269 |
if (mask & CPSR_NZCV) { |
270 |
env->NZF = (val & 0xc0000000) ^ 0x40000000; |
|
270 |
env->ZF = (~val) & CPSR_Z; |
|
271 |
env->NF = val; |
|
271 | 272 |
env->CF = (val >> 29) & 1; |
272 | 273 |
env->VF = (val << 3) & 0x80000000; |
273 | 274 |
} |
b/target-arm/helper.c | ||
---|---|---|
259 | 259 |
uint32_t cpsr_read(CPUARMState *env) |
260 | 260 |
{ |
261 | 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 | 264 |
(env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27) |
265 | 265 |
| (env->thumb << 5) | ((env->condexec_bits & 3) << 25) |
266 | 266 |
| ((env->condexec_bits & 0xfc) << 8) |
... | ... | |
269 | 269 |
|
270 | 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 | 272 |
if (mask & CPSR_NZCV) { |
274 |
env->NZF = (val & 0xc0000000) ^ 0x40000000; |
|
273 |
env->ZF = (~val) & CPSR_Z; |
|
274 |
env->NF = val; |
|
275 | 275 |
env->CF = (val >> 29) & 1; |
276 | 276 |
env->VF = (val << 3) & 0x80000000; |
277 | 277 |
} |
... | ... | |
1690 | 1690 |
} |
1691 | 1691 |
} |
1692 | 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 | 1695 |
return 0; |
1698 | 1696 |
case 8: /* MMU TLB control. */ |
1699 | 1697 |
goto bad_reg; |
b/target-arm/op_helper.c | ||
---|---|---|
315 | 315 |
{ |
316 | 316 |
uint32_t result; |
317 | 317 |
result = T0 + T1; |
318 |
env->NZF = result; |
|
318 |
env->NF = env->ZF = result;
|
|
319 | 319 |
env->CF = result < a; |
320 | 320 |
env->VF = (a ^ b ^ -1) & (a ^ result); |
321 | 321 |
return result; |
... | ... | |
332 | 332 |
env->CF = result <= a; |
333 | 333 |
} |
334 | 334 |
env->VF = (a ^ b ^ -1) & (a ^ result); |
335 |
env->NZF = result; |
|
335 |
env->NF = env->ZF = result;
|
|
336 | 336 |
return result; |
337 | 337 |
} |
338 | 338 |
|
... | ... | |
340 | 340 |
{ |
341 | 341 |
uint32_t result; |
342 | 342 |
result = a - b; |
343 |
env->NZF = result; |
|
343 |
env->NF = env->ZF = result;
|
|
344 | 344 |
env->CF = a >= b; |
345 | 345 |
env->VF = (a ^ b) & (a ^ result); |
346 | 346 |
return result; |
... | ... | |
357 | 357 |
env->CF = a >= b; |
358 | 358 |
} |
359 | 359 |
env->VF = (a ^ b) & (a ^ result); |
360 |
env->NZF = result; |
|
360 |
env->NF = env->ZF = result;
|
|
361 | 361 |
return result; |
362 | 362 |
} |
363 | 363 |
|
b/target-arm/translate.c | ||
---|---|---|
423 | 423 |
/* Set N and Z flags from var. */ |
424 | 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 | 430 |
/* T0 += T1 + CF. */ |
... | ... | |
679 | 680 |
zero = tcg_const_i32(0); |
680 | 681 |
switch (cc) { |
681 | 682 |
case 0: /* eq: Z */ |
682 |
tmp = load_cpu_field(NZF);
|
|
683 |
tmp = load_cpu_field(ZF); |
|
683 | 684 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
684 | 685 |
break; |
685 | 686 |
case 1: /* ne: !Z */ |
686 |
tmp = load_cpu_field(NZF);
|
|
687 |
tmp = load_cpu_field(ZF); |
|
687 | 688 |
tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); |
688 | 689 |
break; |
689 | 690 |
case 2: /* cs: C */ |
... | ... | |
695 | 696 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
696 | 697 |
break; |
697 | 698 |
case 4: /* mi: N */ |
698 |
tmp = load_cpu_field(NZF);
|
|
699 |
tmp = load_cpu_field(NF); |
|
699 | 700 |
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
700 | 701 |
break; |
701 | 702 |
case 5: /* pl: !N */ |
702 |
tmp = load_cpu_field(NZF);
|
|
703 |
tmp = load_cpu_field(NF); |
|
703 | 704 |
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
704 | 705 |
break; |
705 | 706 |
case 6: /* vs: V */ |
... | ... | |
715 | 716 |
tmp = load_cpu_field(CF); |
716 | 717 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); |
717 | 718 |
dead_tmp(tmp); |
718 |
tmp = load_cpu_field(NZF);
|
|
719 |
tmp = load_cpu_field(ZF); |
|
719 | 720 |
tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); |
720 | 721 |
gen_set_label(inv); |
721 | 722 |
break; |
... | ... | |
723 | 724 |
tmp = load_cpu_field(CF); |
724 | 725 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
725 | 726 |
dead_tmp(tmp); |
726 |
tmp = load_cpu_field(NZF);
|
|
727 |
tmp = load_cpu_field(ZF); |
|
727 | 728 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
728 | 729 |
break; |
729 | 730 |
case 10: /* ge: N == V -> N ^ V == 0 */ |
730 | 731 |
tmp = load_cpu_field(VF); |
731 |
tmp2 = load_cpu_field(NZF);
|
|
732 |
tmp2 = load_cpu_field(NF); |
|
732 | 733 |
tcg_gen_xor_i32(tmp, tmp, tmp2); |
733 | 734 |
dead_tmp(tmp2); |
734 | 735 |
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
735 | 736 |
break; |
736 | 737 |
case 11: /* lt: N != V -> N ^ V != 0 */ |
737 | 738 |
tmp = load_cpu_field(VF); |
738 |
tmp2 = load_cpu_field(NZF);
|
|
739 |
tmp2 = load_cpu_field(NF); |
|
739 | 740 |
tcg_gen_xor_i32(tmp, tmp, tmp2); |
740 | 741 |
dead_tmp(tmp2); |
741 | 742 |
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
742 | 743 |
break; |
743 | 744 |
case 12: /* gt: !Z && N == V */ |
744 | 745 |
inv = gen_new_label(); |
745 |
tmp = load_cpu_field(NZF);
|
|
746 |
tmp = load_cpu_field(ZF); |
|
746 | 747 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); |
747 | 748 |
dead_tmp(tmp); |
748 | 749 |
tmp = load_cpu_field(VF); |
749 |
tmp2 = load_cpu_field(NZF);
|
|
750 |
tmp2 = load_cpu_field(NF); |
|
750 | 751 |
tcg_gen_xor_i32(tmp, tmp, tmp2); |
751 | 752 |
dead_tmp(tmp2); |
752 | 753 |
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
753 | 754 |
gen_set_label(inv); |
754 | 755 |
break; |
755 | 756 |
case 13: /* le: Z || N != V */ |
756 |
tmp = load_cpu_field(NZF);
|
|
757 |
tmp = load_cpu_field(ZF); |
|
757 | 758 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
758 | 759 |
dead_tmp(tmp); |
759 | 760 |
tmp = load_cpu_field(VF); |
760 |
tmp2 = load_cpu_field(NZF);
|
|
761 |
tmp2 = load_cpu_field(NF); |
|
761 | 762 |
tcg_gen_xor_i32(tmp, tmp, tmp2); |
762 | 763 |
dead_tmp(tmp2); |
763 | 764 |
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
... | ... | |
5641 | 5642 |
{ |
5642 | 5643 |
TCGv tmp = new_tmp(); |
5643 | 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 | 5649 |
static void disas_arm_insn(CPUState * env, DisasContext *s) |
Also available in: Unified diff