case FPU:
vg_assert(u->tag1 == Lit16);
vg_assert(u->tag2 == NoValue);
- vg_assert(u->flags_r == FlagsEmpty);
- if (u->flags_w != FlagsEmpty)
+ if (u->flags_r != FlagsEmpty || u->flags_w != FlagsEmpty)
emit_get_eflags();
synth_fpu_no_mem ( (u->val1 >> 8) & 0xFF,
u->val1 & 0xFF );
Addr dis_fpu_no_mem ( UCodeBlock* cb, Addr eip, UChar first_byte )
{
Bool sets_ZCP = False;
+ Bool uses_ZCP = False;
UChar second_byte = getUChar(eip); eip++;
vg_assert(second_byte >= 0xC0);
+ /* Does the insn write any integer condition codes (%EIP) ? */
+
if (first_byte == 0xDB && second_byte >= 0xF0 && second_byte <= 0xF7) {
/* FCOMI */
sets_ZCP = True;
sets_ZCP = True;
}
+ /* Dually, does the insn read any integer condition codes (%EIP) ? */
+
+ if (first_byte == 0xDA && second_byte >= 0xC0 && second_byte <= 0xDF) {
+ /* FCMOVB %st(n), %st(0)
+ FCMOVE %st(n), %st(0)
+ FCMOVBE %st(n), %st(0)
+ FCMOVU %st(n), %st(0)
+ */
+ uses_ZCP = True;
+ } else
+ if (first_byte == 0xDB && second_byte >= 0xC0 && second_byte <= 0xDF) {
+ /* FCMOVNB %st(n), %st(0)
+ FCMOVNE %st(n), %st(0)
+ FCMOVNBE %st(n), %st(0)
+ FCMOVNU %st(n), %st(0)
+ */
+ uses_ZCP = True;
+ }
+
uInstr1(cb, FPU, 0,
Lit16,
(((UShort)first_byte) << 8) | ((UShort)second_byte)
);
+ if (uses_ZCP) {
+ /* VG_(printf)("!!! --- FPU insn which reads %EFLAGS\n"); */
+ uFlagsRWU(cb, FlagsZCP, FlagsEmpty, FlagsEmpty);
+ vg_assert(!sets_ZCP);
+ }
if (sets_ZCP) {
/* VG_(printf)("!!! --- FPU insn which writes %EFLAGS\n"); */
uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty);
+ vg_assert(!uses_ZCP);
}
- if (dis) VG_(printf)("fpu 0x%x:0x%x%s\n",
+ if (dis) VG_(printf)("fpu 0x%x:0x%x%s%s\n",
(UInt)first_byte, (UInt)second_byte,
+ uses_ZCP ? " -rZCP" : "",
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 FLG_RD_WR_MAYBE \
+ ((u->flags_r == FlagsEmpty && u->flags_w == FlagsEmpty) \
+ || (u->flags_r == FlagsEmpty && u->flags_w == FlagsZCP) \
+ || (u->flags_r == FlagsZCP && u->flags_w == FlagsEmpty))
# define CC1 (!(CC0))
# define SZ4_IF_TR1 ((u->tag1 == TempReg || u->tag1 == RealReg) \
? (u->size == 4) : True)
switch (u->opcode) {
case GETF:
- return (SZ2 || SZ4) && TR1 && N2 && N3 && FLG_RD;
+ return (SZ2 || SZ4) && TR1 && N2 && N3 && FLG_RD;
case PUTF:
- return (SZ2 || SZ4) && TR1 && N2 && N3 && FLG_WR;
+ return (SZ2 || SZ4) && TR1 && N2 && N3 && FLG_WR;
case CALLM_S: case CALLM_E:
return SZ0 && N1 && N2 && N3;
case INCEIP:
case FPU_R: case FPU_W:
return CC0 && Ls1 && TR2 && N3;
case FPU:
- return SZ0 && FLG_WR_MAYBE && Ls1 && N2 && N3;
+ return SZ0 && FLG_RD_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
+# undef FLG_RD_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)
+ if (u->flags_r != FlagsEmpty || u->flags_w != FlagsEmpty)
emit_get_eflags();
synth_fpu_no_mem ( (u->val1 >> 8) & 0xFF,
u->val1 & 0xFF );
Addr dis_fpu_no_mem ( UCodeBlock* cb, Addr eip, UChar first_byte )
{
Bool sets_ZCP = False;
+ Bool uses_ZCP = False;
UChar second_byte = getUChar(eip); eip++;
vg_assert(second_byte >= 0xC0);
+ /* Does the insn write any integer condition codes (%EIP) ? */
+
if (first_byte == 0xDB && second_byte >= 0xF0 && second_byte <= 0xF7) {
/* FCOMI */
sets_ZCP = True;
sets_ZCP = True;
}
+ /* Dually, does the insn read any integer condition codes (%EIP) ? */
+
+ if (first_byte == 0xDA && second_byte >= 0xC0 && second_byte <= 0xDF) {
+ /* FCMOVB %st(n), %st(0)
+ FCMOVE %st(n), %st(0)
+ FCMOVBE %st(n), %st(0)
+ FCMOVU %st(n), %st(0)
+ */
+ uses_ZCP = True;
+ } else
+ if (first_byte == 0xDB && second_byte >= 0xC0 && second_byte <= 0xDF) {
+ /* FCMOVNB %st(n), %st(0)
+ FCMOVNE %st(n), %st(0)
+ FCMOVNBE %st(n), %st(0)
+ FCMOVNU %st(n), %st(0)
+ */
+ uses_ZCP = True;
+ }
+
uInstr1(cb, FPU, 0,
Lit16,
(((UShort)first_byte) << 8) | ((UShort)second_byte)
);
+ if (uses_ZCP) {
+ /* VG_(printf)("!!! --- FPU insn which reads %EFLAGS\n"); */
+ uFlagsRWU(cb, FlagsZCP, FlagsEmpty, FlagsEmpty);
+ vg_assert(!sets_ZCP);
+ }
if (sets_ZCP) {
/* VG_(printf)("!!! --- FPU insn which writes %EFLAGS\n"); */
uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty);
+ vg_assert(!uses_ZCP);
}
- if (dis) VG_(printf)("fpu 0x%x:0x%x%s\n",
+ if (dis) VG_(printf)("fpu 0x%x:0x%x%s%s\n",
(UInt)first_byte, (UInt)second_byte,
+ uses_ZCP ? " -rZCP" : "",
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 FLG_RD_WR_MAYBE \
+ ((u->flags_r == FlagsEmpty && u->flags_w == FlagsEmpty) \
+ || (u->flags_r == FlagsEmpty && u->flags_w == FlagsZCP) \
+ || (u->flags_r == FlagsZCP && u->flags_w == FlagsEmpty))
# define CC1 (!(CC0))
# define SZ4_IF_TR1 ((u->tag1 == TempReg || u->tag1 == RealReg) \
? (u->size == 4) : True)
switch (u->opcode) {
case GETF:
- return (SZ2 || SZ4) && TR1 && N2 && N3 && FLG_RD;
+ return (SZ2 || SZ4) && TR1 && N2 && N3 && FLG_RD;
case PUTF:
- return (SZ2 || SZ4) && TR1 && N2 && N3 && FLG_WR;
+ return (SZ2 || SZ4) && TR1 && N2 && N3 && FLG_WR;
case CALLM_S: case CALLM_E:
return SZ0 && N1 && N2 && N3;
case INCEIP:
case FPU_R: case FPU_W:
return CC0 && Ls1 && TR2 && N3;
case FPU:
- return SZ0 && FLG_WR_MAYBE && Ls1 && N2 && N3;
+ return SZ0 && FLG_RD_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
+# undef FLG_RD_WR_MAYBE
}