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;
 }