]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement STC/CLC/CMC, and take the opportunity to make PUSHFL work a
authorJulian Seward <jseward@acm.org>
Thu, 21 Jul 2005 10:07:13 +0000 (10:07 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 21 Jul 2005 10:07:13 +0000 (10:07 +0000)
bit more like how the hardware does.

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

VEX/priv/guest-x86/toIR.c

index bb264d037d822323364c16dbe7ca18819ca3abdd..1d4345241d6e33aafb81909fcd73e573de2ff9ab 100644 (file)
@@ -10989,8 +10989,15 @@ DisResult disInstr_X86_WRK (
       assign( t1, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
       putIReg(4, R_ESP, mkexpr(t1) );
 
+      /* Calculate OSZACP, and patch in fixed fields as per
+         Intel docs. 
+         - bit 1 is always 1
+         - bit 9 is Interrupt Enable (should always be 1 in user mode?)
+      */
       t2 = newTemp(Ity_I32);
-      assign( t2, mk_x86g_calculate_eflags_all() );
+      assign( t2, binop(Iop_Or32, 
+                        mk_x86g_calculate_eflags_all(), 
+                        mkU32( (1<<1)|(1<<9) ) ));
 
       /* Patch in the D flag.  This can simply be a copy of bit 10 of
          baseBlock[OFFB_DFLAG]. */
@@ -11102,29 +11109,38 @@ DisResult disInstr_X86_WRK (
       DIP("std\n");
       break;
 
-//--    case 0xF8: /* CLC */
-//--       uInstr0(cb, CALLM_S, 0);
-//--       uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CLC));
-//--       uFlagsRWU(cb, FlagsEmpty, FlagC, FlagsOSZAP);
-//--       uInstr0(cb, CALLM_E, 0);
-//--       DIP("clc\n");
-//--       break;
-//-- 
-//--    case 0xF9: /* STC */
-//--       uInstr0(cb, CALLM_S, 0);
-//--       uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_STC));
-//--       uFlagsRWU(cb, FlagsEmpty, FlagC, FlagsOSZAP);
-//--       uInstr0(cb, CALLM_E, 0);
-//--       DIP("stc\n");
-//--       break;
-//-- 
-//--    case 0xF5: /* CMC */
-//--       uInstr0(cb, CALLM_S, 0);
-//--       uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CMC));
-//--       uFlagsRWU(cb, FlagC, FlagC, FlagsOSZAP);
-//--       uInstr0(cb, CALLM_E, 0);
-//--       DIP("cmc\n");
-//--       break;
+   case 0xF8: /* CLC */
+   case 0xF9: /* STC */
+   case 0xF5: /* CMC */
+      t0 = newTemp(Ity_I32);
+      t1 = newTemp(Ity_I32);
+      assign( t0, mk_x86g_calculate_eflags_all() );
+      switch (opc) {
+         case 0xF8: 
+            assign( t1, binop(Iop_And32, mkexpr(t0), 
+                                         mkU32(~X86G_CC_MASK_C)));
+            DIP("clc\n");
+            break;
+         case 0xF9: 
+            assign( t1, binop(Iop_Or32, mkexpr(t0), 
+                                        mkU32(X86G_CC_MASK_C)));
+            DIP("stc\n");
+            break;
+         case 0xF5: 
+            assign( t1, binop(Iop_Xor32, mkexpr(t0), 
+                                         mkU32(X86G_CC_MASK_C)));
+            DIP("cmc\n");
+            break;
+         default: 
+            vpanic("disInstr(x86)(clc/stc/cmc)");
+      }
+      stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(X86G_CC_OP_COPY) ));
+      stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0) ));
+      stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t1) ));
+      /* Set NDEP even though it isn't used.  This makes redundant-PUT
+         elimination of previous stores to this field work better. */
+      stmt( IRStmt_Put( OFFB_CC_NDEP, mkU32(0) ));
+      break;
 
    /* REPNE prefix insn */
    case 0xF2: {