diff --git a/lib/Arch/AArch64/Semantics/BINARY.cpp b/lib/Arch/AArch64/Semantics/BINARY.cpp index b57d9570..a69d453a 100644 --- a/lib/Arch/AArch64/Semantics/BINARY.cpp +++ b/lib/Arch/AArch64/Semantics/BINARY.cpp @@ -46,14 +46,15 @@ DEF_ISEL(SUB_64_ADDSUB_EXT) = SUB; namespace { template -T AddWithCarryNZCV(State &state, T lhs, T rhs, T carry) { +T AddWithCarryNZCV(State &state, T lhs, T rhs, T actual_rhs, T carry) { auto unsigned_result = UAdd(UAdd(ZExt(lhs), ZExt(rhs)), ZExt(carry)); auto signed_result = SAdd(SAdd(SExt(lhs), SExt(rhs)), Signed(ZExt(carry))); auto result = TruncTo(unsigned_result); - FLAG_N = SignFlag(result); - FLAG_Z = ZeroFlag(result); + FLAG_N = SignFlag(result, lhs, actual_rhs); + FLAG_Z = ZeroFlag(result, lhs, actual_rhs); FLAG_C = UCmpNeq(ZExt(result), unsigned_result); - FLAG_V = SCmpNeq(SExt(result), signed_result); + FLAG_V = __remill_flag_computation_overflow( + SCmpNeq(SExt(result), signed_result), lhs, actual_rhs, result); return result; } @@ -62,7 +63,7 @@ DEF_SEM(SUBS, D dst, S1 src1, S2 src2) { using T = typename BaseType::BT; auto lhs = Read(src1); auto rhs = Read(src2); - auto res = AddWithCarryNZCV(state, lhs, UNot(rhs), T(1)); + auto res = AddWithCarryNZCV(state, lhs, UNot(rhs), rhs, T(1)); WriteZExt(dst, res); return memory; } @@ -72,7 +73,7 @@ DEF_SEM(ADDS, D dst, S1 src1, S2 src2) { using T = typename BaseType::BT; auto lhs = Read(src1); auto rhs = Read(src2); - auto res = AddWithCarryNZCV(state, lhs, rhs, T(0)); + auto res = AddWithCarryNZCV(state, lhs, rhs, rhs, T(0)); WriteZExt(dst, res); return memory; } @@ -193,7 +194,8 @@ DEF_SEM(SBC, D dst, S src1, S src2) { template DEF_SEM(SBCS, D dst, S src1, S src2) { auto carry = ZExtTo(Unsigned(FLAG_C)); - auto res = AddWithCarryNZCV(state, Read(src1), UNot(Read(src2)), carry); + auto res = + AddWithCarryNZCV(state, Read(src1), UNot(Read(src2)), Read(src2), carry); WriteZExt(dst, res); return memory; } @@ -347,7 +349,7 @@ void FCompare(State &state, S val1, S val2, bool signal = true) { state.sr.ioc = true; } - // Regular float compare + // Regular float compare } else { if (FCmpEq(val1, val2)) { diff --git a/lib/Arch/AArch64/Semantics/COND.cpp b/lib/Arch/AArch64/Semantics/COND.cpp index 87a33c1c..995dc6f1 100644 --- a/lib/Arch/AArch64/Semantics/COND.cpp +++ b/lib/Arch/AArch64/Semantics/COND.cpp @@ -93,7 +93,8 @@ template DEF_SEM(CCMP, S1 src1, S2 src2, S2 nzcv) { using T = typename BaseType::BT; if (check_cond(state)) { - (void) AddWithCarryNZCV(state, Read(src1), UNot(Read(src2)), T(1)); + (void) AddWithCarryNZCV(state, Read(src1), UNot(Read(src2)), Read(src2), + T(1)); } else { auto nzcv_val = Read(nzcv); FLAG_V = UCmpNeq(UAnd(nzcv_val, T(1)), T(0)); @@ -108,7 +109,7 @@ template DEF_SEM(CCMN, S1 src1, S2 src2, S2 nzcv) { using T = typename BaseType::BT; if (check_cond(state)) { - (void) AddWithCarryNZCV(state, Read(src1), Read(src2), T(0)); + (void) AddWithCarryNZCV(state, Read(src1), Read(src2), Read(src2), T(0)); } else { auto nzcv_val = Read(nzcv); FLAG_V = UCmpNeq(UAnd(nzcv_val, T(1)), T(0)); diff --git a/lib/Arch/AArch64/Semantics/FLAGS.cpp b/lib/Arch/AArch64/Semantics/FLAGS.cpp index 407e0e9d..7676fe69 100644 --- a/lib/Arch/AArch64/Semantics/FLAGS.cpp +++ b/lib/Arch/AArch64/Semantics/FLAGS.cpp @@ -21,21 +21,28 @@ namespace { enum : uint32_t { kLHS = 2415899639U, kRHS = 70623199U }; // Zero flags, tells us whether or not a value is zero. -template -[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res) { - return __remill_flag_computation_zero(T(0) == res, res); +template +[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res, S1 lhs, S2 rhs) { + return __remill_flag_computation_zero(T(0) == res, lhs, rhs, res); } // Zero flags, tells us whether or not a value is zero. template -[[gnu::const]] ALWAYS_INLINE static bool NotZeroFlag(T res) { - return !__remill_flag_computation_zero(T(0) == res, res); +[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res) { + return T(0) == res; +} + + +// Zero flags, tells us whether or not a value is zero. +template +[[gnu::const]] ALWAYS_INLINE static bool NotZeroFlag(T res, S1 lhs, S2 rhs) { + return !__remill_flag_computation_zero(T(0) == res, lhs, rhs, res); } // Sign flag, tells us if a result is signed or unsigned. -template -[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res) { - return __remill_flag_computation_sign(0 > Signed(res), res); +template +[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res, S1 lhs, S2 rhs) { + return __remill_flag_computation_sign(0 > Signed(res), lhs, rhs, res); } // Tests whether there is an even number of bits in the low order byte. @@ -74,7 +81,8 @@ struct Overflow { const T sign_lhs = lhs >> kSignShift; const T sign_rhs = rhs >> kSignShift; const T sign_res = res >> kSignShift; - return 2 == (sign_lhs ^ sign_res) + (sign_rhs ^ sign_res); + return __remill_flag_computation_overflow( + 2 == (sign_lhs ^ sign_res) + (sign_rhs ^ sign_res), lhs, rhs, res); } }; diff --git a/lib/Arch/AArch64/Semantics/LOGICAL.cpp b/lib/Arch/AArch64/Semantics/LOGICAL.cpp index 055b02b6..2e74a796 100644 --- a/lib/Arch/AArch64/Semantics/LOGICAL.cpp +++ b/lib/Arch/AArch64/Semantics/LOGICAL.cpp @@ -56,8 +56,8 @@ template DEF_SEM(BICS, D dst, S1 src1, S2 src2) { auto res = UAnd(Read(src1), UNot(Read(src2))); WriteZExt(dst, res); - FLAG_N = SignFlag(res); - FLAG_Z = ZeroFlag(res); + FLAG_N = SignFlag(res, src1, src2); + FLAG_Z = ZeroFlag(res, src1, src2); FLAG_C = false; FLAG_V = false; return memory; @@ -99,8 +99,8 @@ template DEF_SEM(ANDS, D dst, S1 src1, S2 src2) { auto res = UAnd(Read(src1), Read(src2)); WriteZExt(dst, res); - FLAG_N = SignFlag(res); - FLAG_Z = ZeroFlag(res); + FLAG_N = SignFlag(res, src1, src2); + FLAG_Z = ZeroFlag(res, src1, src2); FLAG_C = false; FLAG_V = false; return memory; diff --git a/lib/Arch/SPARC32/Semantics/BINARY.cpp b/lib/Arch/SPARC32/Semantics/BINARY.cpp index 61cf1667..e1ea631a 100644 --- a/lib/Arch/SPARC32/Semantics/BINARY.cpp +++ b/lib/Arch/SPARC32/Semantics/BINARY.cpp @@ -6,8 +6,8 @@ namespace { template ALWAYS_INLINE static void WriteFlagsIncDec(State &state, T lhs, T rhs, T res) { - FLAG_ICC_ZF = ZeroFlag(res); - FLAG_ICC_NF = SignFlag(res); + FLAG_ICC_ZF = ZeroFlag(res, lhs, rhs); + FLAG_ICC_NF = SignFlag(res, lhs, rhs); FLAG_ICC_VF = Overflow::Flag(lhs, rhs, res); } @@ -20,16 +20,16 @@ ALWAYS_INLINE static void WriteFlagsAddSub(State &state, T lhs, T rhs, T res) { template ALWAYS_INLINE static void WriteXCCFlagsIncDec(State &state, T lhs, T rhs, T res) { - FLAG_XCC_ZF = ZeroFlag(res); - FLAG_XCC_NF = SignFlag(res); + FLAG_XCC_ZF = ZeroFlag(res, lhs, rhs); + FLAG_XCC_NF = SignFlag(res, lhs, rhs); FLAG_XCC_VF = Overflow::Flag(lhs, rhs, res); } template ALWAYS_INLINE static void WriteICCFlagsIncDec(State &state, T lhs, T rhs, T res) { - FLAG_ICC_ZF = ZeroFlag(res); - FLAG_ICC_NF = SignFlag(res); + FLAG_ICC_ZF = ZeroFlag(res, lhs, rhs); + FLAG_ICC_NF = SignFlag(res, lhs, rhs); FLAG_ICC_VF = Overflow::Flag(lhs, rhs, res); } @@ -145,8 +145,8 @@ DEF_SEM(SMULcc, S1 src1, S2 src2, D dst) { auto rhs_wide = SExt(rhs); auto res = SMul(lhs_wide, rhs_wide); auto res_trunc = TruncTo(res); - FLAG_ICC_NF = SignFlag(static_cast(res)); - FLAG_ICC_ZF = ZeroFlag(static_cast(res)); + FLAG_ICC_NF = SignFlag(static_cast(res), src1, src2); + FLAG_ICC_ZF = ZeroFlag(static_cast(res), src1, src2); FLAG_ICC_VF = 0; FLAG_ICC_CF = 0; auto index = Literal(32); @@ -176,8 +176,8 @@ DEF_SEM(UMULcc, S1 src1, S2 src2, D dst) { auto rhs_wide = ZExt(rhs); auto res = UMul(lhs_wide, rhs_wide); auto res_trunc = TruncTo(res); - FLAG_ICC_NF = SignFlag(static_cast(res)); - FLAG_ICC_ZF = ZeroFlag(static_cast(res)); + FLAG_ICC_NF = SignFlag(static_cast(res), src1, src2); + FLAG_ICC_ZF = ZeroFlag(static_cast(res), src1, src2); FLAG_ICC_VF = 0; FLAG_ICC_CF = 0; auto index = Literal(32); @@ -223,8 +223,8 @@ DEF_SEM(SDIVcc, S1 src1, S2 src2, D dst) { auto rhs = Read(src2); auto rhs_wide = SExt(rhs); auto quot = SDiv(y_lhs_wide, rhs_wide); - FLAG_ICC_NF = SignFlag(static_cast(quot)); - FLAG_ICC_ZF = ZeroFlag(static_cast(quot)); + FLAG_ICC_NF = SignFlag(static_cast(quot), src1, src2); + FLAG_ICC_ZF = ZeroFlag(static_cast(quot), src1, src2); FLAG_ICC_VF = Overflow::Flag(lhs, rhs, quot); FLAG_ICC_CF = 0; auto res = Overflow::Value(lhs, rhs, quot); @@ -250,8 +250,8 @@ DEF_SEM(UDIVcc, S1 src1, S2 src2, D dst) { auto lhs_wide = ZExt(lhs); auto rhs_wide = ZExt(rhs); auto quot = UDiv(lhs_wide, rhs_wide); - FLAG_ICC_NF = SignFlag(static_cast(quot)); - FLAG_ICC_ZF = ZeroFlag(static_cast(quot)); + FLAG_ICC_NF = SignFlag(static_cast(quot), src1, src2); + FLAG_ICC_ZF = ZeroFlag(static_cast(quot), src1, src2); FLAG_ICC_VF = Overflow::Flag(lhs, rhs, quot); FLAG_ICC_CF = 0; auto res = Overflow::Value(lhs, rhs, quot); diff --git a/lib/Arch/SPARC32/Semantics/FLAGS.cpp b/lib/Arch/SPARC32/Semantics/FLAGS.cpp index 576cdd04..8aac6782 100644 --- a/lib/Arch/SPARC32/Semantics/FLAGS.cpp +++ b/lib/Arch/SPARC32/Semantics/FLAGS.cpp @@ -19,21 +19,21 @@ namespace { // Zero flags, tells us whether or not a value is zero. -template -[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res) { - return __remill_flag_computation_zero(T(0) == res, res); +template +[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res, S1 lhs, S2 rhs) { + return __remill_flag_computation_zero(T(0) == res, lhs, rhs, res); } // Zero flags, tells us whether or not a value is zero. -template -[[gnu::const]] ALWAYS_INLINE static bool NotZeroFlag(T res) { - return !__remill_flag_computation_zero(T(0) == res); +template +[[gnu::const]] ALWAYS_INLINE static bool NotZeroFlag(T res, S1 lhs, S2 rhs) { + return !__remill_flag_computation_zero(T(0) == res, lhs, rhs, res); } // Sign flag, tells us if a result is signed or unsigned. -template -[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res) { - return __remill_flag_computation_sign(0 > Signed(res), res); +template +[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res, S1 lhs, S2 rhs) { + return __remill_flag_computation_sign(0 > Signed(res), lhs, rhs, res); } // Tests whether there is an even number of bits in the low order byte. diff --git a/lib/Arch/SPARC32/Semantics/LOGICAL.cpp b/lib/Arch/SPARC32/Semantics/LOGICAL.cpp index 5cbc1c3c..b1ad772c 100644 --- a/lib/Arch/SPARC32/Semantics/LOGICAL.cpp +++ b/lib/Arch/SPARC32/Semantics/LOGICAL.cpp @@ -7,8 +7,8 @@ namespace { template ALWAYS_INLINE void SetFlagsLogical(State &state, T lhs, T rhs, T res) { FLAG_ICC_CF = false; - FLAG_ICC_ZF = ZeroFlag(res); - FLAG_ICC_NF = SignFlag(res); + FLAG_ICC_ZF = ZeroFlag(res, lhs, rhs); + FLAG_ICC_NF = SignFlag(res, lhs, rhs); FLAG_ICC_VF = false; } diff --git a/lib/Arch/SPARC64/Semantics/BINARY.cpp b/lib/Arch/SPARC64/Semantics/BINARY.cpp index c59171a2..fc5207f7 100644 --- a/lib/Arch/SPARC64/Semantics/BINARY.cpp +++ b/lib/Arch/SPARC64/Semantics/BINARY.cpp @@ -20,8 +20,8 @@ namespace { template ALWAYS_INLINE static void WriteFlagsIncDec(State &state, T lhs, T rhs, T res) { - FLAG_ICC_ZF = ZeroFlag(res); - FLAG_ICC_NF = SignFlag(res); + FLAG_ICC_ZF = ZeroFlag(res, lhs, rhs); + FLAG_ICC_NF = SignFlag(res, lhs, rhs); FLAG_ICC_VF = Overflow::Flag(lhs, rhs, res); } @@ -34,16 +34,16 @@ ALWAYS_INLINE static void WriteFlagsAddSub(State &state, T lhs, T rhs, T res) { template ALWAYS_INLINE static void WriteXCCFlagsIncDec(State &state, T lhs, T rhs, T res) { - FLAG_XCC_ZF = ZeroFlag(res); - FLAG_XCC_NF = SignFlag(res); + FLAG_XCC_ZF = ZeroFlag(res, lhs, rhs); + FLAG_XCC_NF = SignFlag(res, lhs, rhs); FLAG_XCC_VF = Overflow::Flag(lhs, rhs, res); } template ALWAYS_INLINE static void WriteICCFlagsIncDec(State &state, T lhs, T rhs, T res) { - FLAG_ICC_ZF = ZeroFlag(res); - FLAG_ICC_NF = SignFlag(res); + FLAG_ICC_ZF = ZeroFlag(res, lhs, rhs); + FLAG_ICC_NF = SignFlag(res, lhs, rhs); FLAG_ICC_VF = Overflow::Flag(lhs, rhs, res); } @@ -214,8 +214,8 @@ DEF_SEM(TADDCC, S1 src1, S2 src2, D dst) { FLAG_ICC_CF = Carry::Flag(static_cast(rs1), static_cast(rs2), static_cast(sum)); - FLAG_ICC_ZF = ZeroFlag(static_cast(sum)); - FLAG_ICC_NF = SignFlag(static_cast(sum)); + FLAG_ICC_ZF = ZeroFlag(static_cast(sum), src1, src2); + FLAG_ICC_NF = SignFlag(static_cast(sum), src1, src2); WriteXCCFlagsAddSub(state, rs1, rs2, sum); Write(dst, sum); return memory; @@ -243,8 +243,8 @@ DEF_SEM(TADDCCTV, R8W cond, S1 src1, S2 src2, D dst) { FLAG_ICC_VF = tag_ov; FLAG_ICC_CF = Carry::Flag( Literal(rs1), Literal(rs2), Literal(sum)); - FLAG_ICC_ZF = ZeroFlag(static_cast(sum)); - FLAG_ICC_NF = SignFlag(static_cast(sum)); + FLAG_ICC_ZF = ZeroFlag(static_cast(sum), src1, src2); + FLAG_ICC_NF = SignFlag(static_cast(sum), src1, src2); WriteXCCFlagsAddSub(state, rs1, rs2, sum); return memory; } @@ -263,8 +263,8 @@ DEF_SEM(TSUBCC, S1 src1, S2 src2, D dst) { FLAG_ICC_CF = Carry::Flag(static_cast(rs1), static_cast(rs2), static_cast(res)); - FLAG_ICC_ZF = ZeroFlag(static_cast(res)); - FLAG_ICC_NF = SignFlag(static_cast(res)); + FLAG_ICC_ZF = ZeroFlag(static_cast(res), src1, src2); + FLAG_ICC_NF = SignFlag(static_cast(res), src1, src2); WriteXCCFlagsAddSub(state, rs1, rs2, res); return memory; } @@ -292,8 +292,8 @@ DEF_SEM(TSUBCCTV, R8W cond, S1 src1, S2 src2, D dst) { FLAG_ICC_VF = tag_ov; FLAG_ICC_CF = Carry::Flag( Literal(rs1), Literal(rs2), Literal(res)); - FLAG_ICC_ZF = ZeroFlag(Literal(res)); - FLAG_ICC_NF = SignFlag(Literal(res)); + FLAG_ICC_ZF = ZeroFlag(Literal(res), src1, src2); + FLAG_ICC_NF = SignFlag(Literal(res), src1, src2); WriteXCCFlagsAddSub(state, rs1, rs2, res); return memory; } @@ -344,12 +344,12 @@ DEF_SEM(SMULCC, S1 src1, S2 src2, D dst) { auto lhs_wide = SExt(lhs); auto rhs_wide = SExt(rhs); auto res = SMul(lhs_wide, rhs_wide); - FLAG_ICC_NF = SignFlag(static_cast(res)); - FLAG_ICC_ZF = ZeroFlag(static_cast(res)); + FLAG_ICC_NF = SignFlag(static_cast(res), src1, src2); + FLAG_ICC_ZF = ZeroFlag(static_cast(res), src1, src2); FLAG_ICC_VF = 0; FLAG_ICC_CF = 0; - FLAG_XCC_NF = SignFlag(static_cast(res)); - FLAG_XCC_ZF = ZeroFlag(static_cast(res)); + FLAG_XCC_NF = SignFlag(static_cast(res), src1, src2); + FLAG_XCC_ZF = ZeroFlag(static_cast(res), src1, src2); FLAG_XCC_VF = 0; FLAG_XCC_CF = 0; auto index = Literal(32); @@ -380,12 +380,12 @@ DEF_SEM(UMULcc, S1 src1, S2 src2, D dst) { auto lhs_wide = ZExt(lhs); auto rhs_wide = ZExt(rhs); auto res = UMul(lhs_wide, rhs_wide); - FLAG_ICC_NF = SignFlag(static_cast(res)); - FLAG_ICC_ZF = ZeroFlag(static_cast(res)); + FLAG_ICC_NF = SignFlag(static_cast(res), src1, src2); + FLAG_ICC_ZF = ZeroFlag(static_cast(res), src1, src2); FLAG_ICC_VF = 0; FLAG_ICC_CF = 0; - FLAG_XCC_NF = SignFlag(static_cast(res)); - FLAG_XCC_ZF = ZeroFlag(static_cast(res)); + FLAG_XCC_NF = SignFlag(static_cast(res), src1, src2); + FLAG_XCC_ZF = ZeroFlag(static_cast(res), src1, src2); FLAG_XCC_VF = 0; FLAG_XCC_CF = 0; auto index = Literal(32); @@ -429,12 +429,12 @@ DEF_SEM(SDIVCC, S1 src1, S2 src2, D dst) { auto rhs = Read(src2); auto rhs_wide = SExt(rhs); auto quot = SDiv(y_lhs_wide, rhs_wide); - FLAG_ICC_NF = SignFlag(static_cast(quot)); - FLAG_ICC_ZF = ZeroFlag(static_cast(quot)); + FLAG_ICC_NF = SignFlag(static_cast(quot), src1, src2); + FLAG_ICC_ZF = ZeroFlag(static_cast(quot), src1, src2); FLAG_ICC_VF = Overflow::Flag(lhs, rhs, quot); FLAG_ICC_CF = 0; - FLAG_XCC_NF = SignFlag(static_cast(quot)); - FLAG_XCC_ZF = ZeroFlag(static_cast(quot)); + FLAG_XCC_NF = SignFlag(static_cast(quot), src1, src2); + FLAG_XCC_ZF = ZeroFlag(static_cast(quot), src1, src2); FLAG_XCC_VF = 0; FLAG_XCC_CF = 0; auto res = Overflow::Value(lhs, rhs, quot); @@ -465,12 +465,12 @@ DEF_SEM(UDIVCC, S1 src1, S2 src2, D dst) { auto lhs_wide = UOr(shift_y, ZExt(lhs)); auto rhs_wide = ZExt(rhs); auto quot = UDiv(lhs_wide, rhs_wide); - FLAG_ICC_NF = SignFlag(static_cast(quot)); - FLAG_ICC_ZF = ZeroFlag(static_cast(quot)); + FLAG_ICC_NF = SignFlag(static_cast(quot), src1, src2); + FLAG_ICC_ZF = ZeroFlag(static_cast(quot), src1, src2); FLAG_ICC_VF = Overflow::Flag(lhs, rhs, quot); FLAG_ICC_CF = 0; - FLAG_XCC_NF = SignFlag(static_cast(quot)); - FLAG_XCC_ZF = ZeroFlag(static_cast(quot)); + FLAG_XCC_NF = SignFlag(static_cast(quot), src1, src2); + FLAG_XCC_ZF = ZeroFlag(static_cast(quot), src1, src2); FLAG_XCC_VF = 0; FLAG_XCC_CF = 0; auto res = Overflow::Value(lhs, rhs, quot); diff --git a/lib/Arch/SPARC64/Semantics/LOGICAL.cpp b/lib/Arch/SPARC64/Semantics/LOGICAL.cpp index 09524ae0..77738969 100644 --- a/lib/Arch/SPARC64/Semantics/LOGICAL.cpp +++ b/lib/Arch/SPARC64/Semantics/LOGICAL.cpp @@ -22,13 +22,13 @@ ALWAYS_INLINE void SetFlagsLogical(State &state, uint64_t lhs, uint64_t rhs, uint64_t res) { const auto res_32 = static_cast(res); FLAG_ICC_CF = false; - FLAG_ICC_ZF = ZeroFlag(res_32); - FLAG_ICC_NF = SignFlag(res_32); + FLAG_ICC_ZF = ZeroFlag(res_32, lhs, rhs); + FLAG_ICC_NF = SignFlag(res_32, lhs, rhs); FLAG_ICC_VF = false; FLAG_XCC_CF = false; - FLAG_XCC_ZF = ZeroFlag(res); - FLAG_XCC_NF = SignFlag(res); + FLAG_XCC_ZF = ZeroFlag(res, lhs, rhs); + FLAG_XCC_NF = SignFlag(res, lhs, rhs); FLAG_XCC_VF = false; } diff --git a/lib/Arch/X86/Semantics/BINARY.cpp b/lib/Arch/X86/Semantics/BINARY.cpp index 1189906b..f27a3fa0 100644 --- a/lib/Arch/X86/Semantics/BINARY.cpp +++ b/lib/Arch/X86/Semantics/BINARY.cpp @@ -22,8 +22,8 @@ template ALWAYS_INLINE static void WriteFlagsIncDec(State &state, T lhs, T rhs, T res) { FLAG_PF = ParityFlag(res); FLAG_AF = AuxCarryFlag(lhs, rhs, res); - FLAG_ZF = ZeroFlag(res); - FLAG_SF = SignFlag(res); + FLAG_ZF = ZeroFlag(res, lhs, rhs); + FLAG_SF = SignFlag(res, lhs, rhs); FLAG_OF = Overflow::Flag(lhs, rhs, res); } diff --git a/lib/Arch/X86/Semantics/FLAGS.cpp b/lib/Arch/X86/Semantics/FLAGS.cpp index 24bf2daf..d107b5b0 100644 --- a/lib/Arch/X86/Semantics/FLAGS.cpp +++ b/lib/Arch/X86/Semantics/FLAGS.cpp @@ -22,22 +22,34 @@ namespace { // is executed. enum : uint32_t { kLHS = 2415899639U, kRHS = 70623199U }; -// Zero flags, tells us whether or not a value is zero. + template [[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res) { - return __remill_flag_computation_zero(T(0) == res, res); + return T(0) == res; +} + +template +[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res) { + return 0 > Signed(res); +} + + +// Zero flags, tells us whether or not a value is zero. +template +[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res, S1 lhs, S2 rhs) { + return __remill_flag_computation_zero(T(0) == res, lhs, rhs, res); } // Zero flags, tells us whether or not a value is zero. -template -[[gnu::const]] ALWAYS_INLINE static bool NotZeroFlag(T res) { - return !__remill_flag_computation_zero(T(0) == res, res); +template +[[gnu::const]] ALWAYS_INLINE static bool NotZeroFlag(T res, S1 lhs, S2 rhs) { + return !__remill_flag_computation_zero(T(0) == res, lhs, rhs, res); } // Sign flag, tells us if a result is signed or unsigned. -template -[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res) { - return __remill_flag_computation_sign(0 > Signed(res), res); +template +[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res, S1 lhs, S2 rhs) { + return __remill_flag_computation_sign(0 > Signed(res), lhs, rhs, res); } // Auxiliary carry flag. This is used for binary coded decimal operations and diff --git a/lib/Arch/X86/Semantics/LOGICAL.cpp b/lib/Arch/X86/Semantics/LOGICAL.cpp index 03054e0e..4d62cbd1 100644 --- a/lib/Arch/X86/Semantics/LOGICAL.cpp +++ b/lib/Arch/X86/Semantics/LOGICAL.cpp @@ -22,8 +22,8 @@ template ALWAYS_INLINE void SetFlagsLogical(State &state, T lhs, T rhs, T res) { state.aflag.cf = false; state.aflag.pf = ParityFlag(res); - state.aflag.zf = ZeroFlag(res); - state.aflag.sf = SignFlag(res); + state.aflag.zf = ZeroFlag(res, lhs, rhs); + state.aflag.sf = SignFlag(res, lhs, rhs); state.aflag.of = false; state.aflag.af = false; // Undefined, but ends up being `0`. }