// File: BU-DiSC[P]BF-Shared-Hashing/hash/murmurhash.cc
// Function: MurmurHash64A(void const*, int, unsigned int)
uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed )
{
    const uint64_t m = 0xc6a4a7935bd1e995;
    const int r = 47;

    uint64_t h = seed ^ (len * m);

    const uint64_t * data = (const uint64_t *)key;
    const uint64_t * end = data + (len/8);

    while(data != end)
    {
        uint64_t k = *data++;

        k *= m;
        k ^= k >> r;
        k *= m;

        h ^= k;
        h *= m;
    }

    const unsigned char * data2 = (const unsigned char*)data;

    switch(len & 7)
    {
    case 7: h ^= ((uint64_t)data2[6]) << 48;
    case 6: h ^= ((uint64_t)data2[5]) << 40;
    case 5: h ^= ((uint64_t)data2[4]) << 32;
    case 4: h ^= ((uint64_t)data2[3]) << 24;
    case 3: h ^= ((uint64_t)data2[2]) << 16;
    case 2: h ^= ((uint64_t)data2[1]) << 8; 
    case 1: h ^= ((uint64_t)data2[0]);
        h *= m;
    };

    h ^= h >> r;
    h *= m;
    h ^= h >> r;

    return h;
}

// Assembly:
movq %rdi, -0x8(%rsp)
movl %esi, -0xc(%rsp)
movl %edx, -0x10(%rsp)
movabsq $-0x395b586ca42e166b, %rax # imm = 0xC6A4A7935BD1E995
movq %rax, -0x18(%rsp)
movl $0x2f, -0x1c(%rsp)
movl -0x10(%rsp), %eax
movslq -0xc(%rsp), %rcx
movabsq $-0x395b586ca42e166b, %rdx # imm = 0xC6A4A7935BD1E995
imulq %rdx, %rcx
xorq %rcx, %rax
movq %rax, -0x28(%rsp)
movq -0x8(%rsp), %rax
movq %rax, -0x30(%rsp)
movq -0x30(%rsp), %rax
movq %rax, -0x50(%rsp)
movl -0xc(%rsp), %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq -0x50(%rsp), %rax
movslq %ecx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x38(%rsp)
movq -0x30(%rsp), %rax
cmpq -0x38(%rsp), %rax
je 0x4c284
movq -0x30(%rsp), %rax
movq %rax, %rcx
addq $0x8, %rcx
movq %rcx, -0x30(%rsp)
movq (%rax), %rax
movq %rax, -0x40(%rsp)
movabsq $-0x395b586ca42e166b, %rax # imm = 0xC6A4A7935BD1E995
imulq -0x40(%rsp), %rax
movq %rax, -0x40(%rsp)
movq -0x40(%rsp), %rax
shrq $0x2f, %rax
xorq -0x40(%rsp), %rax
movq %rax, -0x40(%rsp)
movabsq $-0x395b586ca42e166b, %rax # imm = 0xC6A4A7935BD1E995
imulq -0x40(%rsp), %rax
movq %rax, -0x40(%rsp)
movq -0x40(%rsp), %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movabsq $-0x395b586ca42e166b, %rax # imm = 0xC6A4A7935BD1E995
imulq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
jmp 0x4c1f9
movq -0x30(%rsp), %rax
movq %rax, -0x48(%rsp)
movl -0xc(%rsp), %eax
andl $0x7, %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x58(%rsp)
subl $0x6, %eax
ja 0x4c36d
movq -0x58(%rsp), %rax
leaq 0x19175(%rip), %rcx     # 0x65428
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x48(%rsp), %rax
movzbl 0x6(%rax), %eax
shlq $0x30, %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x48(%rsp), %rax
movzbl 0x5(%rax), %eax
shlq $0x28, %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x48(%rsp), %rax
movzbl 0x4(%rax), %eax
shlq $0x20, %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x48(%rsp), %rax
movzbl 0x3(%rax), %eax
shlq $0x18, %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x48(%rsp), %rax
movzbl 0x2(%rax), %eax
shlq $0x10, %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x48(%rsp), %rax
movzbl 0x1(%rax), %eax
shlq $0x8, %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x48(%rsp), %rax
movzbl (%rax), %eax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movabsq $-0x395b586ca42e166b, %rax # imm = 0xC6A4A7935BD1E995
imulq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x28(%rsp), %rax
shrq $0x2f, %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movabsq $-0x395b586ca42e166b, %rax # imm = 0xC6A4A7935BD1E995
imulq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x28(%rsp), %rax
shrq $0x2f, %rax
xorq -0x28(%rsp), %rax
movq %rax, -0x28(%rsp)
movq -0x28(%rsp), %rax
retq
nop