* vg_to_ucode.c (disInstr): Implement DAA as well as DAS.
Byrial Jensen <byrial@image.dk>
+ (dis_fpu_no_mem): Detect FPU instructions which set %EFLAGS and
+ mark the resulting UInstrs accordingly.
+
* vg_errcontext.c (pp_ErrContext): Change message "Use of
uninitialized CPU condition code" to "Conditional jump or move
depends on uninitialised value(s)", since that will be more
case FPU:
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == NoValue);
+ vg_assert(u->flags_r == FlagsEmpty);
+ if (u->flags_w != FlagsEmpty)
+ emit_get_eflags();
synth_fpu_no_mem ( (u->val1 >> 8) & 0xFF,
u->val1 & 0xFF );
+ if (u->flags_w != FlagsEmpty)
+ emit_put_eflags();
break;
default:
#define FlagsOSACP (FlagO | FlagS | FlagA | FlagC | FlagP)
#define FlagsSZACP ( FlagS | FlagZ | FlagA | FlagC | FlagP)
#define FlagsSZAP ( FlagS | FlagZ | FlagA | FlagP)
+#define FlagsZCP ( FlagZ | FlagC | FlagP)
#define FlagsOC (FlagO | FlagC )
#define FlagsAC ( FlagA | FlagC )
static
Addr dis_fpu_no_mem ( UCodeBlock* cb, Addr eip, UChar first_byte )
{
+ Bool sets_ZCP = False;
UChar second_byte = getUChar(eip); eip++;
vg_assert(second_byte >= 0xC0);
+
+ if (first_byte == 0xDB && second_byte >= 0xF0 && second_byte <= 0xF7) {
+ /* FCOMI */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDF && second_byte >= 0xF0 && second_byte <= 0xF7) {
+ /* FCOMIP */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDB && second_byte >= 0xE8 && second_byte <= 0xEF) {
+ /* FUCOMI */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDF && second_byte >= 0xE8 && second_byte <= 0xEF) {
+ /* FUCOMIP */
+ sets_ZCP = True;
+ }
+
uInstr1(cb, FPU, 0,
Lit16,
(((UShort)first_byte) << 8) | ((UShort)second_byte)
);
- if (dis) VG_(printf)("fpu 0x%x:0x%x\n",
- (UInt)first_byte, (UInt)second_byte );
+ if (sets_ZCP) {
+ /* VG_(printf)("!!! --- FPU insn which writes %EFLAGS\n"); */
+ uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty);
+ }
+
+ if (dis) VG_(printf)("fpu 0x%x:0x%x%s\n",
+ (UInt)first_byte, (UInt)second_byte,
+ sets_ZCP ? " -wZCP" : "" );
return eip;
}
# define CC0 (u->flags_r == FlagsEmpty && u->flags_w == FlagsEmpty)
# define FLG_RD (u->flags_r == FlagsALL && u->flags_w == FlagsEmpty)
# define FLG_WR (u->flags_r == FlagsEmpty && u->flags_w == FlagsALL)
+# define FLG_WR_MAYBE (u->flags_r == FlagsEmpty && \
+ (u->flags_w == FlagsEmpty || u->flags_w == FlagsZCP))
# define CC1 (!(CC0))
# define SZ4_IF_TR1 ((u->tag1 == TempReg || u->tag1 == RealReg) \
? (u->size == 4) : True)
case FPU_R: case FPU_W:
return CC0 && Ls1 && TR2 && N3;
case FPU:
- return SZ0 && CC0 && Ls1 && N2 && N3;
+ return SZ0 && FLG_WR_MAYBE && Ls1 && N2 && N3;
case LOADV:
return CC0 && TR1 && TR2 && N3;
case STOREV:
# undef N3
# undef FLG_RD
# undef FLG_WR
+# undef FLG_WR_MAYBE
}
case FPU:
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == NoValue);
+ vg_assert(u->flags_r == FlagsEmpty);
+ if (u->flags_w != FlagsEmpty)
+ emit_get_eflags();
synth_fpu_no_mem ( (u->val1 >> 8) & 0xFF,
u->val1 & 0xFF );
+ if (u->flags_w != FlagsEmpty)
+ emit_put_eflags();
break;
default:
#define FlagsOSACP (FlagO | FlagS | FlagA | FlagC | FlagP)
#define FlagsSZACP ( FlagS | FlagZ | FlagA | FlagC | FlagP)
#define FlagsSZAP ( FlagS | FlagZ | FlagA | FlagP)
+#define FlagsZCP ( FlagZ | FlagC | FlagP)
#define FlagsOC (FlagO | FlagC )
#define FlagsAC ( FlagA | FlagC )
static
Addr dis_fpu_no_mem ( UCodeBlock* cb, Addr eip, UChar first_byte )
{
+ Bool sets_ZCP = False;
UChar second_byte = getUChar(eip); eip++;
vg_assert(second_byte >= 0xC0);
+
+ if (first_byte == 0xDB && second_byte >= 0xF0 && second_byte <= 0xF7) {
+ /* FCOMI */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDF && second_byte >= 0xF0 && second_byte <= 0xF7) {
+ /* FCOMIP */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDB && second_byte >= 0xE8 && second_byte <= 0xEF) {
+ /* FUCOMI */
+ sets_ZCP = True;
+ } else
+ if (first_byte == 0xDF && second_byte >= 0xE8 && second_byte <= 0xEF) {
+ /* FUCOMIP */
+ sets_ZCP = True;
+ }
+
uInstr1(cb, FPU, 0,
Lit16,
(((UShort)first_byte) << 8) | ((UShort)second_byte)
);
- if (dis) VG_(printf)("fpu 0x%x:0x%x\n",
- (UInt)first_byte, (UInt)second_byte );
+ if (sets_ZCP) {
+ /* VG_(printf)("!!! --- FPU insn which writes %EFLAGS\n"); */
+ uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty);
+ }
+
+ if (dis) VG_(printf)("fpu 0x%x:0x%x%s\n",
+ (UInt)first_byte, (UInt)second_byte,
+ sets_ZCP ? " -wZCP" : "" );
return eip;
}
# define CC0 (u->flags_r == FlagsEmpty && u->flags_w == FlagsEmpty)
# define FLG_RD (u->flags_r == FlagsALL && u->flags_w == FlagsEmpty)
# define FLG_WR (u->flags_r == FlagsEmpty && u->flags_w == FlagsALL)
+# define FLG_WR_MAYBE (u->flags_r == FlagsEmpty && \
+ (u->flags_w == FlagsEmpty || u->flags_w == FlagsZCP))
# define CC1 (!(CC0))
# define SZ4_IF_TR1 ((u->tag1 == TempReg || u->tag1 == RealReg) \
? (u->size == 4) : True)
case FPU_R: case FPU_W:
return CC0 && Ls1 && TR2 && N3;
case FPU:
- return SZ0 && CC0 && Ls1 && N2 && N3;
+ return SZ0 && FLG_WR_MAYBE && Ls1 && N2 && N3;
case LOADV:
return CC0 && TR1 && TR2 && N3;
case STOREV:
# undef N3
# undef FLG_RD
# undef FLG_WR
+# undef FLG_WR_MAYBE
}