diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index b7a9b03b..29f212f9 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -9016,7 +9016,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) if (rd != 15) { tmp3 = load_reg(s, rd); if (insn & (1 << 6)) { - tcg_gen_sub_i32(tcg_ctx, tmp, tmp, tmp3); + /* + * For SMMLS, we need a 64-bit subtract. + * Borrow caused by a non-zero multiplicand + * lowpart, and the correct result lowpart + * for rounding. + */ + TCGv_i32 zero = tcg_const_i32(tcg_ctx, 0); + tcg_gen_sub2_i32(tcg_ctx, tmp2, tmp, zero, tmp3, + tmp2, tmp); + tcg_temp_free_i32(tcg_ctx, zero); } else { tcg_gen_add_i32(tcg_ctx, tmp, tmp, tmp3); } @@ -10259,7 +10268,14 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) if (insn & (1 << 20)) { tcg_gen_add_i32(tcg_ctx, tmp, tmp, tmp3); } else { - tcg_gen_sub_i32(tcg_ctx, tmp, tmp, tmp3); + /* + * For SMMLS, we need a 64-bit subtract. + * Borrow caused by a non-zero multiplicand lowpart, + * and the correct result lowpart for rounding. + */ + TCGv_i32 zero = tcg_const_i32(tcg_ctx, 0); + tcg_gen_sub2_i32(tcg_ctx, tmp2, tmp, zero, tmp3, tmp2, tmp); + tcg_temp_free_i32(tcg_ctx, zero); } tcg_temp_free_i32(tcg_ctx, tmp3); }