Optimize PowerPC overflow flag computation in most useful cases.
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 11 Nov 2007 00:18:34 +0000 (00:18 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 11 Nov 2007 00:18:34 +0000 (00:18 +0000)
Use the same routines to check overflow for addo, subfo and PowerPC 405
  multiply and add cases.
Fix carry reset in addme(o) and subfme(o) cases.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3574 c046a42c-6fe2-441c-8c8c-71466251a162

target-ppc/op.c
target-ppc/op_helper.c
target-ppc/op_helper.h
target-ppc/translate.c

index 730dc0e..bbc5c5b 100644 (file)
@@ -191,6 +191,12 @@ void OPPROTO op_move_T2_T0 (void)
     RETURN();
 }
 
+void OPPROTO op_moven_T2_T0 (void)
+{
+    T2 = ~T0;
+    RETURN();
+}
+
 /* Generate exceptions */
 void OPPROTO op_raise_exception_err (void)
 {
@@ -847,26 +853,18 @@ void OPPROTO op_add (void)
 
 void OPPROTO op_check_addo (void)
 {
-    if (likely(!(((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &
-                 ((uint32_t)T2 ^ (uint32_t)T0) & (1UL << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
+    xer_ov = (((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &
+              ((uint32_t)T2 ^ (uint32_t)T0)) >> 31;
+    xer_so |= xer_ov;
     RETURN();
 }
 
 #if defined(TARGET_PPC64)
 void OPPROTO op_check_addo_64 (void)
 {
-    if (likely(!(((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &
-                 ((uint64_t)T2 ^ (uint64_t)T0) & (1ULL << 63)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
+    xer_ov = (((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &
+              ((uint64_t)T2 ^ (uint64_t)T0)) >> 63;
+    xer_so |= xer_ov;
     RETURN();
 }
 #endif
@@ -922,6 +920,8 @@ void OPPROTO op_add_me (void)
     T0 += xer_ca + (-1);
     if (likely((uint32_t)T1 != 0))
         xer_ca = 1;
+    else
+        xer_ca = 0;
     RETURN();
 }
 
@@ -931,6 +931,8 @@ void OPPROTO op_add_me_64 (void)
     T0 += xer_ca + (-1);
     if (likely((uint64_t)T1 != 0))
         xer_ca = 1;
+    else
+        xer_ca = 0;
     RETURN();
 }
 #endif
@@ -1142,32 +1144,6 @@ void OPPROTO op_subf (void)
     RETURN();
 }
 
-void OPPROTO op_check_subfo (void)
-{
-    if (likely(!(((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
-                 ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
-    RETURN();
-}
-
-#if defined(TARGET_PPC64)
-void OPPROTO op_check_subfo_64 (void)
-{
-    if (likely(!(((uint64_t)(~T2) ^ (uint64_t)T1 ^ UINT64_MAX) &
-                 ((uint64_t)(~T2) ^ (uint64_t)T0) & (1ULL << 63)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
-    RETURN();
-}
-#endif
-
 /* subtract from carrying */
 void OPPROTO op_check_subfc (void)
 {
@@ -1235,8 +1211,10 @@ void OPPROTO op_subfic_64 (void)
 void OPPROTO op_subfme (void)
 {
     T0 = ~T0 + xer_ca - 1;
-    if (likely((uint32_t)T0 != (uint32_t)-1))
+    if (likely((uint32_t)T0 != UINT32_MAX))
         xer_ca = 1;
+    else
+        xer_ca = 0;
     RETURN();
 }
 
@@ -1244,8 +1222,10 @@ void OPPROTO op_subfme (void)
 void OPPROTO op_subfme_64 (void)
 {
     T0 = ~T0 + xer_ca - 1;
-    if (likely((uint64_t)T0 != (uint64_t)-1))
+    if (likely((uint64_t)T0 != UINT64_MAX))
         xer_ca = 1;
+    else
+        xer_ca = 0;
     RETURN();
 }
 #endif
@@ -2528,12 +2508,6 @@ void OPPROTO op_405_mullhwu (void)
     RETURN();
 }
 
-void OPPROTO op_405_check_ov (void)
-{
-    do_405_check_ov();
-    RETURN();
-}
-
 void OPPROTO op_405_check_sat (void)
 {
     do_405_check_sat();
index 6ed9c95..75bf33b 100644 (file)
@@ -151,15 +151,12 @@ void do_addmeo (void)
 {
     T1 = T0;
     T0 += xer_ca + (-1);
-    if (likely(!((uint32_t)T1 &
-                 ((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
+    xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31;
+    xer_so |= xer_ov;
     if (likely(T1 != 0))
         xer_ca = 1;
+    else
+        xer_ca = 0;
 }
 
 #if defined(TARGET_PPC64)
@@ -167,15 +164,12 @@ void do_addmeo_64 (void)
 {
     T1 = T0;
     T0 += xer_ca + (-1);
-    if (likely(!((uint64_t)T1 &
-                 ((uint64_t)T1 ^ (uint64_t)T0) & (1ULL << 63)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
+    xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63;
+    xer_so |= xer_ov;
     if (likely(T1 != 0))
         xer_ca = 1;
+    else
+        xer_ca = 0;
 }
 #endif
 
@@ -316,15 +310,12 @@ void do_subfmeo (void)
 {
     T1 = T0;
     T0 = ~T0 + xer_ca - 1;
-    if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) &
-                 (1UL << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
+    xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31;
+    xer_so |= xer_ov;
     if (likely((uint32_t)T1 != UINT32_MAX))
         xer_ca = 1;
+    else
+        xer_ca = 0;
 }
 
 #if defined(TARGET_PPC64)
@@ -332,15 +323,12 @@ void do_subfmeo_64 (void)
 {
     T1 = T0;
     T0 = ~T0 + xer_ca - 1;
-    if (likely(!((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0) &
-                 (1ULL << 63)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
+    xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63;
+    xer_so |= xer_ov;
     if (likely((uint64_t)T1 != UINT64_MAX))
         xer_ca = 1;
+    else
+        xer_ca = 0;
 }
 #endif
 
@@ -348,13 +336,9 @@ void do_subfzeo (void)
 {
     T1 = T0;
     T0 = ~T0 + xer_ca;
-    if (likely(!(((uint32_t)~T1 ^ UINT32_MAX) &
-                 ((uint32_t)(~T1) ^ (uint32_t)T0) & (1UL << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
+    xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) &
+              ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31;
+    xer_so |= xer_ov;
     if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
         xer_ca = 0;
     } else {
@@ -367,13 +351,9 @@ void do_subfzeo_64 (void)
 {
     T1 = T0;
     T0 = ~T0 + xer_ca;
-    if (likely(!(((uint64_t)~T1 ^ UINT64_MAX) &
-                 ((uint64_t)(~T1) ^ (uint64_t)T0) & (1ULL << 63)))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
+    xer_ov = (((uint64_t)~T1 ^  UINT64_MAX) &
+              ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63;
+    xer_so |= xer_ov;
     if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
         xer_ca = 0;
     } else {
@@ -1755,17 +1735,6 @@ void do_op_602_mfrom (void)
 
 /*****************************************************************************/
 /* Embedded PowerPC specific helpers */
-void do_405_check_ov (void)
-{
-    if (likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
-               !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
-        xer_ov = 0;
-    } else {
-        xer_ov = 1;
-        xer_so = 1;
-    }
-}
-
 void do_405_check_sat (void)
 {
     if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
index 6575d3d..5b77cb2 100644 (file)
@@ -182,7 +182,6 @@ void do_440_tlbwe (int word);
 #endif
 
 /* PowerPC 4xx specific helpers */
-void do_405_check_ov (void);
 void do_405_check_sat (void);
 void do_load_dcr (void);
 void do_store_dcr (void);
index 1adff9f..73b2e22 100644 (file)
@@ -888,17 +888,17 @@ GEN_INT_ARITH1_64 (neg,    0x1F, 0x08, 0x03, PPC_INTEGER);
 /* subf   subf.   subfo   subfo.   */
 static always_inline void gen_op_subfo (void)
 {
-    gen_op_move_T2_T0();
+    gen_op_moven_T2_T0();
     gen_op_subf();
-    gen_op_check_subfo();
+    gen_op_check_addo();
 }
 #if defined(TARGET_PPC64)
 #define gen_op_subf_64 gen_op_subf
 static always_inline void gen_op_subfo_64 (void)
 {
-    gen_op_move_T2_T0();
+    gen_op_moven_T2_T0();
     gen_op_subf();
-    gen_op_check_subfo_64();
+    gen_op_check_addo_64();
 }
 #endif
 GEN_INT_ARITH2_64 (subf,   0x1F, 0x08, 0x01, PPC_INTEGER);
@@ -910,10 +910,10 @@ static always_inline void gen_op_subfc (void)
 }
 static always_inline void gen_op_subfco (void)
 {
-    gen_op_move_T2_T0();
+    gen_op_moven_T2_T0();
     gen_op_subf();
     gen_op_check_subfc();
-    gen_op_check_subfo();
+    gen_op_check_addo();
 }
 #if defined(TARGET_PPC64)
 static always_inline void gen_op_subfc_64 (void)
@@ -923,27 +923,27 @@ static always_inline void gen_op_subfc_64 (void)
 }
 static always_inline void gen_op_subfco_64 (void)
 {
-    gen_op_move_T2_T0();
+    gen_op_moven_T2_T0();
     gen_op_subf();
     gen_op_check_subfc_64();
-    gen_op_check_subfo_64();
+    gen_op_check_addo_64();
 }
 #endif
 GEN_INT_ARITH2_64 (subfc,  0x1F, 0x08, 0x00, PPC_INTEGER);
 /* subfe  subfe.  subfeo  subfeo.  */
 static always_inline void gen_op_subfeo (void)
 {
-    gen_op_move_T2_T0();
+    gen_op_moven_T2_T0();
     gen_op_subfe();
-    gen_op_check_subfo();
+    gen_op_check_addo();
 }
 #if defined(TARGET_PPC64)
 #define gen_op_subfe_64 gen_op_subfe
 static always_inline void gen_op_subfeo_64 (void)
 {
-    gen_op_move_T2_T0();
+    gen_op_moven_T2_T0();
     gen_op_subfe_64();
-    gen_op_check_subfo_64();
+    gen_op_check_addo_64();
 }
 #endif
 GEN_INT_ARITH2_64 (subfe,  0x1F, 0x08, 0x04, PPC_INTEGER);
@@ -5116,7 +5116,7 @@ static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
     if (opc3 & 0x10) {
         /* Check overflow */
         if (opc3 & 0x01)
-            gen_op_405_check_ov();
+            gen_op_check_addo();
         else
             gen_op_405_check_ovu();
     }