Commit 9c7e37e7fad48f6e7bbafa29f7980a4a9bf191b7
1 parent
c3e10c7b
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
Showing
2 changed files
with
10 additions
and
8 deletions
target-ppc/op.c
| ... | ... | @@ -2199,9 +2199,9 @@ void OPPROTO op_store_601_batu (void) |
| 2199 | 2199 | /* XXX: those micro-ops need tests ! */ |
| 2200 | 2200 | void OPPROTO op_POWER_abs (void) |
| 2201 | 2201 | { |
| 2202 | - if (T0 == INT32_MIN) | |
| 2202 | + if ((int32_t)T0 == INT32_MIN) | |
| 2203 | 2203 | T0 = INT32_MAX; |
| 2204 | - else if (T0 < 0) | |
| 2204 | + else if ((int32_t)T0 < 0) | |
| 2205 | 2205 | T0 = -T0; |
| 2206 | 2206 | RETURN(); |
| 2207 | 2207 | } | ... | ... |
target-ppc/op_helper.c
| ... | ... | @@ -1512,14 +1512,16 @@ void do_td (int flags) |
| 1512 | 1512 | /* PowerPC 601 specific instructions (POWER bridge) */ |
| 1513 | 1513 | void do_POWER_abso (void) |
| 1514 | 1514 | { |
| 1515 | - if ((uint32_t)T0 == INT32_MIN) { | |
| 1515 | + if ((int32_t)T0 == INT32_MIN) { | |
| 1516 | 1516 | T0 = INT32_MAX; |
| 1517 | 1517 | xer_ov = 1; |
| 1518 | - xer_so = 1; | |
| 1519 | - } else { | |
| 1518 | + } else if ((int32_t)T0 < 0) { | |
| 1520 | 1519 | T0 = -T0; |
| 1521 | 1520 | xer_ov = 0; |
| 1521 | + } else { | |
| 1522 | + xer_ov = 0; | |
| 1522 | 1523 | } |
| 1524 | + xer_so |= xer_ov; | |
| 1523 | 1525 | } |
| 1524 | 1526 | |
| 1525 | 1527 | void do_POWER_clcs (void) |
| ... | ... | @@ -1896,8 +1898,8 @@ void do_ev##name (void) \ |
| 1896 | 1898 | /* Fixed-point vector arithmetic */ |
| 1897 | 1899 | static always_inline uint32_t _do_eabs (uint32_t val) |
| 1898 | 1900 | { |
| 1899 | - if (val != 0x80000000) | |
| 1900 | - val &= ~0x80000000; | |
| 1901 | + if ((val & 0x80000000) && val != 0x80000000) | |
| 1902 | + val -= val; | |
| 1901 | 1903 | |
| 1902 | 1904 | return val; |
| 1903 | 1905 | } |
| ... | ... | @@ -1923,7 +1925,7 @@ static always_inline int _do_ecntlzw (uint32_t val) |
| 1923 | 1925 | static always_inline uint32_t _do_eneg (uint32_t val) |
| 1924 | 1926 | { |
| 1925 | 1927 | if (val != 0x80000000) |
| 1926 | - val ^= 0x80000000; | |
| 1928 | + val -= val; | |
| 1927 | 1929 | |
| 1928 | 1930 | return val; |
| 1929 | 1931 | } | ... | ... |