|
From: <sv...@va...> - 2005-07-21 10:07:18
|
Author: sewardj
Date: 2005-07-21 11:07:13 +0100 (Thu, 21 Jul 2005)
New Revision: 1284
Log:
Implement STC/CLC/CMC, and take the opportunity to make PUSHFL work a
bit more like how the hardware does.
Modified:
trunk/priv/guest-x86/toIR.c
Modified: trunk/priv/guest-x86/toIR.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/guest-x86/toIR.c 2005-07-20 10:55:26 UTC (rev 1283)
+++ trunk/priv/guest-x86/toIR.c 2005-07-21 10:07:13 UTC (rev 1284)
@@ -10989,8 +10989,15 @@
assign( t1, binop(Iop_Sub32,getIReg(4,R_ESP),mkU32(sz)) );
putIReg(4, R_ESP, mkexpr(t1) );
=20
+ /* Calculate OSZACP, and patch in fixed fields as per
+ Intel docs.=20
+ - bit 1 is always 1
+ - bit 9 is Interrupt Enable (should always be 1 in user mode?)
+ */
t2 =3D newTemp(Ity_I32);
- assign( t2, mk_x86g_calculate_eflags_all() );
+ assign( t2, binop(Iop_Or32,=20
+ mk_x86g_calculate_eflags_all(),=20
+ mkU32( (1<<1)|(1<<9) ) ));
=20
/* Patch in the D flag. This can simply be a copy of bit 10 of
baseBlock[OFFB_DFLAG]. */
@@ -11102,29 +11109,38 @@
DIP("std\n");
break;
=20
-//-- 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;
-//--=20
-//-- 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;
-//--=20
-//-- 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 =3D newTemp(Ity_I32);
+ t1 =3D newTemp(Ity_I32);
+ assign( t0, mk_x86g_calculate_eflags_all() );
+ switch (opc) {
+ case 0xF8:=20
+ assign( t1, binop(Iop_And32, mkexpr(t0),=20
+ mkU32(~X86G_CC_MASK_C)));
+ DIP("clc\n");
+ break;
+ case 0xF9:=20
+ assign( t1, binop(Iop_Or32, mkexpr(t0),=20
+ mkU32(X86G_CC_MASK_C)));
+ DIP("stc\n");
+ break;
+ case 0xF5:=20
+ assign( t1, binop(Iop_Xor32, mkexpr(t0),=20
+ mkU32(X86G_CC_MASK_C)));
+ DIP("cmc\n");
+ break;
+ default:=20
+ 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;
=20
/* REPNE prefix insn */
case 0xF2: {=20
|