Merge patch from JeremyF:
75-simple-jle
Another pattern to test for Jle/Jnle. The observation is that EFLAGS
looks like this:
----O--+SZ------
with Z in bit 6, S in 7 and O in 11. Therefore RORL $7, %eflags will
result in:
Z------+-------+-------+---O---S
Since parity is only computed on the lower 8 bits, testing on P will
determine whether O==S, and since Z is in the MSB, it can be tested
with S.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1366 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c
index b3603a1..f2e89c4 100644
--- a/coregrind/vg_from_ucode.c
+++ b/coregrind/vg_from_ucode.c
@@ -1887,9 +1887,11 @@
{
UInt mask;
Bool simd;
- Int tgt;
+ Int tgt, tgt2, tgt_jump;
VG_(init_target)(&tgt);
+ VG_(init_target)(&tgt2);
+ VG_(init_target)(&tgt_jump);
/* Ensure simulated %EFLAGS are up-to-date, by copying back %eflags
if need be */
@@ -1914,32 +1916,32 @@
switch (cond) {
- case CondLE:
- case CondNLE:
+ case CondLE: /* Z || S != O -> S || !P */
+ case CondNLE: /* !Z && S == O -> !S && P */
vg_assert(eax_trashable);
VG_(emit_movv_offregmem_reg)
( 4, VGOFF_(m_eflags) * 4, R_EBP, R_EAX );
/* eax == %EFLAGS */
- VG_(emit_shiftopv_lit_reg)( False, 4, SHR, 11-7, R_EAX );
- /* eax has OF in SF's place */
+ VG_(emit_nonshiftopv_lit_reg)
+ ( False, 4, AND, EFlagO|EFlagS|EFlagZ, R_EAX );
+ /* eax just contains OF, SF and ZF */
- emit_nonshiftopv_offregmem_reg
- ( False, 4, XOR, VGOFF_(m_eflags) * 4, R_EBP, R_EAX );
- /* eax has (OF xor SF) in SF's place */
+ VG_(emit_shiftopv_lit_reg)( False, 4, ROR, 7, R_EAX );
+ /* eax has OF and SF in lower 8 bits, and ZF in MSB */
- VG_(emit_shiftopv_lit_reg)( False, 4, SHR, 7-6, R_EAX );
- /* eax has (OF xor SF) in ZF's place */
-
- emit_nonshiftopv_offregmem_reg
- ( False, 4, OR, VGOFF_(m_eflags) * 4, R_EBP, R_EAX );
- /* eax has ((OF xor SF) or ZF) in SF's place */
-
- VG_(emit_nonshiftopv_lit_reg)( False, 4, AND, 1 << 6, R_EAX );
- /* Z is now set iff ((OF xor SF) or ZF) == 1 */
-
- if (cond == CondLE) cond = CondZ; else cond = CondNZ;
+ if (cond == CondLE) {
+ /* test Z */
+ VG_(emit_jcondshort_target)(False, CondS, &tgt_jump);
+ /* test OF != SF */
+ cond = CondP;
+ } else {
+ /* test Z */
+ VG_(emit_jcondshort_target)(False, CondS, &tgt2);
+ /* test OF == SF */
+ cond = CondNP;
+ }
break;
case CondL:
@@ -2018,9 +2020,12 @@
}
VG_(emit_jcondshort_target) ( simd, cond, &tgt );
+
+ VG_(target_forward)(&tgt_jump);
synth_jmp_lit ( addr, JmpBoring );
VG_(target_forward)(&tgt);
+ VG_(target_forward)(&tgt2);
}