Signed-off-by: Richard Henderson <r...@twiddle.net> --- target-m68k/helper.c | 40 ----------------------------- target-m68k/helper.h | 2 -- target-m68k/translate.c | 67 +++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 56 insertions(+), 53 deletions(-)
diff --git a/target-m68k/helper.c b/target-m68k/helper.c index 6bd80a5..519eef3 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -275,46 +275,6 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t v) return val; } -uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2) -{ - uint32_t res, new_x; - - if (env->cc_x) { - new_x = (op1 <= op2); - res = op1 - (op2 + 1); - } else { - new_x = (op1 < op2); - res = op1 - op2; - } - env->cc_x = new_x; - env->cc_c = new_x; - env->cc_n = res; - env->cc_z |= res; /* !Z is sticky */ - env->cc_v = (res ^ op1) & (op1 ^ op2); - - return res; -} - -uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2) -{ - uint32_t res, new_x; - - if (env->cc_x) { - res = op1 + op2 + 1; - new_x = (res <= op2); - } else { - res = op1 + op2; - new_x = (res < op2); - } - env->cc_x = new_x; - env->cc_c = new_x; - env->cc_n = res; - env->cc_z |= res; /* !Z is sticky. */ - env->cc_v = (res ^ op1) & ~(op1 ^ op2); - - return res; -} - void HELPER(set_sr)(CPUM68KState *env, uint32_t val) { env->sr = val & 0xffe0; diff --git a/target-m68k/helper.h b/target-m68k/helper.h index 9985f9b..aae01f9 100644 --- a/target-m68k/helper.h +++ b/target-m68k/helper.h @@ -3,8 +3,6 @@ DEF_HELPER_1(ff1, i32, i32) DEF_HELPER_FLAGS_2(sats, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_2(divu, void, env, i32) DEF_HELPER_2(divs, void, env, i32) -DEF_HELPER_3(addx_cc, i32, env, i32, i32) -DEF_HELPER_3(subx_cc, i32, env, i32, i32) DEF_HELPER_2(set_sr, void, env, i32) DEF_HELPER_3(movec, void, env, i32, i32) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index a536054..33d6747 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1527,11 +1527,27 @@ DISAS_INSN(move) DISAS_INSN(negx) { - TCGv reg; + TCGv reg, z; - gen_flush_flags(s); reg = DREG(insn, 0); - gen_helper_subx_cc(reg, cpu_env, tcg_const_i32(0), reg); + + /* Perform subtraction with borrow. */ + z = tcg_const_i32(0); + tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, reg, z, QREG_CC_X, z); + tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, z, z, QREG_CC_N, QREG_CC_X); + tcg_temp_free(z); + tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1); + + /* Compute signed-overflow for negation. The normal formula for + subtraction is (res ^ src1) & (src1 ^ src2), but with src1==0 + this simplies to res & src2. */ + tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, reg); + + /* Copy the rest of the results into place. */ + tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); + tcg_gen_mov_i32(reg, QREG_CC_N); + set_cc_op(s, CC_OP_FLAGS); } DISAS_INSN(lea) @@ -1951,13 +1967,28 @@ DISAS_INSN(suba) DISAS_INSN(subx) { - TCGv reg; - TCGv src; + TCGv reg, src, z; - gen_flush_flags(s); reg = DREG(insn, 9); src = DREG(insn, 0); - gen_helper_subx_cc(reg, cpu_env, reg, src); + + /* Perform subtract with borrow. */ + z = tcg_const_i32(0); + tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z); + tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, reg, z, QREG_CC_N, QREG_CC_X); + tcg_temp_free(z); + tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1); + + /* Compute signed-overflow for subtraction. */ + tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg); + tcg_gen_xor_i32(QREG_CC_Z, reg, src); + tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, QREG_CC_Z); + + /* Copy the rest of the results into place. */ + tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); + tcg_gen_mov_i32(reg, QREG_CC_N); + set_cc_op(s, CC_OP_FLAGS); } DISAS_INSN(mov3q) @@ -2051,13 +2082,27 @@ DISAS_INSN(adda) DISAS_INSN(addx) { - TCGv reg; - TCGv src; + TCGv reg, src, z; - gen_flush_flags(s); reg = DREG(insn, 9); src = DREG(insn, 0); - gen_helper_addx_cc(reg, cpu_env, reg, src); + + /* Perform addition with carry. */ + z = tcg_const_i32(0); + tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, z, reg, z); + tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, z); + tcg_temp_free(z); + + /* Compute signed-overflow for addition. */ + tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, reg); + tcg_gen_xor_i32(QREG_CC_Z, reg, src); + tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, QREG_CC_Z); + + /* Copy the rest of the results into place. */ + tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N); + tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X); + tcg_gen_mov_i32(reg, QREG_CC_N); + set_cc_op(s, CC_OP_FLAGS); } DISAS_INSN(shift_im) -- 2.4.3