You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <immintrin.h>
#define MIX(x) do { \
m = m; \
a = _mm_aesenc_si128(x, a); \
a = _mm_aesenc_si128(a, m); \
b = _mm_shuffle_epi8(_mm_xor_si128(x, b), s); \
b = _mm_shuffle_epi8(_mm_aesdec_si128(b, m), s); \
} while (0)
__m128i AESNI_Hash128(const uint8_t* msg, unsigned len, uint32_t seed) {
__m128i a = _mm_set1_epi32(seed);
__m128i b = _mm_set1_epi32(len);
__m128i m = _mm_set_epi32(0xdeadbeef, 0xffff0000, 0x01234567, 0x89abcdef);
__m128i s = _mm_set_epi8(3, 7, 11, 15, 2, 6, 10, 14, 1, 5, 9, 13, 0, 4, 8, 12);
bool greed = (((uintptr_t)msg + (len-1)) & 0xfffUL) >= 15; // do not cross page
if (len > 80) {
__m128i c = _mm_aesenc_si128(b, m);
__m128i d = _mm_aesdec_si128(a, m);
a = _mm_aesenc_si128(a, m);
b = _mm_aesdec_si128(b, m);
do {
a = _mm_xor_si128(a, _mm_lddqu_si128((const __m128i*)msg));
b = _mm_xor_si128(b, _mm_lddqu_si128((const __m128i*)(msg + 16)));
c = _mm_xor_si128(c, _mm_lddqu_si128((const __m128i*)(msg + 32)));
d = _mm_xor_si128(d, _mm_lddqu_si128((const __m128i*)(msg + 48)));
a = _mm_shuffle_epi8(_mm_aesenc_si128(a, m), s);
b = _mm_shuffle_epi8(_mm_aesdec_si128(b, m), s);
c = _mm_shuffle_epi8(_mm_aesenc_si128(c, m), s);
d = _mm_shuffle_epi8(_mm_aesdec_si128(d, m), s);
msg += 64;
len -= 64;
} while (len > 80);
c = _mm_aesenc_si128(a, c);
d = _mm_aesdec_si128(b, d);
a = _mm_aesenc_si128(c, d);
b = _mm_aesdec_si128(d, c);
}
while (len >= 16) {
MIX(_mm_lddqu_si128((const __m128i*)msg));
msg += 16;
len -= 16;
}
if (greed) {
#define GREEDILY_READ(n, addr) \
_mm_bsrli_si128(_mm_bslli_si128(_mm_lddqu_si128((const __m128i*)addr), (16-(n))), (16-(n)))
switch (len) {
case 15: MIX(GREEDILY_READ(15,msg)); break;
case 14: MIX(GREEDILY_READ(14,msg)); break;
case 13: MIX(GREEDILY_READ(13,msg)); break;
case 12: MIX(GREEDILY_READ(12,msg)); break;
case 11: MIX(GREEDILY_READ(11,msg)); break;
case 10: MIX(GREEDILY_READ(10,msg)); break;
case 9: MIX(GREEDILY_READ(9,msg)); break;
case 8: MIX((__m128i)_mm_load_sd((const double*)msg)); break;
case 7: MIX(GREEDILY_READ(7,msg)); break;
case 6: MIX(GREEDILY_READ(6,msg)); break;
case 5: MIX(GREEDILY_READ(5,msg)); break;
case 4: MIX((__m128i)_mm_load_ss((const float*)msg)); break;
case 3: MIX(GREEDILY_READ(3,msg)); break;
case 2: MIX(GREEDILY_READ(2,msg)); break;
case 1: MIX(GREEDILY_READ(1,msg)); break;
case 0:
default: // try to keep m & s from register spilling
a = _mm_add_epi8(a, s);
b = _mm_add_epi8(b, m);
}
#undef GREEDILY_READ
return _mm_aesenc_si128(a, b);
}
uint64_t x = 0;
switch (len) {
case 15:
x |= ((uint64_t)msg[14]) << 48U;
case 14:
x |= ((uint64_t)msg[13]) << 40U;
case 13:
x |= ((uint64_t)msg[12]) << 32U;
case 12:
x |= *(const uint32_t*)(msg + 8);
MIX(_mm_set_epi64x(x, *(const uint64_t*)msg));
break;
case 11:
x |= ((uint32_t)msg[10]) << 16U;
case 10:
x |= ((uint32_t)msg[9]) << 8U;
case 9:
x |= msg[8];
case 8:
MIX(_mm_set_epi64x(x, *(const uint64_t*)msg));
break;
case 7:
x |= ((uint64_t)msg[6]) << 48U;
case 6:
x |= ((uint64_t)msg[5]) << 40U;
case 5:
x |= ((uint64_t)msg[4]) << 32U;
case 4:
x |= *(const uint32_t*)msg;
MIX(_mm_set_epi64x(0, x));
break;
case 3:
x |= ((uint32_t)msg[2]) << 16U;
case 2:
x |= ((uint32_t)msg[1]) << 8U;
case 1:
x |= msg[0];
MIX(_mm_set_epi64x(0, x));
break;
case 0:
default: // try to keep m & s from register spilling
a = _mm_add_epi8(a, s);
b = _mm_add_epi8(b, m);
}
return _mm_aesenc_si128(a, b);
}
uint64_t AESNI_Hash64(const uint8_t* msg, unsigned len, uint32_t seed) {
union {
uint64_t x[2];
__m128i v;
} t;
t.v = AESNI_Hash128(msg, len, seed);
return t.x[0];
}
The text was updated successfully, but these errors were encountered:
The text was updated successfully, but these errors were encountered: