Fix POWER abs & abso computation.
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 11 Nov 2007 00:33:08 +0000 (00:33 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 11 Nov 2007 00:33:08 +0000 (00:33 +0000)
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
target-ppc/op_helper.c

index bbc5c5b9a51166cb5874721f166ada3e81e27cb4..81c426c1a72c5bbef0f9794026e642fde87f5d01 100644 (file)
@@ -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();
 }
index 75bf33bff1ecf7f6c08eae833ec3135b5ef27421..7d1411a1fdd451c6d0e4f7bd17e87eb8021044ef 100644 (file)
@@ -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;
 }