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]. */
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: {