From 46a8dfff5902bbf839b901067aa99fea9c1540a8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Nov 2019 00:00:15 -0500 Subject: [PATCH] target/arm: Fix SMMLS argument order The previous simplification got the order of operands to the subtraction wrong. Since the 64-bit product is the subtrahend, we must use a 64-bit subtract to properly compute the borrow from the low-part of the product. Fixes: 5f8cd06ebcf5 ("target/arm: Simplify SMMLA, SMMLAR, SMMLS, SMMLSR") Backports commit e0a0c8322b8ebcdad674f443a3e86db8708d6738 from qemu --- qemu/target/arm/translate.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) 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); }