From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52219) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YsEAd-0007lB-GG for qemu-devel@nongnu.org; Tue, 12 May 2015 13:40:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YsEAc-0007j2-21 for qemu-devel@nongnu.org; Tue, 12 May 2015 13:40:43 -0400 Received: from mail-qc0-x230.google.com ([2607:f8b0:400d:c01::230]:35198) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YsEAb-0007is-Sd for qemu-devel@nongnu.org; Tue, 12 May 2015 13:40:41 -0400 Received: by qcbgu10 with SMTP id gu10so8590860qcb.2 for ; Tue, 12 May 2015 10:40:41 -0700 (PDT) Received: from anchor.com (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPSA id f4sm13701736qhe.9.2015.05.12.10.40.40 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 12 May 2015 10:40:40 -0700 (PDT) Sender: Richard Henderson From: Richard Henderson Date: Tue, 12 May 2015 10:39:41 -0700 Message-Id: <1431452387-20280-12-git-send-email-rth@twiddle.net> In-Reply-To: <1431452387-20280-1-git-send-email-rth@twiddle.net> References: <1431452387-20280-1-git-send-email-rth@twiddle.net> Subject: [Qemu-devel] [PATCH v2 11/17] target-alpha: Fix integer overflow checking insns List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org We need to write the result to the destination register before raising any exception. Thus inline the code for each insn, and check for any exception after we're done. Reported-by: Al Viro Signed-off-by: Richard Henderson --- target-alpha/helper.h | 7 +----- target-alpha/int_helper.c | 59 ++-------------------------------------------- target-alpha/translate.c | 60 +++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 70 deletions(-) diff --git a/target-alpha/helper.h b/target-alpha/helper.h index 9e7b771..5b1a5d9 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -1,12 +1,7 @@ DEF_HELPER_3(excp, noreturn, env, int, int) DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_NO_RWG_SE, i64, env) -DEF_HELPER_FLAGS_3(addqv, TCG_CALL_NO_WG, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(addlv, TCG_CALL_NO_WG, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(subqv, TCG_CALL_NO_WG, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(sublv, TCG_CALL_NO_WG, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(mullv, TCG_CALL_NO_WG, i64, env, i64, i64) -DEF_HELPER_FLAGS_3(mulqv, TCG_CALL_NO_WG, i64, env, i64, i64) +DEF_HELPER_FLAGS_3(check_overflow, TCG_CALL_NO_WG, void, env, i64, i64) DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(ctlz, TCG_CALL_NO_RWG_SE, i64, i64) diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c index 7a205eb..8e4537f 100644 --- a/target-alpha/int_helper.c +++ b/target-alpha/int_helper.c @@ -249,64 +249,9 @@ uint64_t helper_unpkbw(uint64_t op1) | ((op1 & 0xff000000) << 24)); } -uint64_t helper_addqv(CPUAlphaState *env, uint64_t op1, uint64_t op2) +void helper_check_overflow(CPUAlphaState *env, uint64_t op1, uint64_t op2) { - uint64_t tmp = op1; - op1 += op2; - if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) { + if (unlikely(op1 != op2)) { arith_excp(env, GETPC(), EXC_M_IOV, 0); } - return op1; -} - -uint64_t helper_addlv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - uint64_t tmp = op1; - op1 = (uint32_t)(op1 + op2); - if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return op1; -} - -uint64_t helper_subqv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - uint64_t res; - res = op1 - op2; - if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return res; -} - -uint64_t helper_sublv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - uint32_t res; - res = op1 - op2; - if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return res; -} - -uint64_t helper_mullv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - int64_t res = (int64_t)op1 * (int64_t)op2; - - if (unlikely((int32_t)res != res)) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return (int64_t)((int32_t)res); -} - -uint64_t helper_mulqv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - uint64_t tl, th; - - muls64(&tl, &th, op1, op2); - /* If th != 0 && th != -1, then we had an overflow */ - if (unlikely((th + 1) > 1)) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return tl; } diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 7868cc4..74f5d07 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -1362,7 +1362,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) uint16_t fn11; uint8_t opc, ra, rb, rc, fpfn, fn7, lit; bool islit; - TCGv va, vb, vc, tmp; + TCGv va, vb, vc, tmp, tmp2; TCGv_i32 t32; ExitStatus ret; @@ -1574,11 +1574,23 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x40: /* ADDL/V */ - gen_helper_addlv(vc, cpu_env, va, vb); + tmp = tcg_temp_new(); + tcg_gen_ext32s_i64(tmp, va); + tcg_gen_ext32s_i64(vc, vb); + tcg_gen_add_i64(tmp, tmp, vc); + tcg_gen_ext32s_i64(vc, tmp); + gen_helper_check_overflow(cpu_env, vc, tmp); + tcg_temp_free(tmp); break; case 0x49: /* SUBL/V */ - gen_helper_sublv(vc, cpu_env, va, vb); + tmp = tcg_temp_new(); + tcg_gen_ext32s_i64(tmp, va); + tcg_gen_ext32s_i64(vc, vb); + tcg_gen_sub_i64(tmp, tmp, vc); + tcg_gen_ext32s_i64(vc, tmp); + gen_helper_check_overflow(cpu_env, vc, tmp); + tcg_temp_free(tmp); break; case 0x4D: /* CMPLT */ @@ -1586,11 +1598,33 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x60: /* ADDQ/V */ - gen_helper_addqv(vc, cpu_env, va, vb); + tmp = tcg_temp_new(); + tmp2 = tcg_temp_new(); + tcg_gen_eqv_i64(tmp, va, vb); + tcg_gen_mov_i64(tmp2, va); + tcg_gen_add_i64(vc, va, vb); + tcg_gen_xor_i64(tmp2, tmp2, vc); + tcg_gen_and_i64(tmp, tmp, tmp2); + tcg_gen_shri_i64(tmp, tmp, 63); + tcg_gen_movi_i64(tmp2, 0); + gen_helper_check_overflow(cpu_env, tmp, tmp2); + tcg_temp_free(tmp); + tcg_temp_free(tmp2); break; case 0x69: /* SUBQ/V */ - gen_helper_subqv(vc, cpu_env, va, vb); + tmp = tcg_temp_new(); + tmp2 = tcg_temp_new(); + tcg_gen_xor_i64(tmp, va, vb); + tcg_gen_mov_i64(tmp2, va); + tcg_gen_sub_i64(vc, va, vb); + tcg_gen_xor_i64(tmp2, tmp2, vc); + tcg_gen_and_i64(tmp, tmp, tmp2); + tcg_gen_shri_i64(tmp, tmp, 63); + tcg_gen_movi_i64(tmp2, 0); + gen_helper_check_overflow(cpu_env, tmp, tmp2); + tcg_temp_free(tmp); + tcg_temp_free(tmp2); break; case 0x6D: /* CMPLE */ @@ -1885,11 +1919,23 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) break; case 0x40: /* MULL/V */ - gen_helper_mullv(vc, cpu_env, va, vb); + tmp = tcg_temp_new(); + tcg_gen_ext32s_i64(tmp, va); + tcg_gen_ext32s_i64(vc, vb); + tcg_gen_mul_i64(tmp, tmp, vc); + tcg_gen_ext32s_i64(vc, tmp); + gen_helper_check_overflow(cpu_env, vc, tmp); + tcg_temp_free(tmp); break; case 0x60: /* MULQ/V */ - gen_helper_mulqv(vc, cpu_env, va, vb); + tmp = tcg_temp_new(); + tmp2 = tcg_temp_new(); + tcg_gen_muls2_i64(vc, tmp, va, vb); + tcg_gen_sari_i64(tmp2, vc, 63); + gen_helper_check_overflow(cpu_env, tmp, tmp2); + tcg_temp_free(tmp); + tcg_temp_free(tmp2); break; default: goto invalid_opc; -- 2.1.0