Improve accuracy of simulation of bsf/bsr instructions when the word
being scanned is zero.  (Zoltan Hidvegi)


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@205 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_helpers.S b/coregrind/vg_helpers.S
index e802081..62db9ec 100644
--- a/coregrind/vg_helpers.S
+++ b/coregrind/vg_helpers.S
@@ -343,16 +343,18 @@
 .global VG_(helper_bsr)
 VG_(helper_bsr):
 	pushl	%eax
+	movl	12(%esp), %eax
 	bsrl	8(%esp), %eax
-	movl	%eax, 8(%esp)
+	movl	%eax, 12(%esp)
 	popl	%eax
 	ret
 
 .global VG_(helper_bsf)
 VG_(helper_bsf):
 	pushl	%eax
+	movl	12(%esp), %eax
 	bsfl	8(%esp), %eax
-	movl	%eax, 8(%esp)
+	movl	%eax, 12(%esp)
 	popl	%eax
 	ret
 
diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c
index 691ef26..4be838c 100644
--- a/coregrind/vg_to_ucode.c
+++ b/coregrind/vg_to_ucode.c
@@ -2758,7 +2758,7 @@
 static
 Addr dis_bs_E_G ( UCodeBlock* cb, Int sz, Addr eip, Bool fwds )
 {
-   Int   t, ta, helper;
+   Int   t, t1, ta, helper;
    UInt  pair;
    UChar dis_buf[50];
    UChar modrm;
@@ -2768,8 +2768,13 @@
 
    helper = fwds ? VGOFF_(helper_bsf) : VGOFF_(helper_bsr);
    modrm  = getUChar(eip);
+   t1     = newTemp(cb);
    t      = newTemp(cb);
 
+   uInstr0(cb, CALLM_S, 0);
+   uInstr2(cb, GET,  sz, ArchReg, gregOfRM(modrm), TempReg, t1);
+   uInstr1(cb, PUSH, sz, TempReg, t1);
+
    if (epartIsReg(modrm)) {
       eip++;
       uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t);
@@ -2790,11 +2795,11 @@
                      nameIReg(sz, gregOfRM(modrm)));
    }
 
-   uInstr0(cb, CALLM_S, 0);
    uInstr1(cb, PUSH,  sz,  TempReg, t);
    uInstr1(cb, CALLM, 0,   Lit16, helper);
    uFlagsRWU(cb, FlagsEmpty, FlagZ, FlagsOSACP);
    uInstr1(cb, POP,   sz,  TempReg, t);
+   uInstr1(cb, POP,   sz,  TempReg, t);
    uInstr2(cb, PUT,   sz,  TempReg, t, ArchReg, gregOfRM(modrm));
    uInstr0(cb, CALLM_E, 0);
 
diff --git a/vg_helpers.S b/vg_helpers.S
index e802081..62db9ec 100644
--- a/vg_helpers.S
+++ b/vg_helpers.S
@@ -343,16 +343,18 @@
 .global VG_(helper_bsr)
 VG_(helper_bsr):
 	pushl	%eax
+	movl	12(%esp), %eax
 	bsrl	8(%esp), %eax
-	movl	%eax, 8(%esp)
+	movl	%eax, 12(%esp)
 	popl	%eax
 	ret
 
 .global VG_(helper_bsf)
 VG_(helper_bsf):
 	pushl	%eax
+	movl	12(%esp), %eax
 	bsfl	8(%esp), %eax
-	movl	%eax, 8(%esp)
+	movl	%eax, 12(%esp)
 	popl	%eax
 	ret
 
diff --git a/vg_to_ucode.c b/vg_to_ucode.c
index 691ef26..4be838c 100644
--- a/vg_to_ucode.c
+++ b/vg_to_ucode.c
@@ -2758,7 +2758,7 @@
 static
 Addr dis_bs_E_G ( UCodeBlock* cb, Int sz, Addr eip, Bool fwds )
 {
-   Int   t, ta, helper;
+   Int   t, t1, ta, helper;
    UInt  pair;
    UChar dis_buf[50];
    UChar modrm;
@@ -2768,8 +2768,13 @@
 
    helper = fwds ? VGOFF_(helper_bsf) : VGOFF_(helper_bsr);
    modrm  = getUChar(eip);
+   t1     = newTemp(cb);
    t      = newTemp(cb);
 
+   uInstr0(cb, CALLM_S, 0);
+   uInstr2(cb, GET,  sz, ArchReg, gregOfRM(modrm), TempReg, t1);
+   uInstr1(cb, PUSH, sz, TempReg, t1);
+
    if (epartIsReg(modrm)) {
       eip++;
       uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t);
@@ -2790,11 +2795,11 @@
                      nameIReg(sz, gregOfRM(modrm)));
    }
 
-   uInstr0(cb, CALLM_S, 0);
    uInstr1(cb, PUSH,  sz,  TempReg, t);
    uInstr1(cb, CALLM, 0,   Lit16, helper);
    uFlagsRWU(cb, FlagsEmpty, FlagZ, FlagsOSACP);
    uInstr1(cb, POP,   sz,  TempReg, t);
+   uInstr1(cb, POP,   sz,  TempReg, t);
    uInstr2(cb, PUT,   sz,  TempReg, t, ArchReg, gregOfRM(modrm));
    uInstr0(cb, CALLM_E, 0);