diff options
Diffstat (limited to 'target-m68k/translate.c')
-rw-r--r-- | target-m68k/translate.c | 56 |
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; } |