diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-11-11 00:33:08 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-11-11 00:33:08 +0000 |
commit | 9c7e37e7fad48f6e7bbafa29f7980a4a9bf191b7 (patch) | |
tree | fc76114a27a92796895ecb341b875c19ef0d5d07 /target-ppc | |
parent | c3e10c7b4377c1cbc0a4fbc12312c2cf41c0cda7 (diff) |
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
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/op.c | 4 | ||||
-rw-r--r-- | 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; } |