From 2b010811d843ddb67dec894f44ae91f78a14c70d Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 25 Feb 2014 12:50:08 +0100 Subject: [PATCH] fixes #932, and partially also fixes #921 --- Algorithms/IteratorBasedCRC32.h | 68 +++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/Algorithms/IteratorBasedCRC32.h b/Algorithms/IteratorBasedCRC32.h index d85d75893..e4a6dc6ec 100644 --- a/Algorithms/IteratorBasedCRC32.h +++ b/Algorithms/IteratorBasedCRC32.h @@ -25,34 +25,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ITERATORBASEDCRC32_H_ -#define ITERATORBASEDCRC32_H_ +#ifndef ITERATOR_BASED_CRC32_H +#define ITERATOR_BASED_CRC32_H #include "../Util/SimpleLogger.h" -#include // for boost::crc_32_type #include +#if defined(__x86_64__) + #include +#else + #include // for boost::crc_32_type + + inline void __get_cpuid( + int param, + unsigned *eax, + unsigned *ebx, + unsigned *ecx, + unsigned *edx + ) { *ecx = 0; } +#endif + template class IteratorbasedCRC32 { private: typedef typename ContainerT::iterator IteratorType; unsigned crc; - typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type; typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc); + CRC32CFunctionPtr crc_function; - unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){ +#if !defined(__x86_64__) boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor; +#endif + unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){ +#if !defined(__x86_64__) CRC32_processor.process_bytes( str, len); return CRC32_processor.checksum(); +#else + return 0; +#endif } - unsigned SSE42BasedCRC32( char *str, unsigned len, unsigned crc){ + // adapted from http://byteworm.com/2010/10/13/crc32/ + unsigned SSE42BasedCRC32( char *str, unsigned len, unsigned){ #if defined(__x86_64__) - unsigned q=len/sizeof(unsigned), - r=len%sizeof(unsigned), - *p=(unsigned*)str/*, crc*/; + unsigned q = len/sizeof(unsigned); + unsigned r = len%sizeof(unsigned); + unsigned *p = (unsigned*)str; //crc=0; while (q--) { @@ -77,25 +97,17 @@ private: return crc; } -#if defined(__x86_64__) - unsigned cpuid(unsigned functionInput){ - unsigned eax; - unsigned ebx; - unsigned ecx; - unsigned edx; - asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput)); + inline unsigned cpuid() const { + unsigned eax, ebx, ecx, edx; + // on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl. + __get_cpuid( 1, &eax, &ebx, &ecx, &edx ); return ecx; } -#endif CRC32CFunctionPtr DetectNativeCRC32Support(){ -#if defined(__x86_64__) - static const int SSE42_BIT = 20; - unsigned ecx = cpuid(1); - bool has_SSE42 = ecx & (1 << SSE42_BIT); -#else - bool has_SSE42 = false; -#endif + static const int SSE42_BIT = 0x00100000; + const unsigned ecx = cpuid(); + const bool has_SSE42 = ecx & SSE42_BIT; if (has_SSE42) { SimpleLogger().Write() << "using hardware based CRC32 computation"; return &IteratorbasedCRC32::SSE42BasedCRC32; //crc32 hardware accelarated; @@ -104,23 +116,21 @@ private: return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8; } } - CRC32CFunctionPtr crc_function; + public: IteratorbasedCRC32(): crc(0) { crc_function = DetectNativeCRC32Support(); } - // virtual ~IteratorbasedCRC32() { } - unsigned operator()( IteratorType iter, const IteratorType end) { unsigned crc = 0; while(iter != end) { char * data = reinterpret_cast(&(*iter) ); - crc =((*this).*(crc_function))(data, sizeof(typename ContainerT::value_type*), crc); + crc =((*this).*(crc_function))(data, sizeof(typename ContainerT::value_type), crc); ++iter; } return crc; } }; -#endif /* ITERATORBASEDCRC32_H_ */ +#endif /* ITERATOR_BASED_CRC32_H */