#include <msvcrt/float.h>
+#define X87_CW_IM (1<<0) /* Invalid operation mask */
+#define X87_CW_DM (1<<1) /* Denormal operand mask */
+#define X87_CW_ZM (1<<2) /* Zero divide mask */
+#define X87_CW_OM (1<<3) /* Overflow mask */
+#define X87_CW_UM (1<<4) /* Underflow mask */
+#define X87_CW_PM (1<<5) /* Precision mask */
+
+#define X87_CW_PC_MASK (3<<8) /* precision control mask */
+#define X87_CW_PC24 (0<<8) /* 24 bit precision */
+#define X87_CW_PC53 (2<<8) /* 53 bit precision */
+#define X87_CW_PC64 (3<<8) /* 64 bit precision */
+
+#define X87_CW_RC_MASK (3<<10) /* rounding control mask */
+#define X87_CW_RC_NEAREST (0<<10) /* round to nearest */
+#define X87_CW_RC_DOWN (1<<10) /* round down */
+#define X87_CW_RC_UP (2<<10) /* round up */
+#define X87_CW_RC_ZERO (3<<10) /* round toward zero (chop) */
+
+#define X87_CW_IC (1<<12) /* infinity control flag */
+
/*
* @implemented
*/
-unsigned int _controlfp (unsigned int unNew, unsigned int unMask)
-{
- return _control87(unNew,unMask);
+unsigned int _controlfp(unsigned int unNew, unsigned int unMask)
+{
+ return _control87(unNew,unMask);
}
/*
* @implemented
*/
-unsigned int _control87 (unsigned int unNew, unsigned int unMask)
-{
+unsigned int _control87(unsigned int unNew, unsigned int unMask)
+{
+ unsigned int FpuCw;
+ unsigned int DummyCw = 0;
+
+ /* get the controlword */
+ asm volatile("fstcw %0\n\t" : "=m"(FpuCw));
+ FpuCw &= 0x0000ffff;
+
+ /* translate it into _control87 format */
+ if (FpuCw & X87_CW_IM)
+ DummyCw |= _EM_INVALID;
+ if (FpuCw & X87_CW_DM)
+ DummyCw |= _EM_DENORMAL;
+ if (FpuCw & X87_CW_ZM)
+ DummyCw |= _EM_ZERODIVIDE;
+ if (FpuCw & X87_CW_OM)
+ DummyCw |= _EM_OVERFLOW;
+ if (FpuCw & X87_CW_UM)
+ DummyCw |= _EM_UNDERFLOW;
+ if (FpuCw & X87_CW_PM)
+ DummyCw |= _EM_INEXACT;
+
+ switch (FpuCw & X87_CW_PC_MASK)
+ {
+ case X87_CW_PC24:
+ DummyCw |= _PC_24;
+ break;
+ case X87_CW_PC53:
+ DummyCw |= _PC_53;
+ break;
+ case X87_CW_PC64:
+ DummyCw |= _PC_64;
+ break;
+ }
+
+ switch (FpuCw & X87_CW_RC_MASK)
+ {
+ case X87_CW_RC_NEAREST:
+ DummyCw |= _RC_NEAR;
+ break;
+ case X87_CW_RC_DOWN:
+ DummyCw |= _RC_DOWN;
+ break;
+ case X87_CW_RC_UP:
+ DummyCw |= _RC_UP;
+ break;
+ case X87_CW_RC_ZERO:
+ DummyCw |= _RC_CHOP;
+ break;
+ }
+
+ /* unset (un)masked bits */
+ DummyCw &= ~unMask;
+ unNew &= unMask;
+
+ /* set new bits */
+ DummyCw |= unNew;
+
+ /* translate back into x87 format
+ * FIXME: translate infinity control!
+ */
+ FpuCw = 0;
+ if (DummyCw & _EM_INVALID)
+ FpuCw |= X87_CW_IM;
+ if (DummyCw & _EM_DENORMAL)
+ FpuCw |= X87_CW_DM;
+ if (DummyCw & _EM_ZERODIVIDE)
+ FpuCw |= X87_CW_ZM;
+ if (DummyCw & _EM_OVERFLOW)
+ FpuCw |= X87_CW_OM;
+ if (DummyCw & _EM_UNDERFLOW)
+ FpuCw |= X87_CW_UM;
+ if (DummyCw & _EM_INEXACT)
+ FpuCw |= X87_CW_PM;
+
+ switch (DummyCw & _MCW_PC)
+ {
+ case _PC_24:
+ FpuCw |= X87_CW_PC24;
+ break;
+ case _PC_53:
+ FpuCw |= X87_CW_PC53;
+ break;
+ case _PC_64:
+ default:
+ FpuCw |= X87_CW_PC64;
+ break;
+ }
+
+ switch (DummyCw & _MCW_RC)
+ {
+ case _RC_NEAR:
+ FpuCw |= X87_CW_RC_NEAREST;
+ break;
+ case _RC_DOWN:
+ FpuCw |= X87_CW_RC_DOWN;
+ break;
+ case _RC_UP:
+ FpuCw |= X87_CW_RC_UP;
+ break;
+ case _RC_CHOP:
+ FpuCw |= X87_CW_RC_ZERO;
+ break;
+ }
+
+ /* set controlword */
+ asm volatile("fldcw %0" : : "m"(FpuCw));
+
+ return DummyCw;
+
+#if 0 /* The follwing is the original code, broken I think! -blight */
register unsigned int __res;
#ifdef __GNUC__
__asm__ __volatile__ (
"fldcw (%%esp) \n\t"
"popl %%edx \n\t"
- :"=r" (__res):"r" (unNew),"r" (unMask): "ax", "dx", "cx");
+ :"=a" (__res):"r" (unNew),"r" (unMask): "dx", "cx");
#else
#endif /*__GNUC__*/
return __res;
+#endif
}
#include <msvcrt/float.h>
+#define X87_CW_IM (1<<0) /* Invalid operation mask */
+#define X87_CW_DM (1<<1) /* Denormal operand mask */
+#define X87_CW_ZM (1<<2) /* Zero divide mask */
+#define X87_CW_OM (1<<3) /* Overflow mask */
+#define X87_CW_UM (1<<4) /* Underflow mask */
+#define X87_CW_PM (1<<5) /* Precision mask */
+
+#define X87_CW_PC_MASK (3<<8) /* precision control mask */
+#define X87_CW_PC24 (0<<8) /* 24 bit precision */
+#define X87_CW_PC53 (2<<8) /* 53 bit precision */
+#define X87_CW_PC64 (3<<8) /* 64 bit precision */
+
+#define X87_CW_RC_MASK (3<<10) /* rounding control mask */
+#define X87_CW_RC_NEAREST (0<<10) /* round to nearest */
+#define X87_CW_RC_DOWN (1<<10) /* round down */
+#define X87_CW_RC_UP (2<<10) /* round up */
+#define X87_CW_RC_ZERO (3<<10) /* round toward zero (chop) */
+
+#define X87_CW_IC (1<<12) /* infinity control flag */
+
/*
* @implemented
*/
*/
unsigned int _control87(unsigned int unNew, unsigned int unMask)
{
+ unsigned int FpuCw;
+ unsigned int DummyCw = 0;
+
+ /* get the controlword */
+ asm volatile("fstcw %0\n\t" : "=m"(FpuCw));
+ FpuCw &= 0x0000ffff;
+
+ /* translate it into _control87 format */
+ if (FpuCw & X87_CW_IM)
+ DummyCw |= _EM_INVALID;
+ if (FpuCw & X87_CW_DM)
+ DummyCw |= _EM_DENORMAL;
+ if (FpuCw & X87_CW_ZM)
+ DummyCw |= _EM_ZERODIVIDE;
+ if (FpuCw & X87_CW_OM)
+ DummyCw |= _EM_OVERFLOW;
+ if (FpuCw & X87_CW_UM)
+ DummyCw |= _EM_UNDERFLOW;
+ if (FpuCw & X87_CW_PM)
+ DummyCw |= _EM_INEXACT;
+
+ switch (FpuCw & X87_CW_PC_MASK)
+ {
+ case X87_CW_PC24:
+ DummyCw |= _PC_24;
+ break;
+ case X87_CW_PC53:
+ DummyCw |= _PC_53;
+ break;
+ case X87_CW_PC64:
+ DummyCw |= _PC_64;
+ break;
+ }
+
+ switch (FpuCw & X87_CW_RC_MASK)
+ {
+ case X87_CW_RC_NEAREST:
+ DummyCw |= _RC_NEAR;
+ break;
+ case X87_CW_RC_DOWN:
+ DummyCw |= _RC_DOWN;
+ break;
+ case X87_CW_RC_UP:
+ DummyCw |= _RC_UP;
+ break;
+ case X87_CW_RC_ZERO:
+ DummyCw |= _RC_CHOP;
+ break;
+ }
+
+ /* unset (un)masked bits */
+ DummyCw &= ~unMask;
+ unNew &= unMask;
+
+ /* set new bits */
+ DummyCw |= unNew;
+
+ /* translate back into x87 format
+ * FIXME: translate infinity control!
+ */
+ FpuCw = 0;
+ if (DummyCw & _EM_INVALID)
+ FpuCw |= X87_CW_IM;
+ if (DummyCw & _EM_DENORMAL)
+ FpuCw |= X87_CW_DM;
+ if (DummyCw & _EM_ZERODIVIDE)
+ FpuCw |= X87_CW_ZM;
+ if (DummyCw & _EM_OVERFLOW)
+ FpuCw |= X87_CW_OM;
+ if (DummyCw & _EM_UNDERFLOW)
+ FpuCw |= X87_CW_UM;
+ if (DummyCw & _EM_INEXACT)
+ FpuCw |= X87_CW_PM;
+
+ switch (DummyCw & _MCW_PC)
+ {
+ case _PC_24:
+ FpuCw |= X87_CW_PC24;
+ break;
+ case _PC_53:
+ FpuCw |= X87_CW_PC53;
+ break;
+ case _PC_64:
+ default:
+ FpuCw |= X87_CW_PC64;
+ break;
+ }
+
+ switch (DummyCw & _MCW_RC)
+ {
+ case _RC_NEAR:
+ FpuCw |= X87_CW_RC_NEAREST;
+ break;
+ case _RC_DOWN:
+ FpuCw |= X87_CW_RC_DOWN;
+ break;
+ case _RC_UP:
+ FpuCw |= X87_CW_RC_UP;
+ break;
+ case _RC_CHOP:
+ FpuCw |= X87_CW_RC_ZERO;
+ break;
+ }
+
+ /* set controlword */
+ asm volatile("fldcw %0" : : "m"(FpuCw));
+
+ return DummyCw;
+
+#if 0 /* The follwing is the original code, broken I think! -blight */
register unsigned int __res;
#ifdef __GNUC__
__asm__ __volatile__ (
"fldcw (%%esp) \n\t"
"popl %%edx \n\t"
- :"=r" (__res):"r" (unNew),"r" (unMask): "ax", "dx", "cx");
+ :"=a" (__res):"r" (unNew),"r" (unMask): "dx", "cx");
#else
#endif /*__GNUC__*/
return __res;
+#endif
}