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