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