eflags |= (1<<10);
if (vex_state->guest_IDFLAG == 1)
eflags |= (1<<21);
+ if (vex_state->guest_ACFLAG == 1)
+ eflags |= (1<<18);
return eflags;
}
vex_state->guest_CC_NDEP = 0;
vex_state->guest_DFLAG = 1; /* forwards */
vex_state->guest_IDFLAG = 0;
+ vex_state->guest_ACFLAG = 0;
vex_state->guest_EIP = 0;
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
- .n_alwaysDefd = 21,
+ .n_alwaysDefd = 22,
/* flags thunk: OP and NDEP are always defd, whereas DEP1
and DEP2 have to be tracked. See detailed comment in
/* 1 */ ALWAYSDEFD(guest_CC_NDEP),
/* 2 */ ALWAYSDEFD(guest_DFLAG),
/* 3 */ ALWAYSDEFD(guest_IDFLAG),
- /* 4 */ ALWAYSDEFD(guest_EIP),
- /* 5 */ ALWAYSDEFD(guest_FTOP),
- /* 6 */ ALWAYSDEFD(guest_FPTAG),
- /* 7 */ ALWAYSDEFD(guest_FPROUND),
- /* 8 */ ALWAYSDEFD(guest_FC3210),
- /* 9 */ ALWAYSDEFD(guest_CS),
- /* 10 */ ALWAYSDEFD(guest_DS),
- /* 11 */ ALWAYSDEFD(guest_ES),
- /* 12 */ ALWAYSDEFD(guest_FS),
- /* 13 */ ALWAYSDEFD(guest_GS),
- /* 14 */ ALWAYSDEFD(guest_SS),
- /* 15 */ ALWAYSDEFD(guest_LDT),
- /* 16 */ ALWAYSDEFD(guest_GDT),
- /* 17 */ ALWAYSDEFD(guest_EMWARN),
- /* 18 */ ALWAYSDEFD(guest_SSEROUND),
- /* 19 */ ALWAYSDEFD(guest_TISTART),
- /* 20 */ ALWAYSDEFD(guest_TILEN)
+ /* 4 */ ALWAYSDEFD(guest_ACFLAG),
+ /* 5 */ ALWAYSDEFD(guest_EIP),
+ /* 6 */ ALWAYSDEFD(guest_FTOP),
+ /* 7 */ ALWAYSDEFD(guest_FPTAG),
+ /* 8 */ ALWAYSDEFD(guest_FPROUND),
+ /* 9 */ ALWAYSDEFD(guest_FC3210),
+ /* 10 */ ALWAYSDEFD(guest_CS),
+ /* 11 */ ALWAYSDEFD(guest_DS),
+ /* 12 */ ALWAYSDEFD(guest_ES),
+ /* 13 */ ALWAYSDEFD(guest_FS),
+ /* 14 */ ALWAYSDEFD(guest_GS),
+ /* 15 */ ALWAYSDEFD(guest_SS),
+ /* 16 */ ALWAYSDEFD(guest_LDT),
+ /* 17 */ ALWAYSDEFD(guest_GDT),
+ /* 18 */ ALWAYSDEFD(guest_EMWARN),
+ /* 19 */ ALWAYSDEFD(guest_SSEROUND),
+ /* 20 */ ALWAYSDEFD(guest_TISTART),
+ /* 21 */ ALWAYSDEFD(guest_TILEN)
}
};
only way to observe eflags[1], a proper fix would be to make that
bit be set by PUSHF.
+ The state of %eflags.AC (alignment check, bit 18) is recorded by
+ the simulation (viz, if you set it with popf then a pushf produces
+ the value you set it to), but it is otherwise ignored. In
+ particular, setting it to 1 does NOT cause alignment checking to
+ happen. Programs that set it to 1 and then rely on the resulting
+ SIGBUSs to inform them of misaligned accesses will not work.
+
This module uses global variables and so is not MT-safe (if that
should ever become relevant).
#define OFFB_FPTAGS offsetof(VexGuestX86State,guest_FPTAG[0])
#define OFFB_DFLAG offsetof(VexGuestX86State,guest_DFLAG)
#define OFFB_IDFLAG offsetof(VexGuestX86State,guest_IDFLAG)
+#define OFFB_ACFLAG offsetof(VexGuestX86State,guest_ACFLAG)
#define OFFB_FTOP offsetof(VexGuestX86State,guest_FTOP)
#define OFFB_FC3210 offsetof(VexGuestX86State,guest_FC3210)
#define OFFB_FPROUND offsetof(VexGuestX86State,guest_FPROUND)
mkU32(0xFFFFFFFF)))
);
- /* And set the ID flag */
+ /* Set the ID flag */
stmt( IRStmt_Put(
OFFB_IDFLAG,
IRExpr_Mux0X(
mkU32(1)))
);
+ /* And set the AC flag. If setting it 1 to, emit an emulation
+ warning. */
+ stmt( IRStmt_Put(
+ OFFB_ACFLAG,
+ IRExpr_Mux0X(
+ unop(Iop_32to8,
+ binop(Iop_And32,
+ binop(Iop_Shr32, mkexpr(t1), mkU8(18)),
+ mkU32(1))),
+ mkU32(0),
+ mkU32(1)))
+ );
+
+ put_emwarn( mkU32(EmWarn_X86_acFlag) );
+ stmt(
+ IRStmt_Exit(
+ binop( Iop_CmpNE32,
+ binop(Iop_And32, mkexpr(t1), mkU32(1<<18)),
+ mkU32(0) ),
+ Ijk_EmWarn,
+ IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
+ )
+ );
+
DIP("popf%c\n", nameISize(sz));
break;
mkU32(1<<21)))
);
+ /* And patch in the AC flag. */
+ t5 = newTemp(Ity_I32);
+ assign( t5, binop(Iop_Or32,
+ mkexpr(t4),
+ binop(Iop_And32,
+ binop(Iop_Shl32, IRExpr_Get(OFFB_ACFLAG,Ity_I32),
+ mkU8(18)),
+ mkU32(1<<18)))
+ );
+
/* if sz==2, the stored value needs to be narrowed. */
if (sz == 2)
- storeLE( mkexpr(t1), unop(Iop_32to16,mkexpr(t4)) );
+ storeLE( mkexpr(t1), unop(Iop_32to16,mkexpr(t5)) );
else
- storeLE( mkexpr(t1), mkexpr(t4) );
+ storeLE( mkexpr(t1), mkexpr(t5) );
DIP("pushf%c\n", nameISize(sz));
break;
return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
case EmWarn_X86_daz:
return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
+ case EmWarn_X86_acFlag:
+ return "Setting %eflags.ac (setting noted but ignored)";
case EmWarn_PPC32exns:
return "Unmasking PPC32 FP exceptions";
default:
/* The max number of guest state chunks which we can describe as
always defined (for the benefit of Memcheck). */
-#define VEXGLO_N_ALWAYSDEFD 21
+#define VEXGLO_N_ALWAYSDEFD 22
typedef
struct {
/* setting mxcsr.daz is not supported */
EmWarn_X86_daz,
+
+ /* settings to %eflags.ac (alignment check) are noted but ignored */
+ EmWarn_X86_acFlag,
/* unmasking PPC32 FP exceptions is not supported */
EmWarn_PPC32exns,
UInt guest_EBP;
UInt guest_ESI;
UInt guest_EDI; /* 28 */
+
/* 4-word thunk used to calculate O S Z A C P flags. */
UInt guest_CC_OP; /* 32 */
UInt guest_CC_DEP1;
UInt guest_DFLAG; /* 48 */
/* Bit 21 (ID) of eflags stored here, as either 0 or 1. */
UInt guest_IDFLAG; /* 52 */
+ /* Bit 18 (AC) of eflags stored here, as either 0 or 1. */
+ UInt guest_ACFLAG; /* 56 */
+
/* EIP */
- UInt guest_EIP; /* 56 */
+ UInt guest_EIP; /* 60 */
+
/* FPU */
- UInt guest_FTOP; /* 60 */
ULong guest_FPREG[8]; /* 64 */
UChar guest_FPTAG[8]; /* 128 */
UInt guest_FPROUND; /* 136 */
UInt guest_FC3210; /* 140 */
+ UInt guest_FTOP; /* 144 */
+
/* SSE */
- UInt guest_SSEROUND; /* 144 */
- U128 guest_XMM0; /* 148 */
+ UInt guest_SSEROUND; /* 148 */
+ U128 guest_XMM0; /* 152 */
U128 guest_XMM1;
U128 guest_XMM2;
U128 guest_XMM3;
U128 guest_XMM5;
U128 guest_XMM6;
U128 guest_XMM7;
+
/* Segment registers. */
UShort guest_CS;
UShort guest_DS;
UInt guest_TILEN;
/* Padding to make it have an 8-aligned size */
- UInt padding;
+ /* UInt padding; */
}
VexGuestX86State;