wined3d: Remove IWineD3DSurface::GetImplType() from the public interface.
[wine] / dlls / msvcrt / math.c
index f734b9e..3428398 100644 (file)
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 #include "config.h"
-#include "msvcrt.h"
-#include "ms_errno.h"
 
+#include <stdio.h>
 #define __USE_ISOC9X 1
 #define __USE_ISOC99 1
 #include <math.h>
@@ -28,7 +27,7 @@
 #include <ieeefp.h>
 #endif
 
-#include "msvcrt/stdlib.h"
+#include "msvcrt.h"
 
 #include "wine/debug.h"
 
@@ -48,72 +47,378 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 #define signbit(x) 0
 #endif
 
-/* fpclass constants */
-#define _FPCLASS_SNAN 1
-#define _FPCLASS_QNAN 2
-#define _FPCLASS_NINF 4
-#define _FPCLASS_NN   8
-#define _FPCLASS_ND   16
-#define _FPCLASS_NZ   32
-#define _FPCLASS_PZ   64
-#define _FPCLASS_PD   128
-#define _FPCLASS_PN   256
-#define _FPCLASS_PINF 512
-
-/* _statusfp bit flags */
-#define _SW_INEXACT    0x1
-#define _SW_UNDERFLOW  0x2
-#define _SW_OVERFLOW   0x4
-#define _SW_ZERODIVIDE 0x8
-#define _SW_INVALID    0x10
-#define _SW_DENORMAL   0x80000
-
-/* _controlfp masks and bitflags - x86 only so far*/
-#ifdef __i386__
-#define _MCW_EM        0x8001f
-#define _EM_INEXACT    0x1
-#define _EM_UNDERFLOW  0x2
-#define _EM_OVERFLOW   0x4
-#define _EM_ZERODIVIDE 0x8
-#define _EM_INVALID    0x10
-
-#define _MCW_RC        0x300
-#define _RC_NEAR       0x0
-#define _RC_DOWN       0x100
-#define _RC_UP         0x200
-#define _RC_CHOP       0x300
-
-#define _MCW_PC        0x30000
-#define _PC_64         0x0
-#define _PC_53         0x10000
-#define _PC_24         0x20000
-
-#define _MCW_IC        0x40000
-#define _IC_AFFINE     0x40000
-#define _IC_PROJECTIVE 0x0
-
-#define _EM_DENORMAL   0x80000
+typedef int (CDECL *MSVCRT_matherr_func)(struct MSVCRT__exception *);
+
+static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
+
+static BOOL sse2_supported;
+static BOOL sse2_enabled;
+
+void msvcrt_init_math(void)
+{
+    sse2_supported = sse2_enabled = IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE );
+}
+
+/*********************************************************************
+ *      _set_SSE2_enable (MSVCRT.@)
+ */
+int CDECL MSVCRT__set_SSE2_enable(int flag)
+{
+    sse2_enabled = flag && sse2_supported;
+    return sse2_enabled;
+}
+
+#ifdef __x86_64__
+
+/*********************************************************************
+ *      MSVCRT_acosf (MSVCRT.@)
+ */
+float CDECL MSVCRT_acosf( float x )
+{
+  if (x < -1.0 || x > 1.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  /* glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x).
+   * asin() uses a similar construction. This is bad because as x gets nearer to
+   * 1 the error in the expression "1 - x^2" can get relatively large due to
+   * cancellation. The sqrt() makes things worse. A safer way to calculate
+   * acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
+  return atan2f(sqrtf((1 - x) * (1 + x)), x);
+}
+
+/*********************************************************************
+ *      MSVCRT_asinf (MSVCRT.@)
+ */
+float CDECL MSVCRT_asinf( float x )
+{
+  if (x < -1.0 || x > 1.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return atan2f(x, sqrtf((1 - x) * (1 + x)));
+}
+
+/*********************************************************************
+ *      MSVCRT_atanf (MSVCRT.@)
+ */
+float CDECL MSVCRT_atanf( float x )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return atanf(x);
+}
+
+/*********************************************************************
+ *              MSVCRT_atan2f (MSVCRT.@)
+ */
+float CDECL MSVCRT_atan2f( float x, float y )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return atan2f(x,y);
+}
+
+/*********************************************************************
+ *      MSVCRT_cosf (MSVCRT.@)
+ */
+float CDECL MSVCRT_cosf( float x )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return cosf(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_coshf (MSVCRT.@)
+ */
+float CDECL MSVCRT_coshf( float x )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return coshf(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_expf (MSVCRT.@)
+ */
+float CDECL MSVCRT_expf( float x )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return expf(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_fmodf (MSVCRT.@)
+ */
+float CDECL MSVCRT_fmodf( float x, float y )
+{
+  if (!finitef(x) || !finitef(y)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return fmodf(x,y);
+}
+
+/*********************************************************************
+ *      MSVCRT_logf (MSVCRT.@)
+ */
+float CDECL MSVCRT_logf( float x)
+{
+  if (x < 0.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
+  return logf(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_log10f (MSVCRT.@)
+ */
+float CDECL MSVCRT_log10f( float x )
+{
+  if (x < 0.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
+  return log10f(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_powf (MSVCRT.@)
+ */
+float CDECL MSVCRT_powf( float x, float y )
+{
+  /* FIXME: If x < 0 and y is not integral, set EDOM */
+  float z = powf(x,y);
+  if (!finitef(z)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return z;
+}
+
+/*********************************************************************
+ *      MSVCRT_sinf (MSVCRT.@)
+ */
+float CDECL MSVCRT_sinf( float x )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return sinf(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_sinhf (MSVCRT.@)
+ */
+float CDECL MSVCRT_sinhf( float x )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return sinhf(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_sqrtf (MSVCRT.@)
+ */
+float CDECL MSVCRT_sqrtf( float x )
+{
+  if (x < 0.0 || !finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return sqrtf(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_tanf (MSVCRT.@)
+ */
+float CDECL MSVCRT_tanf( float x )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return tanf(x);
+}
+
+/*********************************************************************
+ *      MSVCRT_tanhf (MSVCRT.@)
+ */
+float CDECL MSVCRT_tanhf( float x )
+{
+  if (!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return tanhf(x);
+}
+
+/*********************************************************************
+ *      ceilf (MSVCRT.@)
+ */
+float CDECL MSVCRT_ceilf( float x )
+{
+  return ceilf(x);
+}
+
+/*********************************************************************
+ *      floorf (MSVCRT.@)
+ */
+float CDECL MSVCRT_floorf( float x )
+{
+  return floorf(x);
+}
+
+/*********************************************************************
+ *      frexpf (MSVCRT.@)
+ */
+float CDECL MSVCRT_frexpf( float x, int *exp )
+{
+  return frexpf( x, exp );
+}
+
+/*********************************************************************
+ *      _scalbf (MSVCRT.@)
+ */
+float CDECL MSVCRT__scalbf(float num, MSVCRT_long power)
+{
+  if (!finitef(num)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return ldexpf(num, power);
+}
+
+/*********************************************************************
+ *      modff (MSVCRT.@)
+ */
+double CDECL MSVCRT_modff( float x, float *iptr )
+{
+  return modff( x, iptr );
+}
+
 #endif
 
-typedef struct __MSVCRT_complex
+/*********************************************************************
+ *             MSVCRT_acos (MSVCRT.@)
+ */
+double CDECL MSVCRT_acos( double x )
 {
-  double real;
-  double imaginary;
-} MSVCRT_complex;
+  if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  /* glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x).
+   * asin() uses a similar construction. This is bad because as x gets nearer to
+   * 1 the error in the expression "1 - x^2" can get relatively large due to
+   * cancellation. The sqrt() makes things worse. A safer way to calculate
+   * acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
+  return atan2(sqrt((1 - x) * (1 + x)), x);
+}
 
-typedef struct __MSVCRT_exception
+/*********************************************************************
+ *             MSVCRT_asin (MSVCRT.@)
+ */
+double CDECL MSVCRT_asin( double x )
 {
-  int type;
-  char *name;
-  double arg1;
-  double arg2;
-  double retval;
-} MSVCRT_exception;
+  if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return atan2(x, sqrt((1 - x) * (1 + x)));
+}
+
+/*********************************************************************
+ *             MSVCRT_atan (MSVCRT.@)
+ */
+double CDECL MSVCRT_atan( double x )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return atan(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_atan2 (MSVCRT.@)
+ */
+double CDECL MSVCRT_atan2( double x, double y )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return atan2(x,y);
+}
 
+/*********************************************************************
+ *             MSVCRT_cos (MSVCRT.@)
+ */
+double CDECL MSVCRT_cos( double x )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return cos(x);
+}
 
-typedef int (*MSVCRT_matherr_func)(MSVCRT_exception *);
+/*********************************************************************
+ *             MSVCRT_cosh (MSVCRT.@)
+ */
+double CDECL MSVCRT_cosh( double x )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return cosh(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_exp (MSVCRT.@)
+ */
+double CDECL MSVCRT_exp( double x )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return exp(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_fmod (MSVCRT.@)
+ */
+double CDECL MSVCRT_fmod( double x, double y )
+{
+  if (!finite(x) || !finite(y)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return fmod(x,y);
+}
+
+/*********************************************************************
+ *             MSVCRT_log (MSVCRT.@)
+ */
+double CDECL MSVCRT_log( double x)
+{
+  if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
+  return log(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_log10 (MSVCRT.@)
+ */
+double CDECL MSVCRT_log10( double x )
+{
+  if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
+  return log10(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_pow (MSVCRT.@)
+ */
+double CDECL MSVCRT_pow( double x, double y )
+{
+  /* FIXME: If x < 0 and y is not integral, set EDOM */
+  double z = pow(x,y);
+  if (!finite(z)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return z;
+}
+
+/*********************************************************************
+ *             MSVCRT_sin (MSVCRT.@)
+ */
+double CDECL MSVCRT_sin( double x )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return sin(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_sinh (MSVCRT.@)
+ */
+double CDECL MSVCRT_sinh( double x )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return sinh(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_sqrt (MSVCRT.@)
+ */
+double CDECL MSVCRT_sqrt( double x )
+{
+  if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return sqrt(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_tan (MSVCRT.@)
+ */
+double CDECL MSVCRT_tan( double x )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return tan(x);
+}
+
+/*********************************************************************
+ *             MSVCRT_tanh (MSVCRT.@)
+ */
+double CDECL MSVCRT_tanh( double x )
+{
+  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return tanh(x);
+}
 
-static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
 
 #if defined(__GNUC__) && defined(__i386__)
 
@@ -126,289 +431,321 @@ static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
 /*********************************************************************
  *             _CIacos (MSVCRT.@)
  */
-double _CIacos(void)
+double CDECL _CIacos(void)
 {
   FPU_DOUBLE(x);
-  if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return acos(x);
+  return MSVCRT_acos(x);
 }
 
 /*********************************************************************
  *             _CIasin (MSVCRT.@)
  */
-double _CIasin(void)
+double CDECL _CIasin(void)
 {
   FPU_DOUBLE(x);
-  if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return asin(x);
+  return MSVCRT_asin(x);
 }
 
 /*********************************************************************
  *             _CIatan (MSVCRT.@)
  */
-double _CIatan(void)
+double CDECL _CIatan(void)
 {
   FPU_DOUBLE(x);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return atan(x);
+  return MSVCRT_atan(x);
 }
 
 /*********************************************************************
  *             _CIatan2 (MSVCRT.@)
  */
-double _CIatan2(void)
+double CDECL _CIatan2(void)
 {
   FPU_DOUBLES(x,y);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return atan2(x,y);
+  return MSVCRT_atan2(x,y);
 }
 
 /*********************************************************************
  *             _CIcos (MSVCRT.@)
  */
-double _CIcos(void)
+double CDECL _CIcos(void)
 {
   FPU_DOUBLE(x);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return cos(x);
+  return MSVCRT_cos(x);
 }
 
 /*********************************************************************
  *             _CIcosh (MSVCRT.@)
  */
-double _CIcosh(void)
+double CDECL _CIcosh(void)
 {
   FPU_DOUBLE(x);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return cosh(x);
+  return MSVCRT_cosh(x);
 }
 
 /*********************************************************************
  *             _CIexp (MSVCRT.@)
  */
-double _CIexp(void)
+double CDECL _CIexp(void)
 {
   FPU_DOUBLE(x);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return exp(x);
+  return MSVCRT_exp(x);
 }
 
 /*********************************************************************
  *             _CIfmod (MSVCRT.@)
  */
-double _CIfmod(void)
+double CDECL _CIfmod(void)
 {
   FPU_DOUBLES(x,y);
-  if (!finite(x) || !finite(y)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return fmod(x,y);
+  return MSVCRT_fmod(x,y);
 }
 
 /*********************************************************************
  *             _CIlog (MSVCRT.@)
  */
-double _CIlog(void)
+double CDECL _CIlog(void)
 {
   FPU_DOUBLE(x);
-  if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
-  return log(x);
+  return MSVCRT_log(x);
 }
 
 /*********************************************************************
  *             _CIlog10 (MSVCRT.@)
  */
-double _CIlog10(void)
+double CDECL _CIlog10(void)
 {
   FPU_DOUBLE(x);
-  if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
-  return log10(x);
+  return MSVCRT_log10(x);
 }
 
 /*********************************************************************
  *             _CIpow (MSVCRT.@)
  */
-double _CIpow(void)
+double CDECL _CIpow(void)
 {
-  double z;
   FPU_DOUBLES(x,y);
-  /* FIXME: If x < 0 and y is not integral, set EDOM */
-  z = pow(x,y);
-  if (!finite(z)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return z;
+  return MSVCRT_pow(x,y);
 }
 
 /*********************************************************************
  *             _CIsin (MSVCRT.@)
  */
-double _CIsin(void)
+double CDECL _CIsin(void)
 {
   FPU_DOUBLE(x);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return sin(x);
+  return MSVCRT_sin(x);
 }
 
 /*********************************************************************
  *             _CIsinh (MSVCRT.@)
  */
-double _CIsinh(void)
+double CDECL _CIsinh(void)
 {
   FPU_DOUBLE(x);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return sinh(x);
+  return MSVCRT_sinh(x);
 }
 
 /*********************************************************************
  *             _CIsqrt (MSVCRT.@)
  */
-double _CIsqrt(void)
+double CDECL _CIsqrt(void)
 {
   FPU_DOUBLE(x);
-  if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return sqrt(x);
+  return MSVCRT_sqrt(x);
 }
 
 /*********************************************************************
  *             _CItan (MSVCRT.@)
  */
-double _CItan(void)
+double CDECL _CItan(void)
 {
   FPU_DOUBLE(x);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return tan(x);
+  return MSVCRT_tan(x);
 }
 
 /*********************************************************************
  *             _CItanh (MSVCRT.@)
  */
-double _CItanh(void)
+double CDECL _CItanh(void)
 {
   FPU_DOUBLE(x);
-  if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return tanh(x);
+  return MSVCRT_tanh(x);
 }
 
-#else /* defined(__GNUC__) && defined(__i386__) */
-
-/* The above cannot be called on non x86 platforms, stub them for linking */
-
-#define IX86_ONLY(func) double func(void) { return 0.0; }
-
-IX86_ONLY(_CIacos)
-IX86_ONLY(_CIasin)
-IX86_ONLY(_CIatan)
-IX86_ONLY(_CIatan2)
-IX86_ONLY(_CIcos)
-IX86_ONLY(_CIcosh)
-IX86_ONLY(_CIexp)
-IX86_ONLY(_CIfmod)
-IX86_ONLY(_CIlog)
-IX86_ONLY(_CIlog10)
-IX86_ONLY(_CIpow)
-IX86_ONLY(_CIsin)
-IX86_ONLY(_CIsinh)
-IX86_ONLY(_CIsqrt)
-IX86_ONLY(_CItan)
-IX86_ONLY(_CItanh)
-
 #endif /* defined(__GNUC__) && defined(__i386__) */
 
 /*********************************************************************
  *             _fpclass (MSVCRT.@)
  */
-int _fpclass(double num)
+int CDECL _fpclass(double num)
 {
 #if defined(HAVE_FPCLASS) || defined(fpclass)
   switch (fpclass( num ))
   {
-  case FP_SNAN:  return _FPCLASS_SNAN;
-  case FP_QNAN:  return _FPCLASS_QNAN;
-  case FP_NINF:  return _FPCLASS_NINF;
-  case FP_PINF:  return _FPCLASS_PINF;
-  case FP_NDENORM: return _FPCLASS_ND;
-  case FP_PDENORM: return _FPCLASS_PD;
-  case FP_NZERO: return _FPCLASS_NZ;
-  case FP_PZERO: return _FPCLASS_PZ;
-  case FP_NNORM: return _FPCLASS_NN;
-  case FP_PNORM: return _FPCLASS_PN;
+#ifdef FP_SNAN
+  case FP_SNAN:  return MSVCRT__FPCLASS_SNAN;
+#endif
+#ifdef FP_QNAN
+  case FP_QNAN:  return MSVCRT__FPCLASS_QNAN;
+#endif
+#ifdef FP_NINF
+  case FP_NINF:  return MSVCRT__FPCLASS_NINF;
+#endif
+#ifdef FP_PINF
+  case FP_PINF:  return MSVCRT__FPCLASS_PINF;
+#endif
+#ifdef FP_NDENORM
+  case FP_NDENORM: return MSVCRT__FPCLASS_ND;
+#endif
+#ifdef FP_PDENORM
+  case FP_PDENORM: return MSVCRT__FPCLASS_PD;
+#endif
+#ifdef FP_NZERO
+  case FP_NZERO: return MSVCRT__FPCLASS_NZ;
+#endif
+#ifdef FP_PZERO
+  case FP_PZERO: return MSVCRT__FPCLASS_PZ;
+#endif
+#ifdef FP_NNORM
+  case FP_NNORM: return MSVCRT__FPCLASS_NN;
+#endif
+#ifdef FP_PNORM
+  case FP_PNORM: return MSVCRT__FPCLASS_PN;
+#endif
+  default: return MSVCRT__FPCLASS_PN;
   }
-  return _FPCLASS_PN;
 #elif defined (fpclassify)
   switch (fpclassify( num ))
   {
-  case FP_NAN: return _FPCLASS_QNAN;
-  case FP_INFINITE: return signbit(num) ? _FPCLASS_NINF : _FPCLASS_PINF;
-  case FP_SUBNORMAL: return signbit(num) ?_FPCLASS_ND : _FPCLASS_PD;
-  case FP_ZERO: return signbit(num) ? _FPCLASS_NZ : _FPCLASS_PZ;
+  case FP_NAN: return MSVCRT__FPCLASS_QNAN;
+  case FP_INFINITE: return signbit(num) ? MSVCRT__FPCLASS_NINF : MSVCRT__FPCLASS_PINF;
+  case FP_SUBNORMAL: return signbit(num) ?MSVCRT__FPCLASS_ND : MSVCRT__FPCLASS_PD;
+  case FP_ZERO: return signbit(num) ? MSVCRT__FPCLASS_NZ : MSVCRT__FPCLASS_PZ;
   }
-  return signbit(num) ? _FPCLASS_NN : _FPCLASS_PN;
+  return signbit(num) ? MSVCRT__FPCLASS_NN : MSVCRT__FPCLASS_PN;
 #else
   if (!finite(num))
-    return _FPCLASS_QNAN;
-  return num == 0.0 ? _FPCLASS_PZ : (num < 0 ? _FPCLASS_NN : _FPCLASS_PN);
+    return MSVCRT__FPCLASS_QNAN;
+  return num == 0.0 ? MSVCRT__FPCLASS_PZ : (num < 0 ? MSVCRT__FPCLASS_NN : MSVCRT__FPCLASS_PN);
 #endif
 }
 
 /*********************************************************************
- *             _rotl (MSVCRT.@)
+ *             _rotl (MSVCRT.@)
+ */
+unsigned int CDECL _rotl(unsigned int num, int shift)
+{
+  shift &= 31;
+  return (num << shift) | (num >> (32-shift));
+}
+
+/*********************************************************************
+ *             _logb (MSVCRT.@)
+ */
+double CDECL _logb(double num)
+{
+  if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return logb(num);
+}
+
+/*********************************************************************
+ *             _lrotl (MSVCRT.@)
+ */
+MSVCRT_ulong CDECL MSVCRT__lrotl(MSVCRT_ulong num, int shift)
+{
+  shift &= 0x1f;
+  return (num << shift) | (num >> (32-shift));
+}
+
+/*********************************************************************
+ *             _lrotr (MSVCRT.@)
+ */
+MSVCRT_ulong CDECL MSVCRT__lrotr(MSVCRT_ulong num, int shift)
+{
+  shift &= 0x1f;
+  return (num >> shift) | (num << (32-shift));
+}
+
+/*********************************************************************
+ *             _rotr (MSVCRT.@)
+ */
+unsigned int CDECL _rotr(unsigned int num, int shift)
+{
+    shift &= 0x1f;
+    return (num >> shift) | (num << (32-shift));
+}
+
+/*********************************************************************
+ *             _scalb (MSVCRT.@)
+ */
+double CDECL MSVCRT__scalb(double num, MSVCRT_long power)
+{
+  if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
+  return ldexp(num, power);
+}
+
+/*********************************************************************
+ *             _hypot (MSVCRT.@)
  */
-unsigned int _rotl(unsigned int num, int shift)
+double CDECL _hypot(double x, double y)
 {
-  shift &= 31;
-  return (num << shift) | (num >> (32-shift));
+  /* FIXME: errno handling */
+  return hypot( x, y );
 }
 
 /*********************************************************************
- *             _logb (MSVCRT.@)
+ *      _hypotf (MSVCRT.@)
  */
-double _logb(double num)
+float CDECL _hypotf(float x, float y)
 {
-  if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return logb(num);
+  /* FIXME: errno handling */
+  return hypotf( x, y );
 }
 
 /*********************************************************************
- *             _lrotl (MSVCRT.@)
+ *             ceil (MSVCRT.@)
  */
-unsigned long _lrotl(unsigned long num, int shift)
+double CDECL MSVCRT_ceil( double x )
 {
-  shift &= 0x1f;
-  return (num << shift) | (num >> (32-shift));
+  return ceil(x);
 }
 
 /*********************************************************************
- *             _lrotr (MSVCRT.@)
+ *             floor (MSVCRT.@)
  */
-unsigned long _lrotr(unsigned long num, int shift)
+double CDECL MSVCRT_floor( double x )
 {
-  shift &= 0x1f;
-  return (num >> shift) | (num << (32-shift));
+  return floor(x);
 }
 
 /*********************************************************************
- *             _rotr (MSVCRT.@)
+ *             fabs (MSVCRT.@)
  */
-unsigned int _rotr(unsigned int num, int shift)
+double CDECL MSVCRT_fabs( double x )
 {
-    shift &= 0x1f;
-    return (num >> shift) | (num << (32-shift));
+  return fabs(x);
 }
 
 /*********************************************************************
- *             _scalb (MSVCRT.@)
+ *             frexp (MSVCRT.@)
  */
-double _scalb(double num, long power)
+double CDECL MSVCRT_frexp( double x, int *exp )
 {
-  /* Note - Can't forward directly as libc expects y as double */
-  double dblpower = (double)power;
-  if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
-  return scalb(num, dblpower);
+  return frexp( x, exp );
+}
+
+/*********************************************************************
+ *             modf (MSVCRT.@)
+ */
+double CDECL MSVCRT_modf( double x, double *iptr )
+{
+  return modf( x, iptr );
 }
 
 /*********************************************************************
  *             _matherr (MSVCRT.@)
  */
-int _matherr(MSVCRT_exception *e)
+int CDECL MSVCRT__matherr(struct MSVCRT__exception *e)
 {
   if (e)
     TRACE("(%p = %d, %s, %g %g %g)\n",e, e->type, e->name, e->arg1, e->arg2,
@@ -424,52 +761,122 @@ int _matherr(MSVCRT_exception *e)
 /*********************************************************************
  *             __setusermatherr (MSVCRT.@)
  */
-void MSVCRT___setusermatherr(MSVCRT_matherr_func func)
+void CDECL MSVCRT___setusermatherr(MSVCRT_matherr_func func)
 {
   MSVCRT_default_matherr_func = func;
   TRACE(":new matherr handler %p\n", func);
 }
 
+/**********************************************************************
+ *             _statusfp2 (MSVCRT.@)
+ *
+ * Not exported by native msvcrt, added in msvcr80.
+ */
+#if defined(__i386__) || defined(__x86_64__)
+void CDECL _statusfp2( unsigned int *x86_sw, unsigned int *sse2_sw )
+{
+#ifdef __GNUC__
+    unsigned int flags;
+    unsigned long fpword;
+
+    if (x86_sw)
+    {
+        __asm__ __volatile__( "fstsw %0" : "=m" (fpword) );
+        flags = 0;
+        if (fpword & 0x1)  flags |= MSVCRT__SW_INVALID;
+        if (fpword & 0x2)  flags |= MSVCRT__SW_DENORMAL;
+        if (fpword & 0x4)  flags |= MSVCRT__SW_ZERODIVIDE;
+        if (fpword & 0x8)  flags |= MSVCRT__SW_OVERFLOW;
+        if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
+        if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
+        *x86_sw = flags;
+    }
+
+    if (!sse2_sw) return;
+
+    if (sse2_supported)
+    {
+        __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
+        flags = 0;
+        if (fpword & 0x1)  flags |= MSVCRT__SW_INVALID;
+        if (fpword & 0x2)  flags |= MSVCRT__SW_DENORMAL;
+        if (fpword & 0x4)  flags |= MSVCRT__SW_ZERODIVIDE;
+        if (fpword & 0x8)  flags |= MSVCRT__SW_OVERFLOW;
+        if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
+        if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
+        *sse2_sw = flags;
+    }
+    else *sse2_sw = 0;
+#else
+    FIXME( "not implemented\n" );
+#endif
+}
+#endif
+
 /**********************************************************************
  *             _statusfp (MSVCRT.@)
  */
-unsigned int _statusfp(void)
+unsigned int CDECL _statusfp(void)
 {
-   unsigned int retVal = 0;
-#if defined(__GNUC__) && defined(__i386__)
-  unsigned int fpword;
-
-  __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
-  if (fpword & 0x1)  retVal |= _SW_INVALID;
-  if (fpword & 0x2)  retVal |= _SW_DENORMAL;
-  if (fpword & 0x4)  retVal |= _SW_ZERODIVIDE;
-  if (fpword & 0x8)  retVal |= _SW_OVERFLOW;
-  if (fpword & 0x10) retVal |= _SW_UNDERFLOW;
-  if (fpword & 0x20) retVal |= _SW_INEXACT;
+#if defined(__i386__) || defined(__x86_64__)
+    unsigned int x86_sw, sse2_sw;
+
+    _statusfp2( &x86_sw, &sse2_sw );
+    /* FIXME: there's no definition for ambiguous status, just return all status bits for now */
+    return x86_sw | sse2_sw;
 #else
-  FIXME(":Not implemented!\n");
+    FIXME( "not implemented\n" );
+    return 0;
 #endif
-  return retVal;
 }
 
 /*********************************************************************
  *             _clearfp (MSVCRT.@)
  */
-unsigned int _clearfp(void)
-{
-  unsigned int retVal = _statusfp();
-#if defined(__GNUC__) && defined(__i386__)
-  __asm__ __volatile__( "fnclex" );
+unsigned int CDECL _clearfp(void)
+{
+    unsigned int flags = 0;
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+    unsigned long fpword;
+
+    __asm__ __volatile__( "fnstsw %0; fnclex" : "=m" (fpword) );
+    if (fpword & 0x1)  flags |= MSVCRT__SW_INVALID;
+    if (fpword & 0x2)  flags |= MSVCRT__SW_DENORMAL;
+    if (fpword & 0x4)  flags |= MSVCRT__SW_ZERODIVIDE;
+    if (fpword & 0x8)  flags |= MSVCRT__SW_OVERFLOW;
+    if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
+    if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
+
+    if (sse2_supported)
+    {
+        __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
+        if (fpword & 0x1)  flags |= MSVCRT__SW_INVALID;
+        if (fpword & 0x2)  flags |= MSVCRT__SW_DENORMAL;
+        if (fpword & 0x4)  flags |= MSVCRT__SW_ZERODIVIDE;
+        if (fpword & 0x8)  flags |= MSVCRT__SW_OVERFLOW;
+        if (fpword & 0x10) flags |= MSVCRT__SW_UNDERFLOW;
+        if (fpword & 0x20) flags |= MSVCRT__SW_INEXACT;
+        fpword &= ~0x3f;
+        __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
+    }
 #else
-  FIXME(":Not Implemented\n");
+    FIXME( "not implemented\n" );
 #endif
-  return retVal;
+    return flags;
+}
+
+/*********************************************************************
+ *             __fpecode (MSVCRT.@)
+ */
+int * CDECL __fpecode(void)
+{
+    return &msvcrt_get_thread_data()->fpecode;
 }
 
 /*********************************************************************
  *             ldexp (MSVCRT.@)
  */
-double MSVCRT_ldexp(double num, long exp)
+double CDECL MSVCRT_ldexp(double num, MSVCRT_long exp)
 {
   double z = ldexp(num,exp);
 
@@ -483,107 +890,215 @@ double MSVCRT_ldexp(double num, long exp)
 /*********************************************************************
  *             _cabs (MSVCRT.@)
  */
-double _cabs(MSVCRT_complex num)
+double CDECL MSVCRT__cabs(struct MSVCRT__complex num)
 {
-  return sqrt(num.real * num.real + num.imaginary * num.imaginary);
+  return sqrt(num.x * num.x + num.y * num.y);
 }
 
 /*********************************************************************
  *             _chgsign (MSVCRT.@)
  */
-double _chgsign(double num)
+double CDECL _chgsign(double num)
 {
   /* FIXME: +-infinity,Nan not tested */
   return -num;
 }
 
+/*********************************************************************
+ *             __control87_2 (MSVCRT.@)
+ *
+ * Not exported by native msvcrt, added in msvcr80.
+ */
+#if defined(__i386__) || defined(__x86_64__)
+int CDECL __control87_2( unsigned int newval, unsigned int mask,
+                         unsigned int *x86_cw, unsigned int *sse2_cw )
+{
+#ifdef __GNUC__
+    unsigned long fpword;
+    unsigned int flags;
+
+    if (x86_cw)
+    {
+        __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
+
+        /* Convert into mask constants */
+        flags = 0;
+        if (fpword & 0x1)  flags |= MSVCRT__EM_INVALID;
+        if (fpword & 0x2)  flags |= MSVCRT__EM_DENORMAL;
+        if (fpword & 0x4)  flags |= MSVCRT__EM_ZERODIVIDE;
+        if (fpword & 0x8)  flags |= MSVCRT__EM_OVERFLOW;
+        if (fpword & 0x10) flags |= MSVCRT__EM_UNDERFLOW;
+        if (fpword & 0x20) flags |= MSVCRT__EM_INEXACT;
+        switch (fpword & 0xc00)
+        {
+        case 0xc00: flags |= MSVCRT__RC_UP|MSVCRT__RC_DOWN; break;
+        case 0x800: flags |= MSVCRT__RC_UP; break;
+        case 0x400: flags |= MSVCRT__RC_DOWN; break;
+        }
+        switch (fpword & 0x300)
+        {
+        case 0x0:   flags |= MSVCRT__PC_24; break;
+        case 0x200: flags |= MSVCRT__PC_53; break;
+        case 0x300: flags |= MSVCRT__PC_64; break;
+        }
+        if (fpword & 0x1000) flags |= MSVCRT__IC_AFFINE;
+
+        TRACE( "x86 flags=%08x newval=%08x mask=%08x\n", flags, newval, mask );
+        if (mask)
+        {
+            flags = (flags & ~mask) | (newval & mask);
+
+            /* Convert (masked) value back to fp word */
+            fpword = 0;
+            if (flags & MSVCRT__EM_INVALID)    fpword |= 0x1;
+            if (flags & MSVCRT__EM_DENORMAL)   fpword |= 0x2;
+            if (flags & MSVCRT__EM_ZERODIVIDE) fpword |= 0x4;
+            if (flags & MSVCRT__EM_OVERFLOW)   fpword |= 0x8;
+            if (flags & MSVCRT__EM_UNDERFLOW)  fpword |= 0x10;
+            if (flags & MSVCRT__EM_INEXACT)    fpword |= 0x20;
+            switch (flags & MSVCRT__MCW_RC)
+            {
+            case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fpword |= 0xc00; break;
+            case MSVCRT__RC_UP:                 fpword |= 0x800; break;
+            case MSVCRT__RC_DOWN:               fpword |= 0x400; break;
+            }
+            switch (flags & MSVCRT__MCW_PC)
+            {
+            case MSVCRT__PC_64: fpword |= 0x300; break;
+            case MSVCRT__PC_53: fpword |= 0x200; break;
+            case MSVCRT__PC_24: fpword |= 0x0; break;
+            }
+            if (flags & MSVCRT__IC_AFFINE) fpword |= 0x1000;
+
+            __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
+        }
+        *x86_cw = flags;
+    }
+
+    if (!sse2_cw) return 1;
+
+    if (sse2_supported)
+    {
+        __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
+
+        /* Convert into mask constants */
+        flags = 0;
+        if (fpword & 0x80)   flags |= MSVCRT__EM_INVALID;
+        if (fpword & 0x100)  flags |= MSVCRT__EM_DENORMAL;
+        if (fpword & 0x200)  flags |= MSVCRT__EM_ZERODIVIDE;
+        if (fpword & 0x400)  flags |= MSVCRT__EM_OVERFLOW;
+        if (fpword & 0x800)  flags |= MSVCRT__EM_UNDERFLOW;
+        if (fpword & 0x1000) flags |= MSVCRT__EM_INEXACT;
+        switch (fpword & 0x6000)
+        {
+        case 0x6000: flags |= MSVCRT__RC_UP|MSVCRT__RC_DOWN; break;
+        case 0x4000: flags |= MSVCRT__RC_UP; break;
+        case 0x2000: flags |= MSVCRT__RC_DOWN; break;
+        }
+        switch (fpword & 0x8040)
+        {
+        case 0x0040: flags |= MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS; break;
+        case 0x8000: flags |= MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS; break;
+        case 0x8040: flags |= MSVCRT__DN_FLUSH; break;
+        }
+
+        TRACE( "sse2 flags=%08x newval=%08x mask=%08x\n", flags, newval, mask );
+        if (mask)
+        {
+            flags = (flags & ~mask) | (newval & mask);
+
+            /* Convert (masked) value back to fp word */
+            fpword = 0;
+            if (flags & MSVCRT__EM_INVALID)    fpword |= 0x80;
+            if (flags & MSVCRT__EM_DENORMAL)   fpword |= 0x100;
+            if (flags & MSVCRT__EM_ZERODIVIDE) fpword |= 0x200;
+            if (flags & MSVCRT__EM_OVERFLOW)   fpword |= 0x400;
+            if (flags & MSVCRT__EM_UNDERFLOW)  fpword |= 0x800;
+            if (flags & MSVCRT__EM_INEXACT)    fpword |= 0x1000;
+            switch (flags & MSVCRT__MCW_RC)
+            {
+            case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fpword |= 0x6000; break;
+            case MSVCRT__RC_UP:                 fpword |= 0x4000; break;
+            case MSVCRT__RC_DOWN:               fpword |= 0x2000; break;
+            }
+            switch (flags & MSVCRT__MCW_DN)
+            {
+            case MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS: fpword |= 0x0040; break;
+            case MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS: fpword |= 0x8000; break;
+            case MSVCRT__DN_FLUSH:                       fpword |= 0x8040; break;
+            }
+            __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
+        }
+        *sse2_cw = flags;
+    }
+    else *sse2_cw = 0;
+
+    return 1;
+#else
+    FIXME( "not implemented\n" );
+    return 0;
+#endif
+}
+#endif
+
 /*********************************************************************
  *             _control87 (MSVCRT.@)
  */
-unsigned int _control87(unsigned int newval, unsigned int mask)
+unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
 {
-#if defined(__GNUC__) && defined(__i386__)
-  unsigned int fpword = 0;
-  unsigned int flags = 0;
-
-  TRACE("(%08x, %08x): Called\n", newval, mask);
-
-  /* Get fp control word */
-  __asm__ __volatile__( "fstcw %0" : "=m" (fpword) : );
-
-  TRACE("Control word before : %08x\n", fpword);
-
-  /* Convert into mask constants */
-  if (fpword & 0x1)  flags |= _EM_INVALID;
-  if (fpword & 0x2)  flags |= _EM_DENORMAL;
-  if (fpword & 0x4)  flags |= _EM_ZERODIVIDE;
-  if (fpword & 0x8)  flags |= _EM_OVERFLOW;
-  if (fpword & 0x10) flags |= _EM_UNDERFLOW;
-  if (fpword & 0x20) flags |= _EM_INEXACT;
-  switch(fpword & 0xC00) {
-  case 0xC00: flags |= _RC_UP|_RC_DOWN; break;
-  case 0x800: flags |= _RC_UP; break;
-  case 0x400: flags |= _RC_DOWN; break;
-  }
-  switch(fpword & 0x300) {
-  case 0x0:   flags |= _PC_24; break;
-  case 0x200: flags |= _PC_53; break;
-  case 0x300: flags |= _PC_64; break;
-  }
-  if (fpword & 0x1000) flags |= _IC_AFFINE;
-
-  /* Mask with parameters */
-  flags = (flags & ~mask) | (newval & mask);
-
-  /* Convert (masked) value back to fp word */
-  fpword = 0;
-  if (flags & _EM_INVALID)    fpword |= 0x1;
-  if (flags & _EM_DENORMAL)   fpword |= 0x2;
-  if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
-  if (flags & _EM_OVERFLOW)   fpword |= 0x8;
-  if (flags & _EM_UNDERFLOW)  fpword |= 0x10;
-  if (flags & _EM_INEXACT)    fpword |= 0x20;
-  switch(flags & (_RC_UP | _RC_DOWN)) {
-  case _RC_UP|_RC_DOWN: fpword |= 0xC00; break;
-  case _RC_UP:          fpword |= 0x800; break;
-  case _RC_DOWN:        fpword |= 0x400; break;
-  }
-  switch (flags & (_PC_24 | _PC_53)) {
-  case _PC_64: fpword |= 0x300; break;
-  case _PC_53: fpword |= 0x200; break;
-  case _PC_24: fpword |= 0x0; break;
-  }
-  if (flags & _IC_AFFINE) fpword |= 0x1000;
-
-  TRACE("Control word after  : %08x\n", fpword);
+#if defined(__i386__) || defined(__x86_64__)
+    unsigned int x86_cw, sse2_cw;
 
-  /* Put fp control word */
-  __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
+    __control87_2( newval, mask, &x86_cw, &sse2_cw );
 
-  return flags;
+    if ((x86_cw ^ sse2_cw) & (MSVCRT__MCW_EM | MSVCRT__MCW_RC)) x86_cw |= MSVCRT__EM_AMBIGUOUS;
+    return x86_cw;
 #else
-  FIXME(":Not Implemented!\n");
-  return 0;
+    FIXME( "not implemented\n" );
+    return 0;
 #endif
 }
 
 /*********************************************************************
  *             _controlfp (MSVCRT.@)
  */
-unsigned int _controlfp(unsigned int newval, unsigned int mask)
+unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
 {
-#ifdef __i386__
-  return _control87( newval, mask & ~_EM_DENORMAL );
-#else
-  FIXME(":Not Implemented!\n");
-  return 0;
-#endif
+  return _control87( newval, mask & ~MSVCRT__EM_DENORMAL );
+}
+
+/*********************************************************************
+ *             _set_controlfp (MSVCRT.@)
+ */
+void CDECL _set_controlfp( unsigned int newval, unsigned int mask )
+{
+    _controlfp( newval, mask );
+}
+
+/*********************************************************************
+ *              _controlfp_s (MSVCRT.@)
+ */
+int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
+{
+    static const unsigned int all_flags = (MSVCRT__MCW_EM | MSVCRT__MCW_IC | MSVCRT__MCW_RC |
+                                           MSVCRT__MCW_PC | MSVCRT__MCW_DN);
+    unsigned int val;
+
+    if (!MSVCRT_CHECK_PMT( !(newval & mask & ~all_flags) ))
+    {
+        if (cur) *cur = _controlfp( 0, 0 );  /* retrieve it anyway */
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+    val = _controlfp( newval, mask );
+    if (cur) *cur = val;
+    return 0;
 }
 
 /*********************************************************************
  *             _copysign (MSVCRT.@)
  */
-double _copysign(double num, double sign)
+double CDECL _copysign(double num, double sign)
 {
   /* FIXME: Behaviour for Nan/Inf? */
   if (sign < 0.0)
@@ -594,7 +1109,7 @@ double _copysign(double num, double sign)
 /*********************************************************************
  *             _finite (MSVCRT.@)
  */
-int  _finite(double num)
+int CDECL _finite(double num)
 {
   return (finite(num)?1:0); /* See comment for _isnan() */
 }
@@ -602,19 +1117,25 @@ int  _finite(double num)
 /*********************************************************************
  *             _fpreset (MSVCRT.@)
  */
-void _fpreset(void)
-{
-#if defined(__GNUC__) && defined(__i386__)
-  __asm__ __volatile__( "fninit" );
+void CDECL _fpreset(void)
+{
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+    const unsigned int x86_cw = 0x27f;
+    __asm__ __volatile__( "fninit; fldcw %0" : : "m" (x86_cw) );
+    if (sse2_supported)
+    {
+        const unsigned long sse2_cw = 0x1f80;
+        __asm__ __volatile__( "ldmxcsr %0" : : "m" (sse2_cw) );
+    }
 #else
-  FIXME(":Not Implemented!\n");
+    FIXME( "not implemented\n" );
 #endif
 }
 
 /*********************************************************************
  *             _isnan (MSVCRT.@)
  */
-INT  _isnan(double num)
+INT CDECL _isnan(double num)
 {
   /* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
    * Do the same, as the result may be used in calculations
@@ -622,15 +1143,42 @@ INT  _isnan(double num)
   return isnan(num) ? 1 : 0;
 }
 
+/*********************************************************************
+ *             _j0 (MSVCRT.@)
+ */
+double CDECL _j0(double num)
+{
+  /* FIXME: errno handling */
+  return j0(num);
+}
+
+/*********************************************************************
+ *             _j1 (MSVCRT.@)
+ */
+double CDECL _j1(double num)
+{
+  /* FIXME: errno handling */
+  return j1(num);
+}
+
+/*********************************************************************
+ *             jn (MSVCRT.@)
+ */
+double CDECL _jn(int n, double num)
+{
+  /* FIXME: errno handling */
+  return jn(n, num);
+}
+
 /*********************************************************************
  *             _y0 (MSVCRT.@)
  */
-double _y0(double num)
+double CDECL _y0(double num)
 {
   double retval;
   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
   retval  = y0(num);
-  if (_fpclass(retval) == _FPCLASS_NINF)
+  if (_fpclass(retval) == MSVCRT__FPCLASS_NINF)
   {
     *MSVCRT__errno() = MSVCRT_EDOM;
     retval = sqrt(-1);
@@ -641,12 +1189,12 @@ double _y0(double num)
 /*********************************************************************
  *             _y1 (MSVCRT.@)
  */
-double _y1(double num)
+double CDECL _y1(double num)
 {
   double retval;
   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
   retval  = y1(num);
-  if (_fpclass(retval) == _FPCLASS_NINF)
+  if (_fpclass(retval) == MSVCRT__FPCLASS_NINF)
   {
     *MSVCRT__errno() = MSVCRT_EDOM;
     retval = sqrt(-1);
@@ -657,12 +1205,12 @@ double _y1(double num)
 /*********************************************************************
  *             _yn (MSVCRT.@)
  */
-double _yn(int order, double num)
+double CDECL _yn(int order, double num)
 {
   double retval;
   if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
   retval  = yn(order,num);
-  if (_fpclass(retval) == _FPCLASS_NINF)
+  if (_fpclass(retval) == MSVCRT__FPCLASS_NINF)
   {
     *MSVCRT__errno() = MSVCRT_EDOM;
     retval = sqrt(-1);
@@ -673,7 +1221,7 @@ double _yn(int order, double num)
 /*********************************************************************
  *             _nextafter (MSVCRT.@)
  */
-double _nextafter(double num, double next)
+double CDECL _nextafter(double num, double next)
 {
   double retval;
   if (!finite(num) || !finite(next)) *MSVCRT__errno() = MSVCRT_EDOM;
@@ -681,6 +1229,338 @@ double _nextafter(double num, double next)
   return retval;
 }
 
+/*********************************************************************
+ *             _ecvt (MSVCRT.@)
+ */
+char * CDECL _ecvt( double number, int ndigits, int *decpt, int *sign )
+{
+    int prec, len;
+    thread_data_t *data = msvcrt_get_thread_data();
+    /* FIXME: check better for overflow (native supports over 300 chars's) */
+    ndigits = min( ndigits, 80 - 7); /* 7 : space for dec point, 1 for "e",
+                                      * 4 for exponent and one for
+                                      * terminating '\0' */
+    if (!data->efcvt_buffer)
+        data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
+
+    if( number < 0) {
+        *sign = TRUE;
+        number = -number;
+    } else
+        *sign = FALSE;
+    /* handle cases with zero ndigits or less */
+    prec = ndigits;
+    if( prec < 1) prec = 2;
+    len = snprintf(data->efcvt_buffer, 80, "%.*le", prec - 1, number);
+    /* take the decimal "point away */
+    if( prec != 1)
+        memmove( data->efcvt_buffer + 1, data->efcvt_buffer + 2, len - 1 );
+    /* take the exponential "e" out */
+    data->efcvt_buffer[ prec] = '\0';
+    /* read the exponent */
+    sscanf( data->efcvt_buffer + prec + 1, "%d", decpt);
+    (*decpt)++;
+    /* adjust for some border cases */
+    if( data->efcvt_buffer[0] == '0')/* value is zero */
+        *decpt = 0;
+    /* handle cases with zero ndigits or less */
+    if( ndigits < 1){
+        if( data->efcvt_buffer[ 0] >= '5')
+            (*decpt)++;
+        data->efcvt_buffer[ 0] = '\0';
+    }
+    TRACE("out=\"%s\"\n",data->efcvt_buffer);
+    return data->efcvt_buffer;
+}
+
+/*********************************************************************
+ *             _ecvt_s (MSVCRT.@)
+ */
+int CDECL _ecvt_s( char *buffer, MSVCRT_size_t length, double number, int ndigits, int *decpt, int *sign )
+{
+    int prec, len;
+    char *result;
+    const char infret[] = "1#INF";
+
+    if(!MSVCRT_CHECK_PMT(buffer != NULL) || !MSVCRT_CHECK_PMT(decpt != NULL) || !MSVCRT_CHECK_PMT(sign != NULL))
+    {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+    if(!MSVCRT_CHECK_PMT(length > 2) || !MSVCRT_CHECK_PMT(ndigits < (int)length - 1))
+    {
+        *MSVCRT__errno() = MSVCRT_ERANGE;
+        return MSVCRT_ERANGE;
+    }
+
+    /* special case - inf */
+    if(number == HUGE_VAL || number == -HUGE_VAL)
+    {
+        memset(buffer, '0', ndigits);
+        memcpy(buffer, infret, min(ndigits, sizeof(infret) - 1 ) );
+        buffer[ndigits] = '\0';
+        (*decpt) = 1;
+        if(number == -HUGE_VAL)
+            (*sign) = 1;
+        else
+            (*sign) = 0;
+        return 0;
+    }
+    /* handle cases with zero ndigits or less */
+    prec = ndigits;
+    if( prec < 1) prec = 2;
+    result = (char*)MSVCRT_malloc(prec + 7);
+
+    if( number < 0) {
+        *sign = TRUE;
+        number = -number;
+    } else
+        *sign = FALSE;
+    len = snprintf(result, prec + 7, "%.*le", prec - 1, number);
+    /* take the decimal "point away */
+    if( prec != 1)
+        memmove( result + 1, result + 2, len - 1 );
+    /* take the exponential "e" out */
+    result[ prec] = '\0';
+    /* read the exponent */
+    sscanf( result + prec + 1, "%d", decpt);
+    (*decpt)++;
+    /* adjust for some border cases */
+    if( result[0] == '0')/* value is zero */
+        *decpt = 0;
+    /* handle cases with zero ndigits or less */
+    if( ndigits < 1){
+        if( result[ 0] >= '5')
+            (*decpt)++;
+        result[ 0] = '\0';
+    }
+    memcpy( buffer, result, max(ndigits + 1, 1) );
+    MSVCRT_free( result );
+    return 0;
+}
+
+/***********************************************************************
+ *             _fcvt  (MSVCRT.@)
+ */
+char * CDECL _fcvt( double number, int ndigits, int *decpt, int *sign )
+{
+    thread_data_t *data = msvcrt_get_thread_data();
+    int stop, dec1, dec2;
+    char *ptr1, *ptr2, *first;
+    char buf[80]; /* ought to be enough */
+
+    if (!data->efcvt_buffer)
+        data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
+
+    if (number < 0)
+    {
+       *sign = 1;
+       number = -number;
+    } else *sign = 0;
+
+    snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
+    ptr1 = buf;
+    ptr2 = data->efcvt_buffer;
+    first = NULL;
+    dec1 = 0;
+    dec2 = 0;
+
+    /* For numbers below the requested resolution, work out where
+       the decimal point will be rather than finding it in the string */
+    if (number < 1.0 && number > 0.0) {
+       dec2 = log10(number + 1e-10);
+       if (-dec2 <= ndigits) dec2 = 0;
+    }
+
+    /* If requested digits is zero or less, we will need to truncate
+     * the returned string */
+    if (ndigits < 1) {
+       stop = strlen(buf) + ndigits;
+    } else {
+       stop = strlen(buf);
+    }
+
+    while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
+    while (*ptr1 != '\0' && *ptr1 != '.') {
+       if (!first) first = ptr2;
+       if ((ptr1 - buf) < stop) {
+           *ptr2++ = *ptr1++;
+       } else {
+           ptr1++;
+       }
+       dec1++;
+    }
+
+    if (ndigits > 0) {
+       ptr1++;
+       if (!first) {
+           while (*ptr1 == '0') { /* Process leading zeroes */
+               *ptr2++ = *ptr1++;
+               dec1--;
+           }
+       }
+       while (*ptr1 != '\0') {
+           if (!first) first = ptr2;
+           *ptr2++ = *ptr1++;
+       }
+    }
+
+    *ptr2 = '\0';
+
+    /* We never found a non-zero digit, then our number is either
+     * smaller than the requested precision, or 0.0 */
+    if (!first) {
+       if (number > 0.0) {
+           first = ptr2;
+       } else {
+           first = data->efcvt_buffer;
+           dec1 = 0;
+       }
+    }
+
+    *decpt = dec2 ? dec2 : dec1;
+    return first;
+}
+
+/***********************************************************************
+ *             _fcvt_s  (MSVCRT.@)
+ */
+int CDECL _fcvt_s(char* outbuffer, MSVCRT_size_t size, double number, int ndigits, int *decpt, int *sign)
+{
+    int stop, dec1, dec2;
+    char *ptr1, *ptr2, *first;
+    char buf[80]; /* ought to be enough */
+
+    if (!outbuffer || !decpt || !sign || size == 0)
+    {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+
+    if (number < 0)
+    {
+       *sign = 1;
+       number = -number;
+    } else *sign = 0;
+
+    snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
+    ptr1 = buf;
+    ptr2 = outbuffer;
+    first = NULL;
+    dec1 = 0;
+    dec2 = 0;
+
+    /* For numbers below the requested resolution, work out where
+       the decimal point will be rather than finding it in the string */
+    if (number < 1.0 && number > 0.0) {
+       dec2 = log10(number + 1e-10);
+       if (-dec2 <= ndigits) dec2 = 0;
+    }
+
+    /* If requested digits is zero or less, we will need to truncate
+     * the returned string */
+    if (ndigits < 1) {
+       stop = strlen(buf) + ndigits;
+    } else {
+       stop = strlen(buf);
+    }
+
+    while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
+    while (*ptr1 != '\0' && *ptr1 != '.') {
+       if (!first) first = ptr2;
+       if ((ptr1 - buf) < stop) {
+           if (size > 1) {
+                *ptr2++ = *ptr1++;
+                size--;
+            }
+       } else {
+           ptr1++;
+       }
+       dec1++;
+    }
+
+    if (ndigits > 0) {
+       ptr1++;
+       if (!first) {
+           while (*ptr1 == '0') { /* Process leading zeroes */
+                if (number == 0.0 && size > 1) {
+                    *ptr2++ = '0';
+                    size--;
+                }
+                ptr1++;
+               dec1--;
+           }
+       }
+       while (*ptr1 != '\0') {
+           if (!first) first = ptr2;
+           if (size > 1) {
+                *ptr2++ = *ptr1++;
+                size--;
+            }
+       }
+    }
+
+    *ptr2 = '\0';
+
+    /* We never found a non-zero digit, then our number is either
+     * smaller than the requested precision, or 0.0 */
+    if (!first && (number <= 0.0))
+        dec1 = 0;
+
+    *decpt = dec2 ? dec2 : dec1;
+    return 0;
+}
+
+/***********************************************************************
+ *             _gcvt  (MSVCRT.@)
+ */
+char * CDECL _gcvt( double number, int ndigit, char *buff )
+{
+    if(!buff) {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return NULL;
+    }
+
+    if(ndigit < 0) {
+        *MSVCRT__errno() = MSVCRT_ERANGE;
+        return NULL;
+    }
+
+    MSVCRT_sprintf(buff, "%.*g", ndigit, number);
+    return buff;
+}
+
+/***********************************************************************
+ *              _gcvt_s  (MSVCRT.@)
+ */
+int CDECL _gcvt_s(char *buff, MSVCRT_size_t size, double number, int digits)
+{
+    int len;
+
+    if(!buff) {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+
+    if( digits<0 || digits>=size) {
+        if(size)
+            buff[0] = '\0';
+
+        *MSVCRT__errno() = MSVCRT_ERANGE;
+        return MSVCRT_ERANGE;
+    }
+
+    len = MSVCRT__scprintf("%.*g", digits, number);
+    if(len > size) {
+        buff[0] = '\0';
+        *MSVCRT__errno() = MSVCRT_ERANGE;
+        return MSVCRT_ERANGE;
+    }
+
+    MSVCRT_sprintf(buff, "%.*g", digits, number);
+    return 0;
+}
+
 #include <stdlib.h> /* div_t, ldiv_t */
 
 /*********************************************************************
@@ -689,12 +1569,10 @@ double _nextafter(double num, double next)
  *     [i386] Windows binary compatible - returns the struct in eax/edx.
  */
 #ifdef __i386__
-LONGLONG MSVCRT_div(int num, int denom)
+unsigned __int64 CDECL MSVCRT_div(int num, int denom)
 {
-  LONGLONG retval;
   div_t dt = div(num,denom);
-  retval = ((LONGLONG)dt.rem << 32) | dt.quot;
-  return retval;
+  return ((unsigned __int64)dt.rem << 32) | (unsigned int)dt.quot;
 }
 #else
 /*********************************************************************
@@ -702,7 +1580,7 @@ LONGLONG MSVCRT_div(int num, int denom)
  * VERSION
  *     [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
  */
-MSVCRT_div_t MSVCRT_div(int num, int denom)
+MSVCRT_div_t CDECL MSVCRT_div(int num, int denom)
 {
   div_t dt = div(num,denom);
   MSVCRT_div_t     ret;
@@ -721,12 +1599,10 @@ MSVCRT_div_t MSVCRT_div(int num, int denom)
  *     [i386] Windows binary compatible - returns the struct in eax/edx.
  */
 #ifdef __i386__
-ULONGLONG MSVCRT_ldiv(long num, long denom)
+unsigned __int64 CDECL MSVCRT_ldiv(MSVCRT_long num, MSVCRT_long denom)
 {
-  ULONGLONG retval;
   ldiv_t ldt = ldiv(num,denom);
-  retval = ((ULONGLONG)ldt.rem << 32) | (ULONG)ldt.quot;
-  return retval;
+  return ((unsigned __int64)ldt.rem << 32) | (MSVCRT_ulong)ldt.quot;
 }
 #else
 /*********************************************************************
@@ -734,7 +1610,7 @@ ULONGLONG MSVCRT_ldiv(long num, long denom)
  * VERSION
  *     [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
  */
-MSVCRT_ldiv_t MSVCRT_ldiv(long num, long denom)
+MSVCRT_ldiv_t CDECL MSVCRT_ldiv(MSVCRT_long num, MSVCRT_long denom)
 {
   ldiv_t result = ldiv(num,denom);
 
@@ -746,58 +1622,58 @@ MSVCRT_ldiv_t MSVCRT_ldiv(long num, long denom)
 }
 #endif /* ifdef __i386__ */
 
+#ifdef __i386__
+
+/*********************************************************************
+ *             _adjust_fdiv (MSVCRT.@)
+ * Used by the MSVC compiler to work around the Pentium FDIV bug.
+ */
+int MSVCRT__adjust_fdiv = 0;
+
 /***********************************************************************
  *             _adj_fdiv_m16i (MSVCRT.@)
- * FIXME
- *    This function is likely to have the wrong number of arguments.
  *
  * NOTE
  *    I _think_ this function is intended to work around the Pentium
  *    fdiv bug.
  */
-void _adj_fdiv_m16i(void)
+void __stdcall _adj_fdiv_m16i( short arg )
 {
   TRACE("(): stub\n");
 }
 
 /***********************************************************************
  *             _adj_fdiv_m32 (MSVCRT.@)
- * FIXME
- *    This function is likely to have the wrong number of arguments.
  *
  * NOTE
  *    I _think_ this function is intended to work around the Pentium
  *    fdiv bug.
  */
-void _adj_fdiv_m32(void)
+void __stdcall _adj_fdiv_m32( unsigned int arg )
 {
   TRACE("(): stub\n");
 }
 
 /***********************************************************************
  *             _adj_fdiv_m32i (MSVCRT.@)
- * FIXME
- *    This function is likely to have the wrong number of arguments.
  *
  * NOTE
  *    I _think_ this function is intended to work around the Pentium
  *    fdiv bug.
  */
-void _adj_fdiv_m32i(void)
+void __stdcall _adj_fdiv_m32i( int arg )
 {
   TRACE("(): stub\n");
 }
 
 /***********************************************************************
  *             _adj_fdiv_m64 (MSVCRT.@)
- * FIXME
- *    This function is likely to have the wrong number of arguments.
  *
  * NOTE
  *    I _think_ this function is intended to work around the Pentium
  *    fdiv bug.
  */
-void _adj_fdiv_m64(void)
+void __stdcall _adj_fdiv_m64( unsigned __int64 arg )
 {
   TRACE("(): stub\n");
 }
@@ -818,56 +1694,48 @@ void _adj_fdiv_r(void)
 
 /***********************************************************************
  *             _adj_fdivr_m16i (MSVCRT.@)
- * FIXME
- *    This function is likely to have the wrong number of arguments.
  *
  * NOTE
  *    I _think_ this function is intended to work around the Pentium
  *    fdiv bug.
  */
-void _adj_fdivr_m16i(void)
+void __stdcall _adj_fdivr_m16i( short arg )
 {
   TRACE("(): stub\n");
 }
 
 /***********************************************************************
  *             _adj_fdivr_m32 (MSVCRT.@)
- * FIXME
- *    This function is likely to have the wrong number of arguments.
  *
  * NOTE
  *    I _think_ this function is intended to work around the Pentium
  *    fdiv bug.
  */
-void _adj_fdivr_m32(void)
+void __stdcall _adj_fdivr_m32( unsigned int arg )
 {
   TRACE("(): stub\n");
 }
 
 /***********************************************************************
  *             _adj_fdivr_m32i (MSVCRT.@)
- * FIXME
- *    This function is likely to have the wrong number of arguments.
  *
  * NOTE
  *    I _think_ this function is intended to work around the Pentium
  *    fdiv bug.
  */
-void _adj_fdivr_m32i(void)
+void __stdcall _adj_fdivr_m32i( int arg )
 {
   TRACE("(): stub\n");
 }
 
 /***********************************************************************
  *             _adj_fdivr_m64 (MSVCRT.@)
- * FIXME
- *    This function is likely to have the wrong number of arguments.
  *
  * NOTE
  *    I _think_ this function is intended to work around the Pentium
  *    fdiv bug.
  */
-void _adj_fdivr_m64(void)
+void __stdcall _adj_fdivr_m64( unsigned __int64 arg )
 {
   TRACE("(): stub\n");
 }
@@ -928,17 +1796,6 @@ void _adj_fptan(void)
   TRACE("(): stub\n");
 }
 
-/***********************************************************************
- *             _adjust_fdiv (MSVCRT.@)
- * FIXME
- *    I _think_ this function should be a variable indicating whether
- *    Pentium fdiv bug safe code should be used.
- */
-void _adjust_fdiv(void)
-{
-  TRACE("(): stub\n");
-}
-
 /***********************************************************************
  *             _safe_fdiv (MSVCRT.@)
  * FIXME
@@ -995,3 +1852,236 @@ void _safe_fprem1(void)
 {
   TRACE("(): stub\n");
 }
+
+/***********************************************************************
+ *             __libm_sse2_acos   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_acos(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = acos( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_acosf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_acosf(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = acosf( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_asin   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_asin(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = asin( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_asinf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_asinf(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = asinf( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_atan   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_atan(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = atan( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_atan2   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_atan2(void)
+{
+    double d1, d2;
+    __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
+    d1 = atan2( d1, d2 );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_atanf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_atanf(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = atanf( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_cos   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_cos(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = cos( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_cosf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_cosf(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = cosf( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_exp   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_exp(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = exp( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_expf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_expf(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = expf( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_log   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_log(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = log( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_log10   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_log10(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = log10( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_log10f   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_log10f(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = log10f( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_logf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_logf(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = logf( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_pow   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_pow(void)
+{
+    double d1, d2;
+    __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
+    d1 = pow( d1, d2 );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_powf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_powf(void)
+{
+    float f1, f2;
+    __asm__ __volatile__( "movd %%xmm0,%0; movd %%xmm1,%1" : "=g" (f1), "=g" (f2) );
+    f1 = powf( f1, f2 );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f1) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_sin   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_sin(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = sin( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_sinf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_sinf(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = sinf( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_tan   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_tan(void)
+{
+    double d;
+    __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
+    d = tan( d );
+    __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
+}
+
+/***********************************************************************
+ *             __libm_sse2_tanf   (MSVCRT.@)
+ */
+void __cdecl __libm_sse2_tanf(void)
+{
+    float f;
+    __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
+    f = tanf( f );
+    __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
+}
+
+#endif  /* __i386__ */