Discussion:
vex: r3367 - /trunk/priv/guest_amd64_toIR.c
Add Reply
s***@valgrind.org
2017-05-13 16:41:00 UTC
Reply
Permalink
Raw Message
Author: sewardj
Date: Sat May 13 17:40:59 2017
New Revision: 3367

Log:
Bug 367543 - bt/btc/btr/bts x86/x86_64 instructions are poorly-handled wrt flags.
This fixes the flag handling to be like Skylake.

Modified:
trunk/priv/guest_amd64_toIR.c

Modified: trunk/priv/guest_amd64_toIR.c
==============================================================================
--- trunk/priv/guest_amd64_toIR.c (original)
+++ trunk/priv/guest_amd64_toIR.c Sat May 13 17:40:59 2017
@@ -8215,18 +8215,31 @@
}
}

- /* Side effect done; now get selected bit into Carry flag */
- /* Flags: C=selected bit, O,S,Z,A,P undefined, so are set to zero. */
+ /* Side effect done; now get selected bit into Carry flag. The Intel docs
+ (as of 2015, at least) say that C holds the result, Z is unchanged, and
+ O,S,A and P are undefined. However, on Skylake it appears that O,S,A,P
+ are also unchanged, so let's do that. */
+ const ULong maskC = AMD64G_CC_MASK_C;
+ const ULong maskOSZAP = AMD64G_CC_MASK_O | AMD64G_CC_MASK_S
+ | AMD64G_CC_MASK_Z | AMD64G_CC_MASK_A
+ | AMD64G_CC_MASK_P;
+
+ IRTemp old_rflags = newTemp(Ity_I64);
+ assign(old_rflags, mk_amd64g_calculate_rflags_all());
+
+ IRTemp new_rflags = newTemp(Ity_I64);
+ assign(new_rflags,
+ binop(Iop_Or64,
+ binop(Iop_And64, mkexpr(old_rflags), mkU64(maskOSZAP)),
+ binop(Iop_And64,
+ binop(Iop_Shr64,
+ unop(Iop_8Uto64, mkexpr(t_fetched)),
+ mkexpr(t_bitno2)),
+ mkU64(maskC))));
+
stmt( IRStmt_Put( OFFB_CC_OP, mkU64(AMD64G_CC_OP_COPY) ));
stmt( IRStmt_Put( OFFB_CC_DEP2, mkU64(0) ));
- stmt( IRStmt_Put(
- OFFB_CC_DEP1,
- binop(Iop_And64,
- binop(Iop_Shr64,
- unop(Iop_8Uto64, mkexpr(t_fetched)),
- mkexpr(t_bitno2)),
- mkU64(1)))
- );
+ stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(new_rflags) ));
/* Set NDEP even though it isn't used. This makes redundant-PUT
elimination of previous stores to this field work better. */
stmt( IRStmt_Put( OFFB_CC_NDEP, mkU64(0) ));

Loading...