diff --git a/src/instructions_portable.cpp b/src/instructions_portable.cpp index e8dfd62..caecd27 100644 --- a/src/instructions_portable.cpp +++ b/src/instructions_portable.cpp @@ -127,9 +127,7 @@ along with RandomX. If not, see. void rx_reset_float_state() { setRoundMode_(FE_TONEAREST); -#ifdef RANDOMX_USE_X87 - _control87(_PC_53, _MCW_PC); //set x87 precision to 53 bits -#endif + rx_set_double_precision(); //set precision to 53 bits if needed by the platform } void rx_set_rounding_mode(uint32_t mode) { @@ -153,6 +151,28 @@ void rx_set_rounding_mode(uint32_t mode) { #endif +#ifdef RANDOMX_USE_X87 + +#ifdef _M_IX86 + +void rx_set_double_precision() { + _control87(_PC_53, _MCW_PC); +} + +#elif defined(__i386) + +void rx_set_double_precision() { + uint16_t volatile x87cw; + asm volatile("fstcw %0" : "=m" (x87cw)); + x87cw &= ~0x300; + x87cw |= 0x200; + asm volatile("fldcw %0" : : "m" (x87cw)); +} + +#endif + +#endif //RANDOMX_USE_X87 + union double_ser_t { double f; uint64_t i; diff --git a/src/intrin_portable.h b/src/intrin_portable.h index 7c972f5..6b5a507 100644 --- a/src/intrin_portable.h +++ b/src/intrin_portable.h @@ -46,7 +46,8 @@ constexpr int RoundToZero = 3; //the library "sqrt" function provided by MSVC for x86 targets doesn't give //the correct results, so we have to use inline assembly to call x87 fsqrt directly -#if defined(_M_IX86) && !defined(__SSE2__) +#if !defined(__SSE2__) +#if defined(_M_IX86) inline double __cdecl rx_sqrt(double x) { __asm { fld x @@ -54,13 +55,26 @@ inline double __cdecl rx_sqrt(double x) { } } #define rx_sqrt rx_sqrt + +void rx_set_double_precision(); #define RANDOMX_USE_X87 + +#elif defined(__i386) + +void rx_set_double_precision(); +#define RANDOMX_USE_X87 + #endif +#endif //__SSE2__ #if !defined(rx_sqrt) #define rx_sqrt sqrt #endif +#if !defined(RANDOMX_USE_X87) +#define rx_set_double_precision +#endif + #ifdef __SSE2__ #ifdef __GNUC__ #include