From 9c7e37e7fad48f6e7bbafa29f7980a4a9bf191b7 Mon Sep 17 00:00:00 2001 From: j_mayer Date: Sun, 11 Nov 2007 00:33:08 +0000 Subject: [PATCH] Fix POWER abs & abso computation. Fix PowerPC SPE evabs & evneg (thanks to Fabrice Bellard for reporting the bug) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3575 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-ppc/op.c | 4 ++-- target-ppc/op_helper.c | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/target-ppc/op.c b/target-ppc/op.c index bbc5c5b9a5..81c426c1a7 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -2199,9 +2199,9 @@ void OPPROTO op_store_601_batu (void) /* XXX: those micro-ops need tests ! */ void OPPROTO op_POWER_abs (void) { - if (T0 == INT32_MIN) + if ((int32_t)T0 == INT32_MIN) T0 = INT32_MAX; - else if (T0 < 0) + else if ((int32_t)T0 < 0) T0 = -T0; RETURN(); } diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 75bf33bff1..7d1411a1fd 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -1512,14 +1512,16 @@ void do_td (int flags) /* PowerPC 601 specific instructions (POWER bridge) */ void do_POWER_abso (void) { - if ((uint32_t)T0 == INT32_MIN) { + if ((int32_t)T0 == INT32_MIN) { T0 = INT32_MAX; xer_ov = 1; - xer_so = 1; - } else { + } else if ((int32_t)T0 < 0) { T0 = -T0; xer_ov = 0; + } else { + xer_ov = 0; } + xer_so |= xer_ov; } void do_POWER_clcs (void) @@ -1896,8 +1898,8 @@ void do_ev##name (void) \ /* Fixed-point vector arithmetic */ static always_inline uint32_t _do_eabs (uint32_t val) { - if (val != 0x80000000) - val &= ~0x80000000; + if ((val & 0x80000000) && val != 0x80000000) + val -= val; return val; } @@ -1923,7 +1925,7 @@ static always_inline int _do_ecntlzw (uint32_t val) static always_inline uint32_t _do_eneg (uint32_t val) { if (val != 0x80000000) - val ^= 0x80000000; + val -= val; return val; }