Detect FPU instructions which set %EFLAGS and mark the resulting
UInstrs accordingly. Fixes a bug in the simulated CPU in which the
results of f{u}comi{p} FPU insns were ignored, potentially leading to
wrong program behaviour. This will only have happened to people using
P6/P7/K7 class CPUs.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@30 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/vg_to_ucode.c b/vg_to_ucode.c
index ebce94f..b3bd3c3 100644
--- a/vg_to_ucode.c
+++ b/vg_to_ucode.c
@@ -2244,14 +2244,39 @@
static
Addr dis_fpu_no_mem ( UCodeBlock* cb, Addr eip, UChar first_byte )
{
+ Bool sets_ZCP = False;
UChar second_byte = getUChar(eip); eip++;
vg_assert(second_byte >= 0xC0);
+
+ if (first_byte == 0xDB && second_byte >= 0xF0 && second_byte <= 0xF7) {
+ /* FCOMI */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDF && second_byte >= 0xF0 && second_byte <= 0xF7) {
+ /* FCOMIP */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDB && second_byte >= 0xE8 && second_byte <= 0xEF) {
+ /* FUCOMI */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDF && second_byte >= 0xE8 && second_byte <= 0xEF) {
+ /* FUCOMIP */
+ sets_ZCP = True;
+ }
+
uInstr1(cb, FPU, 0,
Lit16,
(((UShort)first_byte) << 8) | ((UShort)second_byte)
);
- if (dis) VG_(printf)("fpu 0x%x:0x%x\n",
- (UInt)first_byte, (UInt)second_byte );
+ if (sets_ZCP) {
+ /* VG_(printf)("!!! --- FPU insn which writes %EFLAGS\n"); */
+ uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty);
+ }
+
+ if (dis) VG_(printf)("fpu 0x%x:0x%x%s\n",
+ (UInt)first_byte, (UInt)second_byte,
+ sets_ZCP ? " -wZCP" : "" );
return eip;
}