From cff862344f02df4679e057673a477d0b9deec23d Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 28 Aug 2012 15:36:26 -0400 Subject: [PATCH] Add compiler specific syntax for inline assembly. --- BPTCEncoder/CMakeLists.txt | 78 +++++++++++++++++++++++++++++-- BPTCEncoder/config/BC7Config.h.in | 1 + BPTCEncoder/src/RGBAEndpoints.cpp | 21 ++++++--- 3 files changed, 89 insertions(+), 11 deletions(-) diff --git a/BPTCEncoder/CMakeLists.txt b/BPTCEncoder/CMakeLists.txt index 604258c..06fc889 100644 --- a/BPTCEncoder/CMakeLists.txt +++ b/BPTCEncoder/CMakeLists.txt @@ -5,7 +5,67 @@ INCLUDE(CheckCXXSourceRuns) SET(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) IF(CMAKE_COMPILER_IS_GNUCC) - SET(CMAKE_REQUIRED_FLAGS -msse4.1 -E) + + # Test whether or not the compiler allows inline + # assmbly... + CHECK_CXX_SOURCE_RUNS(" + \#ifdef _MSC_VER + int main() { + int x = 1, y = 0; + __asm { + mov eax, x + mov y, eax + } + return !y; + } + \#else + int main() { + int x = 1, y = 0; + __asm__ (\"movl %1, %%eax;\" + \"movl %%eax, %0;\" + :\"=r\"(y) /* output */ + :\"r\"(x) /* input */ + :\"%eax\" /* clobbered register */ + ); + + return !y; + } + \#endif" + HAS_INLINE_ASSEMBLY + ) + + # If the compiler doesn't allow it, then try with a + # compiler flag... + IF( NOT HAS_INLINE_ASSEMBLY ) + SET(CMAKE_REQUIRED_FLAGS -fasm-blocks) + CHECK_CXX_SOURCE_RUNS(" + \#ifdef _MSC_VER + int main() { + int x = 1, y = 0; + __asm { + mov eax, x + mov y, eax + } + return !y; + } + \#else + int main() { + int x = 1, y = 0; + __asm__ (\"movl %1, %%eax;\" + \"movl %%eax, %0;\" + :\"=r\"(y) /* output */ + :\"r\"(x) /* input */ + :\"%eax\" /* clobbered register */ + ); + + return !y; + } + \#endif" + HAS_INLINE_ASSEMBLY_WITH_FLAGS + ) + ENDIF() + + SET(CMAKE_REQUIRED_FLAGS -msse4.1) CHECK_CXX_SOURCE_RUNS(" #include int main() { @@ -36,15 +96,15 @@ ELSEIF(MSVC) ENDIF() SET(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +IF( NOT HAS_INLINE_ASSEMBLY AND NOT HAS_INLINE_ASSEMBLY_WITH_FLAGS ) + SET( NO_INLINE_ASSEMBLY true ) +ENDIF() + CONFIGURE_FILE( "config/BC7Config.h.in" "include/BC7Config.h" ) -IF(CMAKE_COMPILER_IS_GNUCC) - ADD_DEFINITIONS(-fasm-blocks) -ENDIF(CMAKE_COMPILER_IS_GNUCC) - SET( HEADERS src/BC7CompressionMode.h src/BC7IntTypes.h @@ -86,6 +146,14 @@ IF( HAS_SSE_41 ) ) ENDIF( HAS_SSE_41 ) +IF( HAS_INLINE_ASSEMBLY_WITH_FLAGS ) + IF( MSVC ) + # !FIXME! + ELSE() + ADD_DEFINITIONS( -fasm-blocks ) + ENDIF() +ENDIF() + ADD_LIBRARY( BPTCEncoder ${HEADERS} ${SOURCES} diff --git a/BPTCEncoder/config/BC7Config.h.in b/BPTCEncoder/config/BC7Config.h.in index 599835a..174a962 100644 --- a/BPTCEncoder/config/BC7Config.h.in +++ b/BPTCEncoder/config/BC7Config.h.in @@ -5,4 +5,5 @@ // explicitly by the CMake build process. // Do we have the proper popcnt instruction defined? +#cmakedefine NO_INLINE_ASSEMBLY #cmakedefine HAS_SSE_POPCNT diff --git a/BPTCEncoder/src/RGBAEndpoints.cpp b/BPTCEncoder/src/RGBAEndpoints.cpp index 0b7c541..fd64498 100755 --- a/BPTCEncoder/src/RGBAEndpoints.cpp +++ b/BPTCEncoder/src/RGBAEndpoints.cpp @@ -15,6 +15,7 @@ // //-------------------------------------------------------------------------------------- +#include "BC7Config.h" #include "BC7IntTypes.h" #include "RGBAEndpoints.h" #include "BC7Compressor.h" @@ -66,7 +67,7 @@ static const float kFloatConversion[256] = { /////////////////////////////////////////////////////////////////////////////// static inline uint32 CountBitsInMask(uint8 n) { -#if _WIN64 +#if defined(_WIN64) || defined(NO_INLINE_ASSEMBLY) if(!n) return 0; // no bits set if(!(n & (n-1))) return 1; // power of two @@ -76,15 +77,23 @@ static inline uint32 CountBitsInMask(uint8 n) { } return c; #else - - __asm - { +#ifdef _MSC_VER + __asm { mov eax, 8 movzx ecx, n bsf ecx, ecx sub eax, ecx - } - + } +#else + __asm__("mov %%eax, 8;" + "movzbl %0, %%ecx;" + "bsf %%ecx, %%ecx;" + "sub %%eax, %%ecx;" + : // No output registers + : "r"(n) + : "%eax", "%ecx" + ); +#endif #endif }