mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
Added binop forms of sign and zero flags (#567)
* added binop forms of sign and zero flags * added passing real rhs for aarch64
This commit is contained in:
@@ -46,14 +46,15 @@ DEF_ISEL(SUB_64_ADDSUB_EXT) = SUB<R64W, R64, I64>;
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
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<T>(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<S2>::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<S2>::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 <typename D, typename S>
|
||||
DEF_SEM(SBCS, D dst, S src1, S src2) {
|
||||
auto carry = ZExtTo<S>(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)) {
|
||||
|
||||
|
||||
@@ -93,7 +93,8 @@ template <bool (*check_cond)(const State &), typename S1, typename S2>
|
||||
DEF_SEM(CCMP, S1 src1, S2 src2, S2 nzcv) {
|
||||
using T = typename BaseType<S1>::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 <bool (*check_cond)(const State &), typename S1, typename S2>
|
||||
DEF_SEM(CCMN, S1 src1, S2 src2, S2 nzcv) {
|
||||
using T = typename BaseType<S1>::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));
|
||||
|
||||
@@ -21,21 +21,28 @@ namespace {
|
||||
enum : uint32_t { kLHS = 2415899639U, kRHS = 70623199U };
|
||||
|
||||
// Zero flags, tells us whether or not a value is zero.
|
||||
template <typename T>
|
||||
[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res) {
|
||||
return __remill_flag_computation_zero(T(0) == res, res);
|
||||
template <typename T, typename S1, typename S2>
|
||||
[[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 <typename T>
|
||||
[[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 <typename T, typename S1, typename S2>
|
||||
[[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 <typename T>
|
||||
[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res) {
|
||||
return __remill_flag_computation_sign(0 > Signed(res), res);
|
||||
template <typename T, typename S1, typename S2>
|
||||
[[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<tag_add> {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ template <typename D, typename S1, typename S2>
|
||||
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 <typename D, typename S1, typename S2>
|
||||
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;
|
||||
|
||||
@@ -6,8 +6,8 @@ namespace {
|
||||
|
||||
template <typename Tag, typename T>
|
||||
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<Tag>::Flag(lhs, rhs, res);
|
||||
}
|
||||
|
||||
@@ -20,16 +20,16 @@ ALWAYS_INLINE static void WriteFlagsAddSub(State &state, T lhs, T rhs, T res) {
|
||||
template <typename Tag, typename T>
|
||||
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<Tag>::Flag(lhs, rhs, res);
|
||||
}
|
||||
|
||||
template <typename Tag, typename T>
|
||||
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<Tag>::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<S1>(res);
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(res));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_VF = 0;
|
||||
FLAG_ICC_CF = 0;
|
||||
auto index = Literal<S1>(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<S1>(res);
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(res));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_VF = 0;
|
||||
FLAG_ICC_CF = 0;
|
||||
auto index = Literal<S1>(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<uint32_t>(quot));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(quot));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(quot), src1, src2);
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(quot), src1, src2);
|
||||
FLAG_ICC_VF = Overflow<tag_sdiv>::Flag(lhs, rhs, quot);
|
||||
FLAG_ICC_CF = 0;
|
||||
auto res = Overflow<tag_sdiv>::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<uint32_t>(quot));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(quot));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(quot), src1, src2);
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(quot), src1, src2);
|
||||
FLAG_ICC_VF = Overflow<tag_udiv>::Flag(lhs, rhs, quot);
|
||||
FLAG_ICC_CF = 0;
|
||||
auto res = Overflow<tag_udiv>::Value(lhs, rhs, quot);
|
||||
|
||||
@@ -19,21 +19,21 @@
|
||||
namespace {
|
||||
|
||||
// Zero flags, tells us whether or not a value is zero.
|
||||
template <typename T>
|
||||
[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res) {
|
||||
return __remill_flag_computation_zero(T(0) == res, res);
|
||||
template <typename T, typename S1, typename S2>
|
||||
[[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 <typename T>
|
||||
[[gnu::const]] ALWAYS_INLINE static bool NotZeroFlag(T res) {
|
||||
return !__remill_flag_computation_zero(T(0) == res);
|
||||
template <typename T, typename S1, typename S2>
|
||||
[[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 <typename T>
|
||||
[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res) {
|
||||
return __remill_flag_computation_sign(0 > Signed(res), res);
|
||||
template <typename T, typename S1, typename S2>
|
||||
[[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.
|
||||
|
||||
@@ -7,8 +7,8 @@ namespace {
|
||||
template <typename T>
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace {
|
||||
|
||||
template <typename Tag, typename T>
|
||||
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<Tag>::Flag(lhs, rhs, res);
|
||||
}
|
||||
|
||||
@@ -34,16 +34,16 @@ ALWAYS_INLINE static void WriteFlagsAddSub(State &state, T lhs, T rhs, T res) {
|
||||
template <typename Tag, typename T>
|
||||
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<Tag>::Flag(lhs, rhs, res);
|
||||
}
|
||||
|
||||
template <typename Tag, typename T>
|
||||
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<Tag>::Flag(lhs, rhs, res);
|
||||
}
|
||||
|
||||
@@ -214,8 +214,8 @@ DEF_SEM(TADDCC, S1 src1, S2 src2, D dst) {
|
||||
FLAG_ICC_CF = Carry<tag_add>::Flag(static_cast<uint32_t>(rs1),
|
||||
static_cast<uint32_t>(rs2),
|
||||
static_cast<uint32_t>(sum));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(sum));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(sum));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(sum), src1, src2);
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(sum), src1, src2);
|
||||
WriteXCCFlagsAddSub<tag_add>(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<tag_add>::Flag(
|
||||
Literal<uint32_t>(rs1), Literal<uint32_t>(rs2), Literal<uint32_t>(sum));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(sum));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(sum));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(sum), src1, src2);
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(sum), src1, src2);
|
||||
WriteXCCFlagsAddSub<tag_add>(state, rs1, rs2, sum);
|
||||
return memory;
|
||||
}
|
||||
@@ -263,8 +263,8 @@ DEF_SEM(TSUBCC, S1 src1, S2 src2, D dst) {
|
||||
FLAG_ICC_CF = Carry<tag_sub>::Flag(static_cast<uint32_t>(rs1),
|
||||
static_cast<uint32_t>(rs2),
|
||||
static_cast<uint32_t>(res));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(res));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
WriteXCCFlagsAddSub<tag_sub>(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<tag_sub>::Flag(
|
||||
Literal<uint32_t>(rs1), Literal<uint32_t>(rs2), Literal<uint32_t>(res));
|
||||
FLAG_ICC_ZF = ZeroFlag(Literal<uint32_t>(res));
|
||||
FLAG_ICC_NF = SignFlag(Literal<uint32_t>(res));
|
||||
FLAG_ICC_ZF = ZeroFlag(Literal<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_NF = SignFlag(Literal<uint32_t>(res), src1, src2);
|
||||
WriteXCCFlagsAddSub<tag_sub>(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<uint32_t>(res));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_VF = 0;
|
||||
FLAG_ICC_CF = 0;
|
||||
FLAG_XCC_NF = SignFlag(static_cast<uint64_t>(res));
|
||||
FLAG_XCC_ZF = ZeroFlag(static_cast<uint64_t>(res));
|
||||
FLAG_XCC_NF = SignFlag(static_cast<uint64_t>(res), src1, src2);
|
||||
FLAG_XCC_ZF = ZeroFlag(static_cast<uint64_t>(res), src1, src2);
|
||||
FLAG_XCC_VF = 0;
|
||||
FLAG_XCC_CF = 0;
|
||||
auto index = Literal<S1>(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<uint32_t>(res));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(res), src1, src2);
|
||||
FLAG_ICC_VF = 0;
|
||||
FLAG_ICC_CF = 0;
|
||||
FLAG_XCC_NF = SignFlag(static_cast<uint64_t>(res));
|
||||
FLAG_XCC_ZF = ZeroFlag(static_cast<uint64_t>(res));
|
||||
FLAG_XCC_NF = SignFlag(static_cast<uint64_t>(res), src1, src2);
|
||||
FLAG_XCC_ZF = ZeroFlag(static_cast<uint64_t>(res), src1, src2);
|
||||
FLAG_XCC_VF = 0;
|
||||
FLAG_XCC_CF = 0;
|
||||
auto index = Literal<S1>(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<uint32_t>(quot));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(quot));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(quot), src1, src2);
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(quot), src1, src2);
|
||||
FLAG_ICC_VF = Overflow<tag_sdiv>::Flag(lhs, rhs, quot);
|
||||
FLAG_ICC_CF = 0;
|
||||
FLAG_XCC_NF = SignFlag(static_cast<uint64_t>(quot));
|
||||
FLAG_XCC_ZF = ZeroFlag(static_cast<uint64_t>(quot));
|
||||
FLAG_XCC_NF = SignFlag(static_cast<uint64_t>(quot), src1, src2);
|
||||
FLAG_XCC_ZF = ZeroFlag(static_cast<uint64_t>(quot), src1, src2);
|
||||
FLAG_XCC_VF = 0;
|
||||
FLAG_XCC_CF = 0;
|
||||
auto res = Overflow<tag_sdiv>::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<uint32_t>(quot));
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(quot));
|
||||
FLAG_ICC_NF = SignFlag(static_cast<uint32_t>(quot), src1, src2);
|
||||
FLAG_ICC_ZF = ZeroFlag(static_cast<uint32_t>(quot), src1, src2);
|
||||
FLAG_ICC_VF = Overflow<tag_udiv>::Flag(lhs, rhs, quot);
|
||||
FLAG_ICC_CF = 0;
|
||||
FLAG_XCC_NF = SignFlag(static_cast<uint64_t>(quot));
|
||||
FLAG_XCC_ZF = ZeroFlag(static_cast<uint64_t>(quot));
|
||||
FLAG_XCC_NF = SignFlag(static_cast<uint64_t>(quot), src1, src2);
|
||||
FLAG_XCC_ZF = ZeroFlag(static_cast<uint64_t>(quot), src1, src2);
|
||||
FLAG_XCC_VF = 0;
|
||||
FLAG_XCC_CF = 0;
|
||||
auto res = Overflow<tag_udiv>::Value(lhs, rhs, quot);
|
||||
|
||||
@@ -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<uint32_t>(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ template <typename Tag, typename T>
|
||||
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<Tag>::Flag(lhs, rhs, res);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <typename T>
|
||||
[[gnu::const]] ALWAYS_INLINE static bool ZeroFlag(T res) {
|
||||
return __remill_flag_computation_zero(T(0) == res, res);
|
||||
return T(0) == res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[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 <typename T, typename S1, typename S2>
|
||||
[[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 <typename T>
|
||||
[[gnu::const]] ALWAYS_INLINE static bool NotZeroFlag(T res) {
|
||||
return !__remill_flag_computation_zero(T(0) == res, res);
|
||||
template <typename T, typename S1, typename S2>
|
||||
[[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 <typename T>
|
||||
[[gnu::const]] ALWAYS_INLINE static bool SignFlag(T res) {
|
||||
return __remill_flag_computation_sign(0 > Signed(res), res);
|
||||
template <typename T, typename S1, typename S2>
|
||||
[[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
|
||||
|
||||
@@ -22,8 +22,8 @@ template <typename T>
|
||||
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`.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user