Selaa lähdekoodia

Fixed x87 math precision (i386 build)

tevador 7 vuotta sitten
vanhempi
sitoutus
2a04dfdd4f
2 muutettua tiedostoa jossa 38 lisäystä ja 4 poistoa
  1. 23 3
      src/instructions_portable.cpp
  2. 15 1
      src/intrin_portable.h

+ 23 - 3
src/instructions_portable.cpp

@@ -127,9 +127,7 @@ along with RandomX.  If not, see<http://www.gnu.org/licenses/>.
 
 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;

+ 15 - 1
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 <x86intrin.h>