summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Hash.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/Common/Hash.cpp')
-rw-r--r--Source/Core/Common/Hash.cpp20
1 files changed, 15 insertions, 5 deletions
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