From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52411) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YDykZ-0006kI-IT for qemu-devel@nongnu.org; Wed, 21 Jan 2015 12:07:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YDykU-0005eD-GZ for qemu-devel@nongnu.org; Wed, 21 Jan 2015 12:07:27 -0500 Received: from mail.uni-paderborn.de ([131.234.142.9]:39511) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YDykU-0005e1-7z for qemu-devel@nongnu.org; Wed, 21 Jan 2015 12:07:22 -0500 From: Bastian Koppelmann Date: Wed, 21 Jan 2015 18:08:12 +0000 Message-Id: <1421863692-8145-5-git-send-email-kbastian@mail.uni-paderborn.de> In-Reply-To: <1421863692-8145-1-git-send-email-kbastian@mail.uni-paderborn.de> References: <1421863692-8145-1-git-send-email-kbastian@mail.uni-paderborn.de> Subject: [Qemu-devel] [PATCH 4/4] target-tricore: split up suov32 into suov32_pos and suov32_neg List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org suov checks unsigned for an overflow and an underflow, after some arithmetic operations and saturates the result to either max_uint32 or 0. So far we handled this by expanding to the next bigger data type and compare whether the result is > max_uint32 or < 0. However this approach can fail for an 32 bit multiplication, if both operands of the multiplication are 0x80000000. This sets the sign bit of the 64 bit integer and would result in a false saturation to 0. Since unsigned operations, e.g add, sub, mul always result in either a positive or negative overflow, we split the functions for suov32 up into two functions (suov32_pos, suov32_neg) for each case. Signed-off-by: Bastian Koppelmann --- target-tricore/op_helper.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 889d045..71dcb70 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -80,29 +80,40 @@ static uint32_t ssov32(CPUTriCoreState *env, int64_t arg) return ret; } -static uint32_t suov32(CPUTriCoreState *env, int64_t arg) +static uint32_t suov32_pos(CPUTriCoreState *env, uint64_t arg) { uint32_t ret; - int64_t max_pos = UINT32_MAX; + uint64_t max_pos = UINT32_MAX; if (arg > max_pos) { env->PSW_USB_V = (1 << 31); env->PSW_USB_SV = (1 << 31); ret = (target_ulong)max_pos; } else { - if (arg < 0) { - env->PSW_USB_V = (1 << 31); - env->PSW_USB_SV = (1 << 31); - ret = 0; - } else { - env->PSW_USB_V = 0; - ret = (target_ulong)arg; - } + env->PSW_USB_V = 0; + ret = (target_ulong)arg; } env->PSW_USB_AV = arg ^ arg * 2u; env->PSW_USB_SAV |= env->PSW_USB_AV; return ret; } +static uint32_t suov32_neg(CPUTriCoreState *env, int64_t arg) +{ + uint32_t ret; + + if (arg < 0) { + env->PSW_USB_V = (1 << 31); + env->PSW_USB_SV = (1 << 31); + ret = 0; + } else { + env->PSW_USB_V = 0; + ret = (target_ulong)arg; + } + env->PSW_USB_AV = arg ^ arg * 2u; + env->PSW_USB_SAV |= env->PSW_USB_AV; + return ret; +} + static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1) { int32_t max_pos = INT16_MAX; @@ -189,7 +200,7 @@ target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1, int64_t t1 = extract64(r1, 0, 32); int64_t t2 = extract64(r2, 0, 32); int64_t result = t1 + t2; - return suov32(env, result); + return suov32_pos(env, result); } target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1, @@ -227,7 +238,7 @@ target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1, int64_t t1 = extract64(r1, 0, 32); int64_t t2 = extract64(r2, 0, 32); int64_t result = t1 - t2; - return suov32(env, result); + return suov32_neg(env, result); } target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1, @@ -256,7 +267,7 @@ target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1, int64_t t2 = extract64(r2, 0, 32); int64_t result = t1 * t2; - return suov32(env, result); + return suov32_pos(env, result); } target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1, @@ -356,7 +367,7 @@ target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1, int64_t result; result = t2 + (t1 * t3); - return suov32(env, result); + return suov32_pos(env, result); } uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1, @@ -438,7 +449,7 @@ target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1, int64_t result; result = t2 - (t1 * t3); - return suov32(env, result); + return suov32_neg(env, result); } uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1, -- 2.2.2