For FPU/MMX/SSE instructions which don't reference any memory, make memcheck
look at whether the eflags are read or written and generate UCode to validate
and/or mark as valid the eflags when necessary.

CCMAIL: 78514-done@bugs.kde.org


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2344 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c
index 7a2e05b..301d9da 100644
--- a/memcheck/mc_translate.c
+++ b/memcheck/mc_translate.c
@@ -1177,12 +1177,26 @@
             VG_(copy_UInstr)(cb, u_in);
 	    break;
          }
-
-         /* For FPU, MMX and SSE insns not referencing memory, just
-            copy thru. */
+         
+         /* For MMX and SSE insns not referencing memory, just
+            make sure the eflags are defined if the instruction
+            read them, and make them defined it it writes them. */
          case SSE5: case SSE4: case SSE3:
          case MMX1: case MMX2: case MMX3:
-         case FPU: 
+         case FPU:
+            if (u_in->flags_r != FlagsEmpty) {
+               qt = create_GETVF(cb, 0);
+               uInstr1(cb, TESTV, 0, TempReg, qt);
+               /* qt should never be referred to again.  Nevertheless
+                  ... */
+               uInstr1(cb, SETV, 0, TempReg, qt);
+            }
+            if (u_in->flags_w != FlagsEmpty) {
+               qd = newTemp(cb);
+               uInstr2(cb, MOV, 4, Literal, 0, TempReg, qd);
+               uLiteral(cb, qd);
+               create_PUTVF(cb, 0, qd);
+            }
             VG_(copy_UInstr)(cb, u_in);
             break;
 
diff --git a/memcheck/tests/.cvsignore b/memcheck/tests/.cvsignore
index 42dfbb8..9fc694b 100644
--- a/memcheck/tests/.cvsignore
+++ b/memcheck/tests/.cvsignore
@@ -16,6 +16,7 @@
 exitprog
 filter_leak_check_size
 filter_stderr
+fpeflags
 fprw
 fwrite
 inits
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
index 40ba819..37a3dba 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
@@ -27,6 +27,7 @@
 	errs1.stderr.exp errs1.vgtest \
 	exitprog.stderr.exp exitprog.vgtest \
 	execve.stderr.exp execve.vgtest \
+	fpeflags.stderr.exp fpeflags.vgtest \
 	fprw.stderr.exp fprw.vgtest \
 	fwrite.stderr.exp fwrite.stdout.exp fwrite.vgtest \
 	inits.stderr.exp inits.vgtest \
@@ -75,7 +76,7 @@
 	badaddrvalue badfree badjump badloop badrw brk buflen_check \
 	clientperm custom_alloc \
 	doublefree error_counts errs1 exitprog execve \
-	fprw fwrite inits inline \
+	fpeflags fprw fwrite inits inline \
 	malloc1 malloc2 malloc3 manuel1 manuel2 manuel3 \
 	memalign_test memcmptest mmaptest nanoleak new_nothrow null_socket \
 	overlap pushfpopf \
@@ -102,6 +103,7 @@
 errs1_SOURCES 		= errs1.c
 execve_SOURCES 		= execve.c
 exitprog_SOURCES 	= exitprog.c
+fpeflags_SOURCES	= fpeflags.c
 fprw_SOURCES 		= fprw.c
 fwrite_SOURCES 		= fwrite.c
 inits_SOURCES		= inits.c
@@ -141,3 +143,5 @@
 new_nothrow_SOURCES 	= new_nothrow.cpp
 new_override_SOURCES 	= new_override.cpp
 
+# must be built with these flags -- bug only occurred with them
+fpeflags.o: CFLAGS += -march=i686
diff --git a/memcheck/tests/fpeflags.c b/memcheck/tests/fpeflags.c
new file mode 100644
index 0000000..27cd3e3
--- /dev/null
+++ b/memcheck/tests/fpeflags.c
@@ -0,0 +1,20 @@
+#include <stdlib.h>
+
+struct instance
+{
+    unsigned myVal:1;
+};
+
+static struct instance* myInstance;
+
+int main(int argc, char** argv)
+{
+    float g = 1.0f;
+    
+    myInstance = malloc(sizeof(struct instance));
+
+    myInstance->myVal = 1;
+
+    if (g == 1.0f)
+        return 0;
+}
diff --git a/memcheck/tests/fpeflags.stderr.exp b/memcheck/tests/fpeflags.stderr.exp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/memcheck/tests/fpeflags.stderr.exp
diff --git a/memcheck/tests/fpeflags.vgtest b/memcheck/tests/fpeflags.vgtest
new file mode 100644
index 0000000..88ae11d
--- /dev/null
+++ b/memcheck/tests/fpeflags.vgtest
@@ -0,0 +1,2 @@
+vgopts: -q
+prog: fpeflags