]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fixed xer_ca flag calc for subfze,
authorCerion Armour-Brown <cerion@valgrind.org>
Wed, 16 Mar 2005 00:27:37 +0000 (00:27 +0000)
committerCerion Armour-Brown <cerion@valgrind.org>
Wed, 16 Mar 2005 00:27:37 +0000 (00:27 +0000)
Cleaned up ghelpers.c: calc_xer_ca, calc_xer_ov
Cleaned up toIR.c dis_int_arith, dis_int_cmp, dis_int_logic, dis_int_shift

git-svn-id: svn://svn.valgrind.org/vex/trunk@1040

VEX/priv/guest-ppc32/gdefs.h
VEX/priv/guest-ppc32/ghelpers.c
VEX/priv/guest-ppc32/toIR.c

index 82344524b431036c0b1c1becdc9d89cc9c1b1f9e..f8de81d544b01e1db397921ac3752a471c748349 100644 (file)
@@ -78,7 +78,7 @@ VexGuestLayout ppc32Guest_layout;
 extern UInt ppc32g_calculate_cr7_all ( UInt op, UInt val, UInt xer_so );
 
 // Calculate XER flags
-extern UInt ppc32g_calculate_xer_ov  ( UInt op, UInt res, UInt argL, UInt argR, UInt ca );
+extern UInt ppc32g_calculate_xer_ov  ( UInt op, UInt res, UInt argL, UInt argR );
 extern UInt ppc32g_calculate_xer_ca  ( UInt op, UInt res, UInt argL, UInt argR, UInt ca );
 
 
@@ -116,20 +116,16 @@ extern UInt ppc32g_calculate_xer_ca  ( UInt op, UInt res, UInt argL, UInt argR,
   Enumeration for xer_ca/ov calculation helper functions
 */
 enum {
-   PPC32G_FLAG_OP_ADD=0,   // addc, addo, addic
-   PPC32G_FLAG_OP_ADDE,    // adde, addeo
-   PPC32G_FLAG_OP_ADDME,   // addme, addmeo
-   PPC32G_FLAG_OP_ADDZE,   // addze, addzeo
+   PPC32G_FLAG_OP_ADD=0,   // addc[o], addic
+   PPC32G_FLAG_OP_ADDE,    // adde[o], addme[o], addze[o]
    PPC32G_FLAG_OP_DIVW,    // divwo
    PPC32G_FLAG_OP_DIVWU,   // divwuo
    PPC32G_FLAG_OP_MULLW,   // mullwo
    PPC32G_FLAG_OP_NEG,     // nego
    PPC32G_FLAG_OP_SUBF,    // subfo
-   PPC32G_FLAG_OP_SUBFC,   // subfc, subfco
-   PPC32G_FLAG_OP_SUBFE,   // subfe, subfeo
+   PPC32G_FLAG_OP_SUBFC,   // subfc[o]
+   PPC32G_FLAG_OP_SUBFE,   // subfe[o], subfme[o], subfze[o]
    PPC32G_FLAG_OP_SUBFI,   // subfic
-   PPC32G_FLAG_OP_SUBFME,  // subfme, subfmeo
-   PPC32G_FLAG_OP_SUBFZE,  // subfze, subfzeo
    PPC32G_FLAG_OP_SRAW,    // sraw
    PPC32G_FLAG_OP_SRAWI,   // srawi
    
index a16b809b830af37ffeb4c8f7af17c19d8bf69943..dadf1a1d91c99b3252458d9ef2bfef605c346031 100644 (file)
@@ -80,23 +80,14 @@ UInt ppc32g_calculate_cr7_all ( UInt op, UInt val, UInt xer_so )
 
 
 // Calculate XER_OV
-UInt ppc32g_calculate_xer_ov ( UInt op, UInt res,
-                               UInt argL, UInt argR, UInt ov )
+UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt argL, UInt argR )
 {
    switch (op) {
    case PPC32G_FLAG_OP_ADD:     // addo, addc
-   case PPC32G_FLAG_OP_ADDE:    // addeo
+   case PPC32G_FLAG_OP_ADDE:    // addeo, addmeo, addzeo
       return ((argL^argR^-1) & (argL^res) & (1<<31)) ? 1:0;
       // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
       
-   case PPC32G_FLAG_OP_ADDME:   // addmeo
-      return ((argL) & (argL ^ res) & (1<<31)) ? 1:0;
-      // i.e. (neg & (sign_changed) & sign_mask)
-      
-   case PPC32G_FLAG_OP_ADDZE:   // addzeo
-      return ((argL^(-1)) & (argL ^ res) & (1<<31)) ? 1:0;
-      // i.e. (pos & (sign_changed) & sign_mask)
-      
    case PPC32G_FLAG_OP_DIVW:    // divwo
       return ((argL == INT32_MIN && argR == -1) || argR == 0) ? 1:0;
       
@@ -117,15 +108,9 @@ UInt ppc32g_calculate_xer_ov ( UInt op, UInt res,
       
    case PPC32G_FLAG_OP_SUBF:    // subfo
    case PPC32G_FLAG_OP_SUBFC:   // subfco
-   case PPC32G_FLAG_OP_SUBFE:   // subfeo
+   case PPC32G_FLAG_OP_SUBFE:   // subfeo, subfmeo, subfzeo
       return (((~argL)^argR^(-1)) & ((~argL)^res) & (1<<31)) ? 1:0;
 
-   case PPC32G_FLAG_OP_SUBFME:  // subfmeo
-      return ((~argL) & ((~argL)^res) & (1<<31)) ? 1:0;
-
-   case PPC32G_FLAG_OP_SUBFZE:  // subfzeo
-      return (((~argL)^(-1)) & ((~argL)^res) & (1<<31)) ? 1:0;
-
    default:
       break;
    }
@@ -138,40 +123,32 @@ UInt ppc32g_calculate_xer_ov ( UInt op, UInt res,
 UInt ppc32g_calculate_xer_ca ( UInt op, UInt res,
                                UInt argL, UInt argR, UInt ca )
 {
-   switch (op) {
-   case PPC32G_FLAG_OP_ADD:     // addc, addco, addic
-   case PPC32G_FLAG_OP_ADDZE:   // addze, addzeo
+  switch (op) {
+   case PPC32G_FLAG_OP_ADD:     // addc[o], addic
       return (res < argL) ? 1:0;
 
-   case PPC32G_FLAG_OP_ADDE:    // adde, addeo
+   case PPC32G_FLAG_OP_ADDE:    // adde[o], addze[o], addme[o]
       return (res < argL || (ca==1 && res==argL)) ? 1:0;
 
-   case PPC32G_FLAG_OP_ADDME:   // addme, addmeo
-      return (argL != 0) ? 1:0;
-
-   case PPC32G_FLAG_OP_SUBFC:   // subfc, subfco
+   case PPC32G_FLAG_OP_SUBFC:   // subfc[o]
    case PPC32G_FLAG_OP_SUBFI:   // subfic
-   case PPC32G_FLAG_OP_SUBFZE:  // subfze, subfzeo
       return (res <= argR) ? 1:0;
 
-   case PPC32G_FLAG_OP_SUBFE:   // subfe, subfeo
+   case PPC32G_FLAG_OP_SUBFE:   // subfe[o], subfze[o], subfme[o]
       return ((res < argR) || (ca == 1 && res == argR)) ? 1:0;
 
-   case PPC32G_FLAG_OP_SUBFME:  // subfme, subfmeo
-      return (res != -1) ? 1:0;
-
    case PPC32G_FLAG_OP_SRAW:    // sraw
       if ((argR & 0x20) == 0) {  // shift <= 31
-         // ca = sign && (bits_shifted_out != 0)
+         // xer_ca = sign && (bits_shifted_out != 0)
          return (((argL & 0x80000000) &&
                   ((argL & (0xFFFFFFFF >> (32-argR))) != 0)) != 0) ? 1:0;
       }
       // shift > 31
-      // ca = sign && src != 0
+      // xer_ca = sign && src != 0
       return (((argL & 0x80000000) && (argR != 0)) != 0) ? 1:0;
 
    case PPC32G_FLAG_OP_SRAWI:   // srawi
-      // ca = sign && (bits_shifted_out != 0)
+      // xer_ca = sign && (bits_shifted_out != 0)
       return (((argL & 0x80000000) &&
                ((argL & (0xFFFFFFFF >> (32-argR))) != 0)) != 0) ? 1:0;
 
index 77400af23ac076a5f419c5fe622889775413b547..ab4ce45260c7c56f57cc33e5eea82da7738ad74d 100644 (file)
@@ -642,9 +642,7 @@ static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt op, IRExpr* res,
    vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32);
    vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32);
 
-   args =
-      mkIRExprVec_5( mkU32(op), res, argL, argR,
-                     getReg_bit( PPC32_SPR_XER, SHIFT_XER_OV ) );
+   args = mkIRExprVec_4( mkU32(op), res, argL, argR );
 
    call
       = mkIRExprCCall(
@@ -669,7 +667,8 @@ static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt op, IRExpr* res,
    vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32);
 
    xer_ca = getReg_bit( PPC32_SPR_XER, SHIFT_XER_CA );
-   args   = mkIRExprVec_5( mkU32(op), res, argL, argR, xer_ca );
+
+   args = mkIRExprVec_5( mkU32(op), res, argL, argR, xer_ca );
 
    call
       = mkIRExprCCall(
@@ -726,9 +725,9 @@ static void setFlags_XER_CA( UInt op, IRExpr* res,
    vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32);
    vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32);
    vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32);
-   
-   // => Calculate result immediately
-   xer_ca = mk_ppc32g_calculate_xer_ca(op, res, argL, argR);
+
+   // Calculate new xer_ca immediately:
+   xer_ca = mk_ppc32g_calculate_xer_ca(op, res, argL, argR );
 
    putReg_bit( PPC32_SPR_XER, xer_ca, SHIFT_XER_CA );
 }
@@ -977,41 +976,31 @@ static Bool dis_int_arith ( UInt theInstr )
    IRTemp Rd     = newTemp(Ity_I32);
    IRTemp res64  = newTemp(Ity_I64);  // multiplies need this.
    IRTemp xer_ca = newTemp(Ity_I32);
-   
-   UInt op    = PPC32G_FLAG_OP_NUMBER;
-   Bool do_ca = False;
-   Bool do_ov = False;
+
+   UInt flag_op = PPC32G_FLAG_OP_NUMBER;
    Bool do_rc = False;
-   IRExpr* argL;
-   IRExpr* argR;
 
    assign( Ra, getIReg(Ra_addr) );
    assign( Rb, getIReg(Rb_addr) );         // XO-Form: Rd, Ra, Rb
    EXTS_SIMM = extend_s_16to32(SIMM_16);   // D-Form:  Rd, Ra, EXTS(SIMM)
-   
-   // ca/ov flag calc params
-   argL = mkexpr(Ra);
-   argR = (opc1 == 0x1F) ? mkexpr(Rb) : mkU32(EXTS_SIMM);
 
    assign( xer_ca, getReg_bit( PPC32_SPR_XER, SHIFT_XER_CA ) );
-    
-
+   
    switch (opc1) {
-
    /* D-Form */
    case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
       DIP("addic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, EXTS_SIMM);
       assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) );
-      op = PPC32G_FLAG_OP_ADD;
-      do_ca = True;
+      flag_op = PPC32G_FLAG_OP_ADD;
+      setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(EXTS_SIMM) );
       break;
       
    case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
       DIP("addic. r%d,r%d,0x%x\n", Rd_addr, Ra_addr, EXTS_SIMM);
       assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) );
-      op = PPC32G_FLAG_OP_ADD;
-      do_ca = True;
-      do_rc = True;
+      flag_op = PPC32G_FLAG_OP_ADD;
+      setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(EXTS_SIMM) );
+      do_rc = True;  // Always record to CR
       flag_Rc = 1;
       break;
 
@@ -1046,8 +1035,8 @@ static Bool dis_int_arith ( UInt theInstr )
       DIP("subfic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16);
       // rD = exts_simm - rA
       assign( Rd, binop(Iop_Sub32, mkU32(EXTS_SIMM), mkexpr(Ra)) );
-      op = PPC32G_FLAG_OP_SUBFI;
-      do_ca = True;
+      flag_op = PPC32G_FLAG_OP_SUBFI;
+      setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(EXTS_SIMM) );
       break;
 
 
@@ -1061,8 +1050,10 @@ static Bool dis_int_arith ( UInt theInstr )
              flag_OE ? "o" : "", flag_Rc ? "." : "",
              Rd_addr, Ra_addr, Rb_addr);
          assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) );
-         op = PPC32G_FLAG_OP_ADD;
-         do_ov = True;
+         if (flag_OE) {
+            flag_op = PPC32G_FLAG_OP_ADD;
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          break;
 
       case 0x00A: // addc      (Add Carrying, PPC32 p348)
@@ -1070,9 +1061,11 @@ static Bool dis_int_arith ( UInt theInstr )
              flag_OE ? "o" : "", flag_Rc ? "." : "",
              Rd_addr, Ra_addr, Rb_addr);
          assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) );
-         op = PPC32G_FLAG_OP_ADD;
-         do_ca = True;
-         do_ov = True;
+         flag_op = PPC32G_FLAG_OP_ADD;
+         setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         if (flag_OE) {
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          break;
          
       case 0x08A: // adde      (Add Extended, PPC32 p349)
@@ -1082,9 +1075,11 @@ static Bool dis_int_arith ( UInt theInstr )
          // rD = rA + rB + XER[CA]
          assign( Rd, binop(Iop_Add32, mkexpr(Ra),
                            binop(Iop_Add32, mkexpr(Rb), mkexpr(xer_ca))) );
-         op = PPC32G_FLAG_OP_ADDE;
-         do_ca = True;
-         do_ov = True;
+         flag_op = PPC32G_FLAG_OP_ADDE;
+         setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         if (flag_OE) {
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          break;
          
       case 0x0EA: // addme      (Add to Minus One Extended, PPC32 p354)
@@ -1095,12 +1090,15 @@ static Bool dis_int_arith ( UInt theInstr )
          DIP("addme%s%s r%d,r%d,r%d\n",
              flag_OE ? "o" : "", flag_Rc ? "." : "",
              Rd_addr, Ra_addr, Rb_addr);
-         // rD = rA + XER[CA] - 1
+         // rD = rA + (-1) + XER[CA]
+         // => Just another form of adde
          assign( Rd, binop(Iop_Add32, mkexpr(Ra),
-                           binop(Iop_Sub32, mkexpr(xer_ca), mkU32(1)) ));
-         op = PPC32G_FLAG_OP_ADDME;
-         do_ca = True;
-         do_ov = True;
+                           binop(Iop_Add32, mkU32(-1), mkexpr(xer_ca)) ));
+         flag_op = PPC32G_FLAG_OP_ADDE;
+         setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1) );
+         if (flag_OE) {
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1) );
+         }
          break;
          
       case 0x0CA: // addze      (Add to Zero Extended, PPC32 p355)
@@ -1111,11 +1109,14 @@ static Bool dis_int_arith ( UInt theInstr )
          DIP("addze%s%s r%d,r%d,r%d\n",
              flag_OE ? "o" : "", flag_Rc ? "." : "",
              Rd_addr, Ra_addr, Rb_addr);
-         // rD = rA + XER[CA]
+         // rD = rA + (0) + XER[CA]
+         // => Just another form of adde
          assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(xer_ca)) );
-         op = PPC32G_FLAG_OP_ADDZE;
-         do_ca = True;
-         do_ov = True;
+         flag_op = PPC32G_FLAG_OP_ADDE;
+         setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(0) );
+         if (flag_OE) {
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(0) );
+         }
          break;
 
       case 0x1EB: // divw       (Divide Word, PPC32 p388)
@@ -1123,8 +1124,10 @@ static Bool dis_int_arith ( UInt theInstr )
              flag_OE ? "o" : "", flag_Rc ? "." : "",
              Rd_addr, Ra_addr, Rb_addr);
          assign( Rd, binop(Iop_DivS32, mkexpr(Ra), mkexpr(Rb)) );
-         op = PPC32G_FLAG_OP_DIVW;
-         do_ov = True;
+         if (flag_OE) {
+            flag_op = PPC32G_FLAG_OP_DIVW;
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          /* Note:
             if (0x8000_0000 / -1) or (x / 0)
             => Rd=undef, if(flag_Rc) CR7=undef, if(flag_OE) XER_OV=1
@@ -1136,8 +1139,10 @@ static Bool dis_int_arith ( UInt theInstr )
              flag_OE ? "o" : "", flag_Rc ? "." : "",
              Rd_addr, Ra_addr, Rb_addr);
          assign( Rd, binop(Iop_DivU32, mkexpr(Ra), mkexpr(Rb)) );
-         op = PPC32G_FLAG_OP_DIVWU;
-         do_ov = True;
+         if (flag_OE) {
+            flag_op = PPC32G_FLAG_OP_DIVWU;
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          /* Note: ditto comment divw, for (x / 0) */
          break;
 
@@ -1169,8 +1174,10 @@ static Bool dis_int_arith ( UInt theInstr )
              Rd_addr, Ra_addr, Rb_addr);
          assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) );
          assign( Rd, unop(Iop_64to32, mkexpr(res64)) );
-         op = PPC32G_FLAG_OP_MULLW;
-         do_ov = True;
+         if (flag_OE) {
+            flag_op = PPC32G_FLAG_OP_MULLW;
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          break;
 
       case 0x068: // neg        (Negate, PPC32 p493)
@@ -1184,8 +1191,10 @@ static Bool dis_int_arith ( UInt theInstr )
          // rD = (log not)rA + 1
          assign( Rd, binop(Iop_Add32,
                            unop(Iop_Not32, mkexpr(Ra)), mkU32(1)) );
-         op = PPC32G_FLAG_OP_NEG;
-         do_ov = True;
+         if (flag_OE) {
+            flag_op = PPC32G_FLAG_OP_NEG;
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          break;
 
       case 0x028: // subf       (Subtract From, PPC32 p537)
@@ -1194,8 +1203,10 @@ static Bool dis_int_arith ( UInt theInstr )
              Rd_addr, Ra_addr, Rb_addr);
          // rD = rB - rA
          assign( Rd, binop(Iop_Sub32, mkexpr(Rb), mkexpr(Ra)) );
-         op = PPC32G_FLAG_OP_SUBF;
-         do_ov = True;
+         if (flag_OE) {
+            flag_op = PPC32G_FLAG_OP_SUBF;
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          break;
 
       case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
@@ -1204,9 +1215,11 @@ static Bool dis_int_arith ( UInt theInstr )
              Rd_addr, Ra_addr, Rb_addr);
          // rD = rB - rA
          assign( Rd, binop(Iop_Sub32, mkexpr(Rb), mkexpr(Ra)) );
-         op = PPC32G_FLAG_OP_SUBFC;
-         do_ca = True;
-         do_ov = True;
+         flag_op = PPC32G_FLAG_OP_SUBFC;
+         setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         if (flag_OE) {
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          break;
          
       case 0x088: // subfe      (Subtract from Extended, PPC32 p539)
@@ -1216,9 +1229,11 @@ static Bool dis_int_arith ( UInt theInstr )
          // rD = (log not)rA + rB + XER[CA]
          assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)),
                            binop(Iop_Add32, mkexpr(Rb), mkexpr(xer_ca))) );
-         op = PPC32G_FLAG_OP_SUBFE;
-         do_ca = True;
-         do_ov = True;
+         flag_op = PPC32G_FLAG_OP_SUBFE;
+         setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         if (flag_OE) {
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
+         }
          break;
          
       case 0x0E8: // subfme     (Subtract from Minus One Extended, PPC32 p541)
@@ -1229,12 +1244,15 @@ static Bool dis_int_arith ( UInt theInstr )
          DIP("subfme%s%s r%d,r%d\n",
              flag_OE ? "o" : "", flag_Rc ? "." : "",
              Rd_addr, Ra_addr);
-         // rD = (log not)rA + XER[CA] - 1
+         // rD = (log not)rA + (-1) + XER[CA]
+         // => Just another form of subfe
          assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)),
-                           binop(Iop_Sub32, mkexpr(xer_ca), mkU32(1))) );
-         op = PPC32G_FLAG_OP_SUBFME;
-         do_ca = True;
-         do_ov = True;
+                           binop(Iop_Add32, mkU32(-1), mkexpr(xer_ca))) );
+         flag_op = PPC32G_FLAG_OP_SUBFE;
+         setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1) );
+         if (flag_OE) {
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1) );
+         }
          break;
          
       case 0x0C8: // subfze     (Subtract from Zero Extended, PPC32 p542)
@@ -1245,12 +1263,14 @@ static Bool dis_int_arith ( UInt theInstr )
          DIP("subfze%s%s r%d,r%d\n",
              flag_OE ? "o" : "", flag_Rc ? "." : "",
              Rd_addr, Ra_addr);
-         // rD = (log not)rA + XER[CA]
-         assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)),
-                           mkexpr(xer_ca)) );
-         op = PPC32G_FLAG_OP_SUBFZE;
-         do_ca = True;
-         do_ov = True;
+         // rD = (log not)rA + (0) + XER[CA]
+         // => Just another form of subfe
+         assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), mkexpr(xer_ca)) );
+         flag_op = PPC32G_FLAG_OP_SUBFE;
+         setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(0) );
+         if (flag_OE) {
+            setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(0) );
+         }
          break;
 
       default:
@@ -1264,15 +1284,6 @@ static Bool dis_int_arith ( UInt theInstr )
    }
 
    putIReg( Rd_addr, mkexpr(Rd) );
-
-   if (do_ov && flag_OE) {
-      vassert(op < PPC32G_FLAG_OP_NUMBER);
-      setFlags_XER_OV_SO( op, mkexpr(Rd), argL, argR );
-   }
-   if (do_ca) {
-      vassert(op < PPC32G_FLAG_OP_NUMBER);
-      setFlags_XER_CA( op, mkexpr(Rd), argL, argR );
-   }
    if (do_rc && flag_Rc) {
       setFlags_CR7( mkexpr(Rd) );
    }
@@ -1305,8 +1316,8 @@ static Bool dis_int_cmp ( UInt theInstr )
    IRTemp cr7     = newTemp(Ity_I32);
    IRTemp mux1    = newTemp(Ity_I32);
    IRTemp mux2    = newTemp(Ity_I32);
-   IRExpr* irx_tst1;
-   IRExpr* irx_tst2;
+   IRExpr* irx_cmp_lt;
+   IRExpr* irx_cmp_eq;
 
    assign( Ra, getIReg(Ra_addr) );
    
@@ -1324,14 +1335,14 @@ static Bool dis_int_cmp ( UInt theInstr )
    case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
       EXTS_SIMM = extend_s_16to32(SIMM_16);
       DIP("cmpi crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, EXTS_SIMM);
-      irx_tst1 = binop(Iop_CmpLT32S, mkexpr(Ra), mkU32(EXTS_SIMM));
-      irx_tst2 = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(EXTS_SIMM));
+      irx_cmp_lt = binop(Iop_CmpLT32S, mkexpr(Ra), mkU32(EXTS_SIMM));
+      irx_cmp_eq = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(EXTS_SIMM));
       break;
           
    case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
       DIP("cmpli crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, UIMM_16);
-      irx_tst1 = binop(Iop_CmpLT32U, mkexpr(Ra), mkU32(UIMM_16));
-      irx_tst2 = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(UIMM_16));
+      irx_cmp_lt = binop(Iop_CmpLT32U, mkexpr(Ra), mkU32(UIMM_16));
+      irx_cmp_eq = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(UIMM_16));
       break;
       
    /* X Form */
@@ -1341,19 +1352,19 @@ static Bool dis_int_cmp ( UInt theInstr )
          return False;
       }
       assign( Rb, getIReg(Rb_addr) );
-      irx_tst2 = binop(Iop_CmpEQ32, mkexpr(Ra), mkexpr(Rb));
+      irx_cmp_eq = binop(Iop_CmpEQ32, mkexpr(Ra), mkexpr(Rb));
 
       switch (opc2) {
       case 0x000: // cmp (Compare, PPC32 p367)
          DIP("cmp crf%d,%u,r%d,r%d\n", crfD, flag_L,
              Ra_addr, Rb_addr);
-         irx_tst1 = binop(Iop_CmpLT32S, mkexpr(Ra), mkexpr(Rb));
+         irx_cmp_lt = binop(Iop_CmpLT32S, mkexpr(Ra), mkexpr(Rb));
          break;
          
        case 0x020: // cmpl (Compare Logical, PPC32 p369)
           DIP("cmpl crf%d,%u,r%d,r%d\n", crfD, flag_L,
               Ra_addr, Rb_addr);
-          irx_tst1 = binop(Iop_CmpLT32U, mkexpr(Ra), mkexpr(Rb));
+          irx_cmp_lt = binop(Iop_CmpLT32U, mkexpr(Ra), mkexpr(Rb));
           break;
 
        default:
@@ -1367,13 +1378,14 @@ static Bool dis_int_cmp ( UInt theInstr )
       return False;
    }
    
-   assign( mux1, IRExpr_Mux0X( unop(Iop_1Uto8, irx_tst1), // argL < argR ?
-                               mkU32(SHIFT_CR_GT),        // GT (or EQ...)
-                               mkU32(SHIFT_CR_LT) ) );    // LT
+   irx_cmp_lt = unop(Iop_1Uto8, irx_cmp_lt);
+   irx_cmp_eq = unop(Iop_1Uto8, irx_cmp_eq);
+
+   // mux_shift_bit = (argL < argR) ? LT : GT (or EQ...)
+   assign( mux1, IRExpr_Mux0X( irx_cmp_lt, mkU32(SHIFT_CR_GT), mkU32(SHIFT_CR_LT) ));
 
-   assign( mux2, IRExpr_Mux0X( unop(Iop_1Uto8, irx_tst2), // argL == argR ?
-                               mkexpr(mux1),              // GT|LT
-                               mkU32(SHIFT_CR_EQ) ) );    // EQ
+   // mux_shift_bit = (argL == argR) ? EQ : GT|LT
+   assign( mux2, IRExpr_Mux0X( irx_cmp_eq, mkexpr(mux1), mkU32(SHIFT_CR_EQ) ));
    
    assign( xer_so, getReg_bit( PPC32_SPR_XER, SHIFT_XER_SO ) );
    assign( cr7, binop(Iop_Or32, mkexpr(mux2), mkexpr(xer_so)) );
@@ -1412,41 +1424,41 @@ static Bool dis_int_logic ( UInt theInstr )
    case 0x1C: // andi. (AND Immediate, PPC32 p358)
       DIP("andi. r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16);
       assign( Ra, binop(Iop_And32, mkexpr(Rs), mkU32(UIMM_16)) );
-      putIReg( Ra_addr, mkexpr(Ra) );
-      do_rc = True;
+      do_rc = True;  // Always record to CR
       flag_Rc = 1;
       break;
       
    case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
       DIP("andis r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16);
       assign( Ra, binop(Iop_And32, mkexpr(Rs), mkU32(UIMM_16 << 16)) );
-      putIReg( Ra_addr, mkexpr(Ra) );
-      do_rc = True;
+      do_rc = True;  // Always record to CR
       flag_Rc = 1;
       break;
 
    case 0x18: // ori (OR Immediate, PPC32 p497)
       DIP("ori r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16);
-      putIReg( Ra_addr, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16)) );
+      assign( Ra, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16)) );
       break;
 
    case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
       DIP("oris r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16);
-      putIReg( Ra_addr, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16 << 16)) );
+      assign( Ra, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16 << 16)) );
       break;
 
    case 0x1A: // xori (XOR Immediate, PPC32 p550)
       DIP("xori r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16);
-      putIReg( Ra_addr, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16)) );
+      assign( Ra, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16)) );
       break;
 
    case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
       DIP("xoris r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16);
-      putIReg( Ra_addr, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16 << 16)) );
+      assign( Ra, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16 << 16)) );
       break;
 
    /* X Form */
    case 0x1F:
+      do_rc = True;    // All below record to CR
+
       switch (opc2) {
       case 0x01C: // and (AND, PPC32 p356)
          DIP("and%s r%d,r%d,r%d\n",
@@ -1550,16 +1562,14 @@ static Bool dis_int_logic ( UInt theInstr )
          vex_printf("dis_int_logic(PPC32)(opc2)\n");
          return False;
       }
-
-      putIReg( Ra_addr, mkexpr(Ra) );
-      do_rc = True;
       break;
       
    default:
       vex_printf("dis_int_logic(PPC32)(opc1)\n");
       return False;
    }
-   
+
+   putIReg( Ra_addr, mkexpr(Ra) );
    if (do_rc && flag_Rc) {
       setFlags_CR7( mkexpr(Ra) );
    }
@@ -2629,8 +2639,7 @@ static Bool dis_int_shift ( UInt theInstr )
    UInt  opc2    =         (theInstr >>  1) & 0x3FF; /* theInstr[1:10]  */
    UChar flag_Rc = toUChar((theInstr >>  0) & 1);    /* theInstr[0]     */
    
-   UInt op    = PPC32G_FLAG_OP_NUMBER;
-   Bool do_ca = False;
+   UInt flag_op  = PPC32G_FLAG_OP_NUMBER;
    
    IRTemp sh_amt = newTemp(Ity_I8);
    IRTemp sign   = newTemp(Ity_I32);
@@ -2684,8 +2693,8 @@ static Bool dis_int_shift ( UInt theInstr )
          assign( Rs_msk, binop(Iop_And32, mkexpr(Rs_sh), mkexpr(mask)) );
          // Ra = Rs_msk | sext
          assign( Ra, binop(Iop_Or32, mkexpr(Rs_msk), mkexpr(sext)) );
-         op = PPC32G_FLAG_OP_SRAW;
-         do_ca = True;
+         flag_op = PPC32G_FLAG_OP_SRAW;
+         setFlags_XER_CA( flag_op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb) );
          break;
          
       case 0x338: // srawi (Shift Right Algebraic Word Immediate, PPC32 p507)
@@ -2706,8 +2715,8 @@ static Bool dis_int_shift ( UInt theInstr )
                                      unop(Iop_Not32, mkexpr(mask)) ));
          // Ra = Rs_shift | sext
          assign( Ra, binop(Iop_Or32, mkexpr(sext), mkexpr(Rs_sh)) );
-         op = PPC32G_FLAG_OP_SRAWI;
-         do_ca = True;
+         flag_op = PPC32G_FLAG_OP_SRAWI;
+         setFlags_XER_CA( flag_op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb) );
          break;
       
       case 0x218: // srw (Shift Right Word, PPC32 p508)
@@ -2732,10 +2741,6 @@ static Bool dis_int_shift ( UInt theInstr )
 
    putIReg( Ra_addr, mkexpr(Ra) );
    
-   if (do_ca) {
-      vassert(op < PPC32G_FLAG_OP_NUMBER);
-      setFlags_XER_CA( op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb) );
-   }
    if (flag_Rc) {
       setFlags_CR7( mkexpr(Ra) );
    }