summaryrefslogtreecommitdiff
path: root/target-m68k
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2015-08-14 07:59:24 -0700
committerLaurent Vivier <laurent@vivier.eu>2016-10-25 20:54:47 +0200
commit36f0399d46f2ccf4f6e7451ba46b1e8d0e9ab341 (patch)
tree3402fcea023d29b3a93cf93f243220cf89dc1f54 /target-m68k
parent9d896621c1820fd8f437fac26fd7d2e0921091c3 (diff)
downloadqemu-36f0399d46f2ccf4f6e7451ba46b1e8d0e9ab341.tar.gz
target-m68k: Optimize gen_flush_flags
Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'target-m68k')
-rw-r--r--target-m68k/translate.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 52aa800f11..6c6173a09e 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -458,18 +458,66 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
static void gen_flush_flags(DisasContext *s)
{
- TCGv tmp;
+ TCGv t0, t1;
switch (s->cc_op) {
case CC_OP_FLAGS:
return;
+
+ case CC_OP_ADD:
+ tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
+ tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+ /* Compute signed overflow for addition. */
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ tcg_gen_sub_i32(t0, QREG_CC_N, QREG_CC_V);
+ tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
+ tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
+ tcg_temp_free(t0);
+ tcg_gen_andc_i32(QREG_CC_V, t1, QREG_CC_V);
+ tcg_temp_free(t1);
+ break;
+
+ case CC_OP_SUB:
+ tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
+ tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+ /* Compute signed overflow for subtraction. */
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V);
+ tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
+ tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
+ tcg_temp_free(t0);
+ tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t1);
+ tcg_temp_free(t1);
+ break;
+
+ case CC_OP_CMP:
+ tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_C, QREG_CC_N, QREG_CC_V);
+ tcg_gen_sub_i32(QREG_CC_Z, QREG_CC_N, QREG_CC_V);
+ /* Compute signed overflow for subtraction. */
+ t0 = tcg_temp_new();
+ tcg_gen_xor_i32(t0, QREG_CC_Z, QREG_CC_N);
+ tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, QREG_CC_N);
+ tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t0);
+ tcg_temp_free(t0);
+ tcg_gen_mov_i32(QREG_CC_N, QREG_CC_Z);
+ break;
+
+ case CC_OP_LOGIC:
+ tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+ tcg_gen_movi_i32(QREG_CC_C, 0);
+ tcg_gen_movi_i32(QREG_CC_V, 0);
+ break;
+
case CC_OP_DYNAMIC:
gen_helper_flush_flags(cpu_env, QREG_CC_OP);
break;
+
default:
- tmp = tcg_const_i32(s->cc_op);
- gen_helper_flush_flags(cpu_env, tmp);
- tcg_temp_free(tmp);
+ t0 = tcg_const_i32(s->cc_op);
+ gen_helper_flush_flags(cpu_env, t0);
+ tcg_temp_free(t0);
break;
}