From: Julian Seward Date: Thu, 21 Jul 2005 10:07:13 +0000 (+0000) Subject: Implement STC/CLC/CMC, and take the opportunity to make PUSHFL work a X-Git-Tag: svn/VALGRIND_3_0_1^2~50 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bf656e507ac5588becd9ef3d1a3869376e828e42;p=thirdparty%2Fvalgrind.git Implement STC/CLC/CMC, and take the opportunity to make PUSHFL work a bit more like how the hardware does. git-svn-id: svn://svn.valgrind.org/vex/trunk@1284 --- diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index bb264d037d..1d4345241d 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -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: {