Index: os.h =================================================================== --- os.h (revision 14848) +++ os.h (working copy) @@ -113,10 +113,11 @@ __asm__("fistl %0": "=m"(i) : "t"(f)); return(i); } -#endif +#endif /* Special i386 GCC implementation */ -#if defined(_WIN32) && !defined(__GNUC__) && !defined(__BORLANDC__) +/* Win32 implementation for Visual C++ (any others with this combination of flags?) */ +#if defined(_WIN32) && !defined(_WIN64) && !defined(__GNUC__) && !defined(__BORLANDC__) # define VORBIS_FPU_CONTROL typedef ogg_int16_t vorbis_fpu_control; @@ -136,15 +137,43 @@ static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){ } -#endif +#endif /* Special Win32 Visual C++ implementation */ +/* Win64 implementation using SSE intrinsics for Visual C++ 2005 and above */ +/* Any CPU supporting x64 also supports SSE, so this is safe and will not lead + to issues with users that do not have an SSE-capable CPU +*/ +#if defined(_WIN32) && defined(_WIN64) && defined(_MSC_VER) && (_MSC_VER >= 1400) +# define VORBIS_FPU_CONTROL + +typedef ogg_int16_t vorbis_fpu_control; + +/* Special implementation for msvc x64 where inline asm doesn't work */ +#include +static int vorbis_ftoi(double f){ + return _mm_cvtsd_si32(_mm_load_sd(&f)); +} + +static __inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){ +} +static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){ +} + +#endif /* Special Win64 (64-bit) Visual C++ implementation */ + +/* If no special implementation was found for the current compiler / platform, + use the default implementation here: */ #ifndef VORBIS_FPU_CONTROL typedef int vorbis_fpu_control; static int vorbis_ftoi(double f){ - return (int)(f+.5); + /* Old implementation (only correct when no negative numbers encountered): */ + /* return (int)(f+.5); */ + + /* Proper but slower implementation */ + return (f < 0) ? (int)(f - 0.5) : (int)(f + 0.5); } /* We don't have special code for this compiler/arch, so do it the slow way */