// Copyright (c) 1996-1999 Microsoft Corporation #ifdef DMSYNTH_MINIPORT #include "common.h" #else #include "simple.h" #include "float.h" #endif #ifdef _ALPHA_ #include #endif // _ALPHA_ #ifndef _ALPHA_ #ifndef DBG extern "C" int _fltused = 1; #endif // asm_fsave(rgbState) // // Store the floating point state into and reinitialize the FPU. // void __cdecl asm_fsave(char *rgbState) { _asm { mov eax, dword ptr rgbState fsave [eax] } } // asm_frestore(rgbState) // // Restore a previously saved floating point state . // void __cdecl asm_frestore(const char *rgbState) { _asm { fwait mov eax, dword ptr rgbState frstor [eax] } } // FLOATSAFE // // Saves floating point state on construction and restores on destruction. // struct FLOATSAFE { char m_rgbState[105]; FLOATSAFE::FLOATSAFE(void) { asm_fsave(m_rgbState); } FLOATSAFE::~FLOATSAFE(void) { asm_frestore(m_rgbState); } }; // asm_fdiv() // float __cdecl asm_fdiv(float flNum, float flDenom) { float flResult = (float) 0.0; if (flDenom != (float) 0.0) { _asm { fld flNum fdiv flDenom fstp flResult fnclex ; clear the status word of exceptions } } return(flResult); } // asm__fsin() // float __cdecl asm_fsin(float flRad) { float flSine; _asm { fld flRad fsin fstp flSine fnclex ; clear the status word of exceptions } return(flSine); } // asm__fcos() // float __cdecl asm_fcos(float flRad) { float flCosine; _asm { fld flRad fcos fstp flCosine fnclex ; clear the status word of exceptions } return(flCosine); } // asm_flog2() // float __cdecl asm_flog2(float flX) { float flLog; _asm { fld1 fld flX fyl2X fstp flLog; fnclex ; clear the status word of exceptions } return flLog; } // asm_ftol() // long __cdecl asm_ftol(float flX) { long lResult; WORD wCW; WORD wNewCW; _asm { fld flX // Push the float onto the stack wait fnstcw wCW // Store the control word wait mov ax,wCW // Setup our rounding or ah,0x0c mov wNewCW,ax fldcw wNewCW // Set Control word to our new value fistp lResult // Round off top of stack into result fldcw wCW // Restore control word fnclex // clear the status word of exceptions } return(lResult); } // asm_fpow() // float __cdecl asm_fpow(float flX, float flY) { float flHalf = (float) 0.5; float flOne = (float) 1.0; float flResult = (float) 0.0; if (flX == (float) 0.0 && flY > (float) 0.0) { flResult = (float) 0.0; } else if (flX == (float) 0.0 && flY <= (float) 0.0) { flResult = (float) 1.0; } else if (flY == (float) 0.0) { flResult = (float) 1.0; } else { BOOL fNeg = FALSE; // Ok, if X is negative the sign is positive if the Y is even // and negative if Y is odd. Fractions can't be done. if (flX < (float) 0.0) { long lY = asm_ftol(flY); if ((float) lY == flY) // Only fix it if we have a integer poer { flX = -flX; if (lY % 2) { fNeg = TRUE; } } } flX = flY * asm_flog2(flX); if (max(-flX,flX) < flOne) // Is the power is in the range which F2XM1 can handle? { _asm { fld flX // Put flX in ST[0] f2xm1 // ST := 2^ST - 1 fadd flOne // ST := 2^mantissa fstp flResult // Store result fnclex // clear the status word of exceptions } } else // Nope, we've got to scale first { _asm { fld flX // Put flX in ST[0] fld ST // Duplicate ST frndint // Integral value in ST fsub ST(1),ST // Fractional value in ST(1) fxch // Factional value in ST f2xm1 // ST := 2^ST - 1 fadd flOne // ST := 2^frac fscale // ST := 2^frac * 2^integral fstp flResult // Store result fnclex // clear the status word of exceptions } } if (fNeg) { flResult = -flResult; } } return flResult; } #endif // _ALPHA_ // fp_ftol() // STDAPI_(long) fp_ftol(float flX) { #ifdef _ALPHA_ return (long)flX; #else FLOATSAFE fs; return(asm_ftol(flX)); #endif } // fp_ltof() // STDAPI_(float) fp_ltof(long lx) { #ifndef _ALPHA_ FLOATSAFE fs; #endif return(float(lx)); } // fp_fadd() // STDAPI_(float) fp_fadd(float flX, float flY) { #ifndef _ALPHA_ FLOATSAFE fs; #endif return(flX + flY); } // fp_fsub() // STDAPI_(float) fp_fsub(float flX, float flY) { #ifndef _ALPHA_ FLOATSAFE fs; #endif return(flX - flY); } // fp_fmul() // STDAPI_(float) fp_fmul(float flX, float flY) { #ifndef _ALPHA_ FLOATSAFE fs; #endif return(flX * flY); } // fp_fdiv() // STDAPI_(float) fp_fdiv(float flNum, float flDenom) { #ifdef _ALPHA_ return flNum/flDenom; #else FLOATSAFE fs; return(asm_fdiv(flNum,flDenom)); #endif } // fp_fabs() // STDAPI_(float) fp_fabs(float flX) { #ifndef _ALPHA_ FLOATSAFE fs; #endif return max(-flX,flX); } // fp_fsin() // STDAPI_(float) fp_fsin(float flRad) { #ifdef _ALPHA_ return sin(flRad); #else FLOATSAFE fs; return(asm_fsin(flRad)); #endif } // fp_fcos() // STDAPI_(float) fp_fcos(float flRad) { #ifdef _ALPHA_ return cos(flRad); #else FLOATSAFE fs; return(asm_fcos(flRad)); #endif } // fp_fpow() // STDAPI_(float) fp_fpow(float flX, float flY) { #ifdef _ALPHA_ return pow(flX, flY); #else FLOATSAFE fs; return(asm_fpow(flX,flY)); #endif } // fp_flog2() // STDAPI_(float) fp_flog2(float flX) { #ifdef _ALPHA_ return log(flX); #else FLOATSAFE fs; return(asm_flog2(flX)); #endif } // fp_flog10() // STDAPI_(float) fp_flog10(float flX) { #ifdef _ALPHA_ return log10(flX); #else FLOATSAFE fs; #define LOG2OF10 float(3.321928094887) return(asm_fdiv(asm_flog2(flX),LOG2OF10)); #endif } // fp_fchs() // STDAPI_(float) fp_fchs(float flX) { #ifndef _ALPHA_ FLOATSAFE fs; #endif return(-flX); } // fp_fcmp() // STDAPI_(int) fp_fcmp(float flA, float flB) { #ifndef _ALPHA_ FLOATSAFE fs; #endif if (flA > flB) return(1); if (flA < flB) return(-1); return(0); } // fp_fmin() // STDAPI_(float) fp_fmin(float flA, float flB) { #ifndef _ALPHA_ FLOATSAFE fs; #endif return(min(flA,flB)); } // fp_fmax() // STDAPI_(float) fp_fmax(float flA, float flB) { #ifndef _ALPHA_ FLOATSAFE fs; #endif return(max(flA,flB)); }