Skip to content

Commit

Permalink
fix FRNDINT, ftst
Browse files Browse the repository at this point in the history
Fix setting de flag; add tests
  • Loading branch information
kumarak committed Aug 24, 2021
1 parent a52f370 commit 13756fb
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 24 deletions.
34 changes: 18 additions & 16 deletions include/remill/Arch/Runtime/Operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,21 +566,19 @@ MAKE_ATOMIC(XorFetch, xor_and_fetch, ^)

#if !defined(issignaling)

ALWAYS_INLINE uint8_t issignaling(float32_t x) {
ALWAYS_INLINE bool issignaling(float32_t x) {
const nan32_t x_nan = {x};
return x_nan.exponent == 0xFFU && !x_nan.is_quiet_nan && x_nan.payload;
}

ALWAYS_INLINE uint8_t issignaling(float64_t x) {
ALWAYS_INLINE bool issignaling(float64_t x) {
const nan64_t x_nan = {x};
return x_nan.exponent == 0x7FFU && !x_nan.is_quiet_nan && x_nan.payload;
}

ALWAYS_INLINE uint8_t issignaling(float80_t x) {
// this casts to a float64_t on purpose -- since we know that
// it is almost certainly an IEEE 754 double which we can decompose
const nan64_t x_nan = {static_cast<float64_t>(x)};
return x_nan.exponent == 0x7FFFU && !(x_nan.is_quiet_nan) && x_nan.payload;
ALWAYS_INLINE bool issignaling(float80_t x) {
const nan80_t x_nan = {x};
return x_nan.exponent == 0x7FFFU && !x_nan.is_quiet_nan && x_nan.payload && x_nan.interger_bit;
}

#endif // !defined(issignaling)
Expand Down Expand Up @@ -652,26 +650,31 @@ ALWAYS_INLINE static uint8_t IsNaN(float80_t x) {
return static_cast<uint8_t>(FP_NAN == std::fpclassify(static_cast<native_float80_t>(x)));
}

ALWAYS_INLINE static uint8_t IsSignalingNaN(float32_t x) {
ALWAYS_INLINE static bool IsSignalingNaN(float32_t x) {
const nan32_t x_nan = {x};
return x_nan.exponent == 0xFFU && !x_nan.is_quiet_nan && x_nan.payload;
}

ALWAYS_INLINE static uint8_t IsSignalingNaN(float64_t x) {
ALWAYS_INLINE static bool IsSignalingNaN(float64_t x) {
const nan64_t x_nan = {x};
return x_nan.exponent == 0x7FFU && !x_nan.is_quiet_nan && x_nan.payload;
}

ALWAYS_INLINE static uint8_t IsSignalingNaN(float80_t x) {
ALWAYS_INLINE static bool IsSignalingNaN(float80_t x) {
const nan80_t x_nan = {x};
return x_nan.exponent == 0x7FFFU && !x_nan.is_quiet_nan && x_nan.payload;
return x_nan.exponent == 0x7FFFU && !x_nan.is_quiet_nan && x_nan.payload && x_nan.interger_bit;
}

template <typename T>
ALWAYS_INLINE static uint8_t IsSignalingNaN(T) {
return 0;
}

template <typename T>
ALWAYS_INLINE static uint8_t IsDenormal(T x) {
return static_cast<uint8_t>(FP_SUBNORMAL == std::fpclassify(x));
}

ALWAYS_INLINE static uint8_t IsDenormal(float32_t x) {
return static_cast<uint8_t>(FP_SUBNORMAL == std::fpclassify(x));
}
Expand All @@ -684,6 +687,10 @@ ALWAYS_INLINE static uint8_t IsDenormal(float80_t x) {
return static_cast<uint8_t>(FP_SUBNORMAL == std::fpclassify(static_cast<native_float80_t>(x)));
}

ALWAYS_INLINE static uint8_t IsDenormal(native_float80_t x) {
return static_cast<uint8_t>(FP_SUBNORMAL == std::fpclassify(static_cast<native_float80_t>(x)));
}

template <typename T>
ALWAYS_INLINE static uint8_t IsZero(T val) {
return static_cast<uint8_t>(!val);
Expand All @@ -699,11 +706,6 @@ ALWAYS_INLINE static uint8_t IsNaN(T) {
return 0;
}

template <typename T>
ALWAYS_INLINE static uint8_t IsDenormal(T) {
return 0;
}

// Return the largest possible value assignable to `val`.
template <typename T>
ALWAYS_INLINE static T Maximize(T) {
Expand Down
28 changes: 20 additions & 8 deletions lib/Arch/X86/Semantics/X87.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,16 @@ DEF_FPU_SEM(FILD, RF80W, T src1) {
template <typename T>
DEF_FPU_SEM(FLD, RF80W, T src1) {
SetFPUIpOp();
auto val = Float80(Read(src1));
auto val = Read(src1);
state.sw.ie |= IsSignalingNaN(val);
state.sw.de = IsDenormal(val);
auto res = val;
auto res = Float80(val);

// Quietize if signaling NaN.
if (state.sw.ie) {
nan64_t res_nan = {Float64(res)};
nan80_t res_nan = {res};
res_nan.is_quiet_nan = 1;
res = Float80(res_nan.d);
res = res_nan.d;
}

PUSH_X87_STACK(res);
Expand Down Expand Up @@ -392,6 +392,18 @@ DEF_SEM(DoFWAIT) {

DEF_SEM(DoFNCLEX) {
feclearexcept(FE_ALL_EXCEPT);
state.sw.pe = 0;
state.sw.ue = 0;
state.sw.oe = 0;
state.sw.ze = 0;
state.sw.de = 0;
state.sw.ie = 0;

state.sw.c0 = UUndefined8();
state.sw.c1 = UUndefined8();
state.sw.c2 = UUndefined8();
state.sw.c3 = UUndefined8();

return memory;
}

Expand Down Expand Up @@ -998,7 +1010,7 @@ DEF_FPU_SEM(DoFXAM) {
}

DEF_HELPER(OrderedCompare, native_float80_t src1, native_float80_t src2)->void {
state.sw.de = IsDenormal(src1) | IsDenormal(src2);
state.sw.de |= IsDenormal(src1) | IsDenormal(src2);
state.sw.ie = 0;

if (__builtin_isunordered(src1, src2)) {
Expand All @@ -1024,7 +1036,7 @@ DEF_HELPER(OrderedCompare, native_float80_t src1, native_float80_t src2)->void {
}

DEF_HELPER(UnorderedCompare, native_float80_t src1, native_float80_t src2)->void {
state.sw.de = IsDenormal(src1) | IsDenormal(src2);
state.sw.de |= IsDenormal(src1) | IsDenormal(src2);
state.sw.ie = 0;

if (__builtin_isunordered(src1, src2)) {
Expand Down Expand Up @@ -1146,7 +1158,7 @@ DEF_FPU_SEM(DoFCOMPP) {
}

DEF_HELPER(UnorderedCompareEflags, native_float80_t src1, native_float80_t src2)->void {
state.sw.de = IsDenormal(src1) | IsDenormal(src2);
state.sw.de |= IsDenormal(src1) | IsDenormal(src2);
state.sw.ie = 0;

if (__builtin_isunordered(src1, src2)) {
Expand All @@ -1173,7 +1185,7 @@ DEF_HELPER(UnorderedCompareEflags, native_float80_t src1, native_float80_t src2)
}

DEF_HELPER(OrderedCompareEflags, native_float80_t src1, native_float80_t src2)->void {
state.sw.de = IsDenormal(src1) | IsDenormal(src2);
state.sw.de |= IsDenormal(src1) | IsDenormal(src2);
state.sw.ie = 0;

if (__builtin_isunordered(src1, src2)) {
Expand Down
12 changes: 12 additions & 0 deletions tests/X86/X87/FCOM.S
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,18 @@ TEST_INPUTS(TEST_INPUTS_MMX_QWORD)
fcomi st(2)
TEST_END_64

TEST_BEGIN_64(FCOMIst0st2_CE, 2)
TEST_INPUTS(TEST_INPUTS_MMX_QWORD)
push ARG1_64
fld QWORD PTR [rsp]
push ARG2_64
fld QWORD PTR [rsp]
push ARG2_64
fld QWORD PTR [rsp]
fnclex
fcomi st(2)
TEST_END_64

TEST_BEGIN_64(FCOMIPst0st2, 2)
TEST_INPUTS(TEST_INPUTS_MMX_QWORD)
push ARG1_64
Expand Down
23 changes: 23 additions & 0 deletions tests/X86/X87/MISC.S
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,29 @@ TEST_INPUTS(
ftst
TEST_END_64

TEST_BEGIN_64(FTST_CE, 1)
TEST_INPUTS(
QNAN_64,
SNAN_64,
0x7ff0000000000000, /* +inf */
0xfff0000000000000, /* -inf */
0xfff8000000000000, /* -nan */
0x7ff8000000000000, /* nan */
0x0010000000000000, /* std::numeric_limits<double>::min() */
0x7fefffffffffffff, /* std::numeric_limits<double>::max() */
0x0008000000000000, /* std::numeric_limits<double>::min() / 2.0 */
0x8008000000000000, /* std::numeric_limits<double>::min() / -2.0 */
0x0000000000000000, /* +0 */
0x8000000000000000, /* -0 */
0x3fe0000000000000, /* 0.5 */
0xbfe0000000000000) /* -0.5 */

push ARG1_64
fld QWORD PTR [rsp]
fnclex
ftst
TEST_END_64

TEST_BEGIN_64(FRNDINT, 1)
TEST_INPUTS(
QNAN_64,
Expand Down

0 comments on commit 13756fb

Please sign in to comment.