From 34692ab826abc8f8faa61bdb2280b742424528f1 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 7 Dec 2013 15:14:29 -0500 Subject: Remove unnecessary Src/ folders --- Source/Core/Common/Hash.cpp | 520 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 520 insertions(+) create mode 100644 Source/Core/Common/Hash.cpp (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp new file mode 100644 index 0000000000..ab017347e8 --- /dev/null +++ b/Source/Core/Common/Hash.cpp @@ -0,0 +1,520 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + + +#include "Hash.h" +#if _M_SSE >= 0x402 +#include "CPUDetect.h" +#include +#endif + +static u64 (*ptrHashFunction)(const u8 *src, int len, u32 samples) = &GetMurmurHash3; + +// uint32_t +// WARNING - may read one more byte! +// Implementation from Wikipedia. +u32 HashFletcher(const u8* data_u8, size_t length) +{ + const u16* data = (const u16*)data_u8; /* Pointer to the data to be summed */ + size_t len = (length + 1) / 2; /* Length in 16-bit words */ + u32 sum1 = 0xffff, sum2 = 0xffff; + + while (len) + { + size_t tlen = len > 360 ? 360 : len; + len -= tlen; + + do { + sum1 += *data++; + sum2 += sum1; + } + while (--tlen); + + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + } + + // Second reduction step to reduce sums to 16 bits + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + return(sum2 << 16 | sum1); +} + + +// Implementation from Wikipedia +// Slightly slower than Fletcher above, but slightly more reliable. +#define MOD_ADLER 65521 +// data: Pointer to the data to be summed; len is in bytes +u32 HashAdler32(const u8* data, size_t len) +{ + u32 a = 1, b = 0; + + while (len) + { + size_t tlen = len > 5550 ? 5550 : len; + len -= tlen; + + do + { + a += *data++; + b += a; + } + while (--tlen); + + a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER); + b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); + } + + // It can be shown that a <= 0x1013a here, so a single subtract will do. + if (a >= MOD_ADLER) + { + a -= MOD_ADLER; + } + + // It can be shown that b can reach 0xfff87 here. + b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); + + if (b >= MOD_ADLER) + { + b -= MOD_ADLER; + } + + return((b << 16) | a); +} + +// Stupid hash - but can't go back now :) +// Don't use for new things. At least it's reasonably fast. +u32 HashEctor(const u8* ptr, int length) +{ + u32 crc = 0; + + for (int i = 0; i < length; i++) + { + crc ^= ptr[i]; + crc = (crc << 3) | (crc >> 29); + } + + return(crc); +} + + +#ifdef _M_X64 + +//----------------------------------------------------------------------------- +// Block read - if your platform needs to do endian-swapping or can only +// handle aligned reads, do the conversion here + +inline u64 getblock(const u64 * p, int i) +{ + return p[i]; +} + +//---------- +// Block mix - combine the key bits with the hash bits and scramble everything + +inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2) +{ + k1 *= c1; + k1 = _rotl64(k1,23); + k1 *= c2; + h1 ^= k1; + h1 += h2; + + h2 = _rotl64(h2,41); + + k2 *= c2; + k2 = _rotl64(k2,23); + k2 *= c1; + h2 ^= k2; + h2 += h1; + + h1 = h1*3+0x52dce729; + h2 = h2*3+0x38495ab5; + + c1 = c1*5+0x7b7d159c; + c2 = c2*5+0x6bce6396; +} + +//---------- +// Finalization mix - avalanches all bits to within 0.05% bias + +inline u64 fmix64(u64 k) +{ + k ^= k >> 33; + k *= 0xff51afd7ed558ccd; + k ^= k >> 33; + k *= 0xc4ceb9fe1a85ec53; + k ^= k >> 33; + + return k; +} + +u64 GetMurmurHash3(const u8 *src, int len, u32 samples) +{ + const u8 * data = (const u8*)src; + const int nblocks = len / 16; + u32 Step = (len / 8); + if(samples == 0) samples = max(Step, 1u); + Step = Step / samples; + if(Step < 1) Step = 1; + + u64 h1 = 0x9368e53c2f6af274; + u64 h2 = 0x586dcd208f7cd3fd; + + u64 c1 = 0x87c37b91114253d5; + u64 c2 = 0x4cf5ad432745937f; + + + //---------- + // body + + const u64 * blocks = (const u64 *)(data); + + for(int i = 0; i < nblocks; i+=Step) + { + u64 k1 = getblock(blocks,i*2+0); + u64 k2 = getblock(blocks,i*2+1); + + bmix64(h1,h2,k1,k2,c1,c2); + } + + //---------- + // tail + + const u8 * tail = (const u8*)(data + nblocks*16); + + u64 k1 = 0; + u64 k2 = 0; + + switch(len & 15) + { + case 15: k2 ^= u64(tail[14]) << 48; + case 14: k2 ^= u64(tail[13]) << 40; + case 13: k2 ^= u64(tail[12]) << 32; + case 12: k2 ^= u64(tail[11]) << 24; + case 11: k2 ^= u64(tail[10]) << 16; + case 10: k2 ^= u64(tail[ 9]) << 8; + case 9: k2 ^= u64(tail[ 8]) << 0; + + case 8: k1 ^= u64(tail[ 7]) << 56; + case 7: k1 ^= u64(tail[ 6]) << 48; + case 6: k1 ^= u64(tail[ 5]) << 40; + case 5: k1 ^= u64(tail[ 4]) << 32; + case 4: k1 ^= u64(tail[ 3]) << 24; + case 3: k1 ^= u64(tail[ 2]) << 16; + case 2: k1 ^= u64(tail[ 1]) << 8; + case 1: k1 ^= u64(tail[ 0]) << 0; + bmix64(h1,h2,k1,k2,c1,c2); + }; + + //---------- + // finalization + + h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = fmix64(h1); + h2 = fmix64(h2); + + h1 += h2; + + return h1; +} + + +// CRC32 hash using the SSE4.2 instruction +u64 GetCRC32(const u8 *src, int len, u32 samples) +{ +#if _M_SSE >= 0x402 + u64 h = len; + u32 Step = (len / 8); + const u64 *data = (const u64 *)src; + const u64 *end = data + Step; + if(samples == 0) samples = max(Step, 1u); + Step = Step / samples; + if(Step < 1) Step = 1; + while(data < end) + { + h = _mm_crc32_u64(h, data[0]); + data += Step; + } + + const u8 *data2 = (const u8*)end; + return _mm_crc32_u64(h, u64(data2[0])); +#else + return 0; +#endif +} + + +/* + * NOTE: This hash function is used for custom texture loading/dumping, so + * it should not be changed, which would require all custom textures to be + * recalculated for their new hash values. If the hashing function is + * changed, make sure this one is still used when the legacy parameter is + * true. + */ +u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) +{ + const u64 m = 0xc6a4a7935bd1e995; + u64 h = len * m; + const int r = 47; + u32 Step = (len / 8); + const u64 *data = (const u64 *)src; + const u64 *end = data + Step; + if(samples == 0) samples = max(Step, 1u); + Step = Step / samples; + if(Step < 1) Step = 1; + while(data < end) + { + u64 k = data[0]; + data+=Step; + k *= m; + k ^= k >> r; + k *= m; + h ^= k; + h *= m; + } + + const u8 * data2 = (const u8*)end; + + switch(len & 7) + { + case 7: h ^= u64(data2[6]) << 48; + case 6: h ^= u64(data2[5]) << 40; + case 5: h ^= u64(data2[4]) << 32; + case 4: h ^= u64(data2[3]) << 24; + case 3: h ^= u64(data2[2]) << 16; + case 2: h ^= u64(data2[1]) << 8; + case 1: h ^= u64(data2[0]); + h *= m; + }; + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return h; +} +#else +// CRC32 hash using the SSE4.2 instruction +u64 GetCRC32(const u8 *src, int len, u32 samples) +{ +#if _M_SSE >= 0x402 + u32 h = len; + u32 Step = (len/4); + const u32 *data = (const u32 *)src; + const u32 *end = data + Step; + if(samples == 0) samples = max(Step, 1u); + Step = Step / samples; + if(Step < 1) Step = 1; + while(data < end) + { + h = _mm_crc32_u32(h, data[0]); + data += Step; + } + + const u8 *data2 = (const u8*)end; + return (u64)_mm_crc32_u32(h, u32(data2[0])); +#else + return 0; +#endif +} + +//----------------------------------------------------------------------------- +// Block read - if your platform needs to do endian-swapping or can only +// handle aligned reads, do the conversion here + +inline u32 getblock(const u32 * p, int i) +{ + return p[i]; +} + +//---------- +// Finalization mix - force all bits of a hash block to avalanche + +// avalanches all bits to within 0.25% bias + +inline u32 fmix32(u32 h) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + +inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2) +{ + k1 *= c1; + k1 = _rotl(k1,11); + k1 *= c2; + h1 ^= k1; + h1 += h2; + + h2 = _rotl(h2,17); + + k2 *= c2; + k2 = _rotl(k2,11); + k2 *= c1; + h2 ^= k2; + h2 += h1; + + h1 = h1*3+0x52dce729; + h2 = h2*3+0x38495ab5; + + c1 = c1*5+0x7b7d159c; + c2 = c2*5+0x6bce6396; +} + +//---------- + +u64 GetMurmurHash3(const u8* src, int len, u32 samples) +{ + const u8 * data = (const u8*)src; + u32 out[2]; + const int nblocks = len / 8; + u32 Step = (len / 4); + if(samples == 0) samples = max(Step, 1u); + Step = Step / samples; + if(Step < 1) Step = 1; + + u32 h1 = 0x8de1c3ac; + u32 h2 = 0xbab98226; + + u32 c1 = 0x95543787; + u32 c2 = 0x2ad7eb25; + + //---------- + // body + + const u32 * blocks = (const u32 *)(data + nblocks*8); + + for(int i = -nblocks; i < 0; i+=Step) + { + u32 k1 = getblock(blocks,i*2+0); + u32 k2 = getblock(blocks,i*2+1); + + bmix32(h1,h2,k1,k2,c1,c2); + } + + //---------- + // tail + + const u8 * tail = (const u8*)(data + nblocks*8); + + u32 k1 = 0; + u32 k2 = 0; + + switch(len & 7) + { + case 7: k2 ^= tail[6] << 16; + case 6: k2 ^= tail[5] << 8; + case 5: k2 ^= tail[4] << 0; + case 4: k1 ^= tail[3] << 24; + case 3: k1 ^= tail[2] << 16; + case 2: k1 ^= tail[1] << 8; + case 1: k1 ^= tail[0] << 0; + bmix32(h1,h2,k1,k2,c1,c2); + }; + + //---------- + // finalization + + h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = fmix32(h1); + h2 = fmix32(h2); + + h1 += h2; + h2 += h1; + + out[0] = h1; + out[1] = h2; + + return *((u64 *)&out); +} + +/* + * FIXME: The old 32-bit version of this hash made different hashes than the + * 64-bit version. Until someone can make a new version of the 32-bit one that + * makes identical hashes, this is just a c/p of the 64-bit one. + */ +u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) +{ + const u64 m = 0xc6a4a7935bd1e995ULL; + u64 h = len * m; + const int r = 47; + u32 Step = (len / 8); + const u64 *data = (const u64 *)src; + const u64 *end = data + Step; + if(samples == 0) samples = max(Step, 1u); + Step = Step / samples; + if(Step < 1) Step = 1; + while(data < end) + { + u64 k = data[0]; + data+=Step; + k *= m; + k ^= k >> r; + k *= m; + h ^= k; + h *= m; + } + + const u8 * data2 = (const u8*)end; + + switch(len & 7) + { + case 7: h ^= u64(data2[6]) << 48; + case 6: h ^= u64(data2[5]) << 40; + case 5: h ^= u64(data2[4]) << 32; + case 4: h ^= u64(data2[3]) << 24; + case 3: h ^= u64(data2[2]) << 16; + case 2: h ^= u64(data2[1]) << 8; + case 1: h ^= u64(data2[0]); + h *= m; + }; + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return h; +} +#endif + +u64 GetHash64(const u8 *src, int len, u32 samples) +{ + return ptrHashFunction(src, len, samples); +} + +// sets the hash function used for the texture cache +void SetHash64Function(bool useHiresTextures) +{ + if (useHiresTextures) + { + ptrHashFunction = &GetHashHiresTexture; + } +#if _M_SSE >= 0x402 + else if (cpu_info.bSSE4_2 && !useHiresTextures) // sse crc32 version + { + ptrHashFunction = &GetCRC32; + } +#endif + else + { + ptrHashFunction = &GetMurmurHash3; + } +} + + + -- cgit v1.2.3 From 2afe2152712981e21d6bda6f029292ed2b1cf91e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 17 Feb 2014 05:18:15 -0500 Subject: Convert all includes to relative paths. --- Source/Core/Common/Hash.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index ab017347e8..df1010c419 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -3,9 +3,9 @@ // Refer to the license.txt file included. -#include "Hash.h" +#include "Common/Hash.h" #if _M_SSE >= 0x402 -#include "CPUDetect.h" +#include "Common/CPUDetect.h" #include #endif -- cgit v1.2.3 From 4f02132f9323a147c68b7dc1a79a62be33c1f170 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 2 Mar 2014 05:21:50 -0600 Subject: Make our architecture defines less stupid. Our defines were never clear between what meant 64bit or x86_64 This makes a clear cut between bitness and architecture. This commit also has the side effect of bringing up aarch64 compiling support. --- Source/Core/Common/Hash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index df1010c419..f9a6d6fd4d 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -99,7 +99,7 @@ u32 HashEctor(const u8* ptr, int length) } -#ifdef _M_X64 +#if _ARCH_64 //----------------------------------------------------------------------------- // Block read - if your platform needs to do endian-swapping or can only -- cgit v1.2.3 From 31cfc73a09a8685cbab20502b4bc132e98e2feb5 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Tue, 11 Mar 2014 00:30:55 +1300 Subject: Fixes spacing for "for", "while", "switch" and "if" Also moved && and || to ends of lines instead of start. Fixed misc vertical alignments and some { needed newlining. --- Source/Core/Common/Hash.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index f9a6d6fd4d..f7ed8f308f 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -155,9 +155,9 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) const u8 * data = (const u8*)src; const int nblocks = len / 16; u32 Step = (len / 8); - if(samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = max(Step, 1u); Step = Step / samples; - if(Step < 1) Step = 1; + if (Step < 1) Step = 1; u64 h1 = 0x9368e53c2f6af274; u64 h2 = 0x586dcd208f7cd3fd; @@ -171,7 +171,7 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) const u64 * blocks = (const u64 *)(data); - for(int i = 0; i < nblocks; i+=Step) + for (int i = 0; i < nblocks; i+=Step) { u64 k1 = getblock(blocks,i*2+0); u64 k2 = getblock(blocks,i*2+1); @@ -187,7 +187,7 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) u64 k1 = 0; u64 k2 = 0; - switch(len & 15) + switch (len & 15) { case 15: k2 ^= u64(tail[14]) << 48; case 14: k2 ^= u64(tail[13]) << 40; @@ -233,10 +233,10 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = max(Step, 1u); Step = Step / samples; - if(Step < 1) Step = 1; - while(data < end) + if (Step < 1) Step = 1; + while (data < end) { h = _mm_crc32_u64(h, data[0]); data += Step; @@ -265,10 +265,10 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = max(Step, 1u); Step = Step / samples; - if(Step < 1) Step = 1; - while(data < end) + if (Step < 1) Step = 1; + while (data < end) { u64 k = data[0]; data+=Step; @@ -281,7 +281,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) const u8 * data2 = (const u8*)end; - switch(len & 7) + switch (len & 7) { case 7: h ^= u64(data2[6]) << 48; case 6: h ^= u64(data2[5]) << 40; @@ -308,10 +308,10 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) u32 Step = (len/4); const u32 *data = (const u32 *)src; const u32 *end = data + Step; - if(samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = max(Step, 1u); Step = Step / samples; - if(Step < 1) Step = 1; - while(data < end) + if (Step < 1) Step = 1; + while (data < end) { h = _mm_crc32_u32(h, data[0]); data += Step; @@ -380,9 +380,9 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) u32 out[2]; const int nblocks = len / 8; u32 Step = (len / 4); - if(samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = max(Step, 1u); Step = Step / samples; - if(Step < 1) Step = 1; + if (Step < 1) Step = 1; u32 h1 = 0x8de1c3ac; u32 h2 = 0xbab98226; @@ -395,7 +395,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) const u32 * blocks = (const u32 *)(data + nblocks*8); - for(int i = -nblocks; i < 0; i+=Step) + for (int i = -nblocks; i < 0; i+=Step) { u32 k1 = getblock(blocks,i*2+0); u32 k2 = getblock(blocks,i*2+1); @@ -411,7 +411,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) u32 k1 = 0; u32 k2 = 0; - switch(len & 7) + switch (len & 7) { case 7: k2 ^= tail[6] << 16; case 6: k2 ^= tail[5] << 8; @@ -456,10 +456,10 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if(samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = max(Step, 1u); Step = Step / samples; - if(Step < 1) Step = 1; - while(data < end) + if (Step < 1) Step = 1; + while (data < end) { u64 k = data[0]; data+=Step; @@ -472,7 +472,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) const u8 * data2 = (const u8*)end; - switch(len & 7) + switch (len & 7) { case 7: h ^= u64(data2[6]) << 48; case 6: h ^= u64(data2[5]) << 40; -- cgit v1.2.3 From 49b0eef393f4d321928fb0b6093d58a7637cf1da Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 2 May 2014 22:47:04 -0400 Subject: Remove the min/max functions in CommonFuncs. The algorithm header has the same functions. --- Source/Core/Common/Hash.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index f7ed8f308f..e346dba796 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 // Refer to the license.txt file included. - +#include #include "Common/Hash.h" #if _M_SSE >= 0x402 #include "Common/CPUDetect.h" @@ -155,7 +155,7 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) const u8 * data = (const u8*)src; const int nblocks = len / 16; u32 Step = (len / 8); - if (samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = std::max(Step, 1u); Step = Step / samples; if (Step < 1) Step = 1; @@ -233,7 +233,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if (samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = std::max(Step, 1u); Step = Step / samples; if (Step < 1) Step = 1; while (data < end) @@ -265,7 +265,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if (samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = std::max(Step, 1u); Step = Step / samples; if (Step < 1) Step = 1; while (data < end) @@ -308,7 +308,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) u32 Step = (len/4); const u32 *data = (const u32 *)src; const u32 *end = data + Step; - if (samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = std::max(Step, 1u); Step = Step / samples; if (Step < 1) Step = 1; while (data < end) @@ -380,7 +380,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) u32 out[2]; const int nblocks = len / 8; u32 Step = (len / 4); - if (samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = std::max(Step, 1u); Step = Step / samples; if (Step < 1) Step = 1; @@ -456,7 +456,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if (samples == 0) samples = max(Step, 1u); + if (samples == 0) samples = std::max(Step, 1u); Step = Step / samples; if (Step < 1) Step = 1; while (data < end) -- cgit v1.2.3 From 46057db37d086c47ff6c69f200f66648fa0e6c84 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Thu, 18 Sep 2014 23:17:41 -0500 Subject: Fix build failing when disabling precompiled headers. --- Source/Core/Common/Hash.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index e346dba796..efe782caf5 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include "Common/CommonFuncs.h" #include "Common/Hash.h" #if _M_SSE >= 0x402 #include "Common/CPUDetect.h" -- cgit v1.2.3 From 15a4bccb7333d0d4979c5574e30e745fd3654d95 Mon Sep 17 00:00:00 2001 From: Fiora Date: Thu, 16 Oct 2014 18:15:27 -0700 Subject: Hash: unroll CRC loop, since CRC32 typically has nontrivial latency Seems to be about 20-30% faster texture cache hashing on my machine. --- Source/Core/Common/Hash.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index efe782caf5..6cdd1e6a7a 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -230,21 +230,31 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) u64 GetCRC32(const u8 *src, int len, u32 samples) { #if _M_SSE >= 0x402 - u64 h = len; + u64 h[4] = { len, 0, 0, 0 }; u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; if (samples == 0) samples = std::max(Step, 1u); Step = Step / samples; if (Step < 1) Step = 1; - while (data < end) + while (data < end - Step * 3) { - h = _mm_crc32_u64(h, data[0]); - data += Step; + h[0] = _mm_crc32_u64(h[0], data[Step * 0]); + h[1] = _mm_crc32_u64(h[1], data[Step * 1]); + h[2] = _mm_crc32_u64(h[2], data[Step * 2]); + h[3] = _mm_crc32_u64(h[3], data[Step * 3]); + data += Step * 4; } + if (data < end - Step * 0) + h[0] = _mm_crc32_u64(h[0], data[Step * 0]); + if (data < end - Step * 1) + h[1] = _mm_crc32_u64(h[1], data[Step * 1]); + if (data < end - Step * 2) + h[2] = _mm_crc32_u64(h[2], data[Step * 2]); const u8 *data2 = (const u8*)end; - return _mm_crc32_u64(h, u64(data2[0])); + // FIXME: is there a better way to combine these partial hashes? + return _mm_crc32_u64(h[0] + h[1] + h[2] + h[3], u64(data2[0])); #else return 0; #endif -- cgit v1.2.3 From d2e004fa9e8b4f331e7e241645e47211e93686eb Mon Sep 17 00:00:00 2001 From: Fiora Date: Sat, 18 Oct 2014 00:22:41 -0700 Subject: Use CRC to output 64 bits instead of 32 A bit hacky, but should dramatically reduce the odds of hash collision. --- Source/Core/Common/Hash.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index 6cdd1e6a7a..f9a3737d34 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -254,7 +254,8 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) const u8 *data2 = (const u8*)end; // FIXME: is there a better way to combine these partial hashes? - return _mm_crc32_u64(h[0] + h[1] + h[2] + h[3], u64(data2[0])); + h[0] = _mm_crc32_u64(h[0], u64(data2[0])); + return h[0] + (h[1] << 10) + (h[2] << 21) + (h[3] << 32); #else return 0; #endif -- cgit v1.2.3 From c6dd5044d6accb22441893afaa1338b0c93b769d Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 22 Dec 2014 22:35:08 +0100 Subject: VideoCommon: make hash independet from hires textures --- Source/Core/Common/Hash.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index f9a3737d34..973e30da02 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -510,19 +510,15 @@ u64 GetHash64(const u8 *src, int len, u32 samples) } // sets the hash function used for the texture cache -void SetHash64Function(bool useHiresTextures) +void SetHash64Function() { - if (useHiresTextures) - { - ptrHashFunction = &GetHashHiresTexture; - } #if _M_SSE >= 0x402 - else if (cpu_info.bSSE4_2 && !useHiresTextures) // sse crc32 version + if (cpu_info.bSSE4_2) // sse crc32 version { ptrHashFunction = &GetCRC32; } -#endif else +#endif { ptrHashFunction = &GetMurmurHash3; } -- cgit v1.2.3 From 1c388b6c37fd64287c41463febe22c9739a6dacf Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 29 Jan 2015 01:55:20 -0600 Subject: Fix clang on x86_64. If we are compiling in the CRC32 hash, clang has an issue with casting a s32 to a u64. Change our lens argument to a unsigned integer to fix the issue. --- Source/Core/Common/Hash.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index 973e30da02..4a0df743be 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -10,7 +10,7 @@ #include #endif -static u64 (*ptrHashFunction)(const u8 *src, int len, u32 samples) = &GetMurmurHash3; +static u64 (*ptrHashFunction)(const u8 *src, u32 len, u32 samples) = &GetMurmurHash3; // uint32_t // WARNING - may read one more byte! @@ -151,7 +151,7 @@ inline u64 fmix64(u64 k) return k; } -u64 GetMurmurHash3(const u8 *src, int len, u32 samples) +u64 GetMurmurHash3(const u8 *src, u32 len, u32 samples) { const u8 * data = (const u8*)src; const int nblocks = len / 16; @@ -227,7 +227,7 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples) // CRC32 hash using the SSE4.2 instruction -u64 GetCRC32(const u8 *src, int len, u32 samples) +u64 GetCRC32(const u8 *src, u32 len, u32 samples) { #if _M_SSE >= 0x402 u64 h[4] = { len, 0, 0, 0 }; @@ -269,7 +269,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) * changed, make sure this one is still used when the legacy parameter is * true. */ -u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) +u64 GetHashHiresTexture(const u8 *src, u32 len, u32 samples) { const u64 m = 0xc6a4a7935bd1e995; u64 h = len * m; @@ -313,7 +313,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) } #else // CRC32 hash using the SSE4.2 instruction -u64 GetCRC32(const u8 *src, int len, u32 samples) +u64 GetCRC32(const u8 *src, u32 len, u32 samples) { #if _M_SSE >= 0x402 u32 h = len; @@ -386,7 +386,7 @@ inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2) //---------- -u64 GetMurmurHash3(const u8* src, int len, u32 samples) +u64 GetMurmurHash3(const u8* src, u32 len, u32 samples) { const u8 * data = (const u8*)src; u32 out[2]; @@ -460,7 +460,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) * 64-bit version. Until someone can make a new version of the 32-bit one that * makes identical hashes, this is just a c/p of the 64-bit one. */ -u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) +u64 GetHashHiresTexture(const u8 *src, u32 len, u32 samples) { const u64 m = 0xc6a4a7935bd1e995ULL; u64 h = len * m; @@ -504,7 +504,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) } #endif -u64 GetHash64(const u8 *src, int len, u32 samples) +u64 GetHash64(const u8 *src, u32 len, u32 samples) { return ptrHashFunction(src, len, samples); } -- cgit v1.2.3 From f6c9b8243e719f6e3ee632fc1b9bf54bfbcbf76c Mon Sep 17 00:00:00 2001 From: mimimi085181 Date: Tue, 17 Feb 2015 22:34:45 +0100 Subject: GetCRC32: Fix the hash for the last byte(s) This fixes issue 8227 https://code.google.com/p/dolphin-emu/issues/detail?id=8227 --- Source/Core/Common/Hash.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index 4a0df743be..63caced040 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -252,9 +252,14 @@ u64 GetCRC32(const u8 *src, u32 len, u32 samples) if (data < end - Step * 2) h[2] = _mm_crc32_u64(h[2], data[Step * 2]); - const u8 *data2 = (const u8*)end; + if (len & 7) + { + u64 temp = 0; + memcpy(&temp, end, len & 7); + h[0] = _mm_crc32_u64(h[0], temp); + } + // FIXME: is there a better way to combine these partial hashes? - h[0] = _mm_crc32_u64(h[0], u64(data2[0])); return h[0] + (h[1] << 10) + (h[2] << 21) + (h[3] << 32); #else return 0; -- cgit v1.2.3 From f298f00e1b3dfd14eeeac65524c9703f0758fa5a Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Mon, 23 Feb 2015 20:40:05 +0100 Subject: Clean up the intrinsics #ifdef mess --- Source/Core/Common/Hash.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index 63caced040..7efc4549d7 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -4,11 +4,9 @@ #include #include "Common/CommonFuncs.h" -#include "Common/Hash.h" -#if _M_SSE >= 0x402 #include "Common/CPUDetect.h" -#include -#endif +#include "Common/Hash.h" +#include "Common/Intrinsics.h" static u64 (*ptrHashFunction)(const u8 *src, u32 len, u32 samples) = &GetMurmurHash3; -- cgit v1.2.3 From 93b16a4a2d5f3e6d467d1315c461aff12852b26c Mon Sep 17 00:00:00 2001 From: Stevoisiak Date: Sun, 15 Feb 2015 14:43:31 -0500 Subject: Formatting/Whitespace Cleanup Various fixes to formatting and whitespace --- Source/Core/Common/Hash.cpp | 81 +++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 35 deletions(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index 7efc4549d7..4aeb802336 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -24,11 +24,11 @@ u32 HashFletcher(const u8* data_u8, size_t length) size_t tlen = len > 360 ? 360 : len; len -= tlen; - do { + do + { sum1 += *data++; sum2 += sum1; - } - while (--tlen); + } while (--tlen); sum1 = (sum1 & 0xffff) + (sum1 >> 16); sum2 = (sum2 & 0xffff) + (sum2 >> 16); @@ -58,8 +58,7 @@ u32 HashAdler32(const u8* data, size_t len) { a += *data++; b += a; - } - while (--tlen); + } while (--tlen); a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER); b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); @@ -115,24 +114,24 @@ inline u64 getblock(const u64 * p, int i) inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2) { k1 *= c1; - k1 = _rotl64(k1,23); + k1 = _rotl64(k1, 23); k1 *= c2; h1 ^= k1; h1 += h2; - h2 = _rotl64(h2,41); + h2 = _rotl64(h2, 41); k2 *= c2; - k2 = _rotl64(k2,23); + k2 = _rotl64(k2, 23); k2 *= c1; h2 ^= k2; h2 += h1; - h1 = h1*3+0x52dce729; - h2 = h2*3+0x38495ab5; + h1 = h1 * 3 + 0x52dce729; + h2 = h2 * 3 + 0x38495ab5; - c1 = c1*5+0x7b7d159c; - c2 = c2*5+0x6bce6396; + c1 = c1 * 5 + 0x7b7d159c; + c2 = c2 * 5 + 0x6bce6396; } //---------- @@ -154,9 +153,11 @@ u64 GetMurmurHash3(const u8 *src, u32 len, u32 samples) const u8 * data = (const u8*)src; const int nblocks = len / 16; u32 Step = (len / 8); - if (samples == 0) samples = std::max(Step, 1u); + if (samples == 0) + samples = std::max(Step, 1u); Step = Step / samples; - if (Step < 1) Step = 1; + if (Step < 1) + Step = 1; u64 h1 = 0x9368e53c2f6af274; u64 h2 = 0x586dcd208f7cd3fd; @@ -172,8 +173,8 @@ u64 GetMurmurHash3(const u8 *src, u32 len, u32 samples) for (int i = 0; i < nblocks; i+=Step) { - u64 k1 = getblock(blocks,i*2+0); - u64 k2 = getblock(blocks,i*2+1); + u64 k1 = getblock(blocks, i*2+0); + u64 k2 = getblock(blocks, i*2+1); bmix64(h1,h2,k1,k2,c1,c2); } @@ -232,9 +233,11 @@ u64 GetCRC32(const u8 *src, u32 len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if (samples == 0) samples = std::max(Step, 1u); + if (samples == 0) + samples = std::max(Step, 1u); Step = Step / samples; - if (Step < 1) Step = 1; + if (Step < 1) + Step = 1; while (data < end - Step * 3) { h[0] = _mm_crc32_u64(h[0], data[Step * 0]); @@ -280,9 +283,11 @@ u64 GetHashHiresTexture(const u8 *src, u32 len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if (samples == 0) samples = std::max(Step, 1u); + if (samples == 0) + samples = std::max(Step, 1u); Step = Step / samples; - if (Step < 1) Step = 1; + if (Step < 1) + Step = 1; while (data < end) { u64 k = data[0]; @@ -323,9 +328,11 @@ u64 GetCRC32(const u8 *src, u32 len, u32 samples) u32 Step = (len/4); const u32 *data = (const u32 *)src; const u32 *end = data + Step; - if (samples == 0) samples = std::max(Step, 1u); + if (samples == 0) + samples = std::max(Step, 1u); Step = Step / samples; - if (Step < 1) Step = 1; + if (Step < 1) + Step = 1; while (data < end) { h = _mm_crc32_u32(h, data[0]); @@ -367,24 +374,24 @@ inline u32 fmix32(u32 h) inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2) { k1 *= c1; - k1 = _rotl(k1,11); + k1 = _rotl(k1, 11); k1 *= c2; h1 ^= k1; h1 += h2; - h2 = _rotl(h2,17); + h2 = _rotl(h2, 17); k2 *= c2; - k2 = _rotl(k2,11); + k2 = _rotl(k2, 11); k2 *= c1; h2 ^= k2; h2 += h1; - h1 = h1*3+0x52dce729; - h2 = h2*3+0x38495ab5; + h1 = h1*3+0x52dce729; + h2 = h2*3+0x38495ab5; - c1 = c1*5+0x7b7d159c; - c2 = c2*5+0x6bce6396; + c1 = c1*5+0x7b7d159c; + c2 = c2*5+0x6bce6396; } //---------- @@ -395,9 +402,11 @@ u64 GetMurmurHash3(const u8* src, u32 len, u32 samples) u32 out[2]; const int nblocks = len / 8; u32 Step = (len / 4); - if (samples == 0) samples = std::max(Step, 1u); + if (samples == 0) + samples = std::max(Step, 1u); Step = Step / samples; - if (Step < 1) Step = 1; + if (Step < 1) + Step = 1; u32 h1 = 0x8de1c3ac; u32 h2 = 0xbab98226; @@ -446,8 +455,8 @@ u64 GetMurmurHash3(const u8* src, u32 len, u32 samples) h1 += h2; h2 += h1; - h1 = fmix32(h1); - h2 = fmix32(h2); + h1 = fmix32(h1); + h2 = fmix32(h2); h1 += h2; h2 += h1; @@ -471,9 +480,11 @@ u64 GetHashHiresTexture(const u8 *src, u32 len, u32 samples) u32 Step = (len / 8); const u64 *data = (const u64 *)src; const u64 *end = data + Step; - if (samples == 0) samples = std::max(Step, 1u); + if (samples == 0) + samples = std::max(Step, 1u); Step = Step / samples; - if (Step < 1) Step = 1; + if (Step < 1) + Step = 1; while (data < end) { u64 k = data[0]; -- cgit v1.2.3 From cefcb0ace9d363b3679b4e93bcc9ec05f1e5f4f8 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Mon, 18 May 2015 01:08:10 +0200 Subject: Update license headers to GPLv2+ --- Source/Core/Common/Hash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index 4aeb802336..9836db93e8 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -1,5 +1,5 @@ // Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 +// Licensed under GPLv2+ // Refer to the license.txt file included. #include -- cgit v1.2.3 From 30ebb2459eb97ba544547183854775df8460b475 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sun, 24 May 2015 06:55:12 +0200 Subject: Set copyright year to when a file was created --- Source/Core/Common/Hash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index 9836db93e8..844dd31f35 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -1,4 +1,4 @@ -// Copyright 2013 Dolphin Emulator Project +// Copyright 2008 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. -- cgit v1.2.3 From ffe085f5eaf0546018bdda342c4ce2753e4016f6 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 8 Jun 2015 01:21:04 -0500 Subject: [AArch64] Implement CRC32 texture hashing. In a particular hashing heavy scene in Crazy Taxi the Murmur3 hash used 3.11% CPU time. The new CRC32 hash in the same scene used 1.86% This was tested on a Nvidia SHIELD Android TV with Cortex-A57s. This will be a bit slower on the Nexus 9, the Denver CPU core is a bit slower with CRC32 texture hashing than Murmur3 texture hashing. --- Source/Core/Common/Hash.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'Source/Core/Common/Hash.cpp') diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index 844dd31f35..868de4e68f 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -228,7 +228,7 @@ u64 GetMurmurHash3(const u8 *src, u32 len, u32 samples) // CRC32 hash using the SSE4.2 instruction u64 GetCRC32(const u8 *src, u32 len, u32 samples) { -#if _M_SSE >= 0x402 +#if _M_SSE >= 0x402 || defined(_M_ARM_64) u64 h[4] = { len, 0, 0, 0 }; u32 Step = (len / 8); const u64 *data = (const u64 *)src; @@ -238,6 +238,9 @@ u64 GetCRC32(const u8 *src, u32 len, u32 samples) Step = Step / samples; if (Step < 1) Step = 1; +#endif + +#if _M_SSE >= 0x402 while (data < end - Step * 3) { h[0] = _mm_crc32_u64(h[0], data[Step * 0]); @@ -259,12 +262,66 @@ u64 GetCRC32(const u8 *src, u32 len, u32 samples) memcpy(&temp, end, len & 7); h[0] = _mm_crc32_u64(h[0], temp); } +#elif defined(_M_ARM_64) + // We should be able to use intrinsics for this + // Too bad the intrinsics for this instruction was added in GCC 4.9.1 + // The Android NDK (as of r10e) only has GCC 4.9 + // Once the Android NDK has a newer GCC version, update these to use intrinsics + while (data < end - Step * 3) + { + asm ("crc32x %w[res], %w[two], %x[three]" + : [res] "=r" (h[0]) + : [two] "r" (h[0]), + [three] "r" (data[Step * 0])); + asm ("crc32x %w[res], %w[two], %x[three]" + : [res] "=r" (h[1]) + : [two] "r" (h[1]), + [three] "r" (data[Step * 1])); + asm ("crc32x %w[res], %w[two], %x[three]" + : [res] "=r" (h[2]) + : [two] "r" (h[2]), + [three] "r" (data[Step * 2])); + asm ("crc32x %w[res], %w[two], %x[three]" + : [res] "=r" (h[3]) + : [two] "r" (h[3]), + [three] "r" (data[Step * 3])); + + data += Step * 4; + } + if (data < end - Step * 0) + asm ("crc32x %w[res], %w[two], %x[three]" + : [res] "=r" (h[0]) + : [two] "r" (h[0]), + [three] "r" (data[Step * 0])); + if (data < end - Step * 1) + asm ("crc32x %w[res], %w[two], %x[three]" + : [res] "=r" (h[1]) + : [two] "r" (h[1]), + [three] "r" (data[Step * 1])); + if (data < end - Step * 2) + asm ("crc32x %w[res], %w[two], %x[three]" + : [res] "=r" (h[2]) + : [two] "r" (h[2]), + [three] "r" (data[Step * 2])); + + if (len & 7) + { + u64 temp = 0; + memcpy(&temp, end, len & 7); + asm ("crc32x %w[res], %w[two], %x[three]" + : [res] "=r" (h[0]) + : [two] "r" (h[0]), + [three] "r" (temp)); + } +#endif +#if _M_SSE >= 0x402 || defined(_M_ARM_64) // FIXME: is there a better way to combine these partial hashes? return h[0] + (h[1] << 10) + (h[2] << 21) + (h[3] << 32); #else return 0; #endif + } @@ -532,6 +589,12 @@ void SetHash64Function() ptrHashFunction = &GetCRC32; } else +#elif defined(_M_ARM_64) + if (cpu_info.bCRC32) + { + ptrHashFunction = &GetCRC32; + } + else #endif { ptrHashFunction = &GetMurmurHash3; -- cgit v1.2.3