// File: /workspace/github_cpp_makefile_star2_O2/cybozu[P]yrmcds/cybozu/siphash.cpp
// Function: cybozu::siphash24(void const*, unsigned long)
uint64_t siphash24(const void *src, std::size_t src_sz) {
    uint64_t b = (uint64_t)src_sz << 56;
    const uint8_t *m = (const uint8_t*)src;

    uint64_t v0 = static_k0 ^ 0x736f6d6570736575ULL;
    uint64_t v1 = static_k1 ^ 0x646f72616e646f6dULL;
    uint64_t v2 = static_k0 ^ 0x6c7967656e657261ULL;
    uint64_t v3 = static_k1 ^ 0x7465646279746573ULL;

    while (src_sz >= 8) {
        uint64_t mi;
        std::memcpy(&mi, m, sizeof(mi));
        mi = le64toh(mi);
        m += 8; src_sz -= 8;
        v3 ^= mi;
        DOUBLE_ROUND(v0,v1,v2,v3);
        v0 ^= mi;
    }

    switch (src_sz) {
    case 7: b |= uint64_t(m[6]) << 48;
    case 6: b |= uint64_t(m[5]) << 40;
    case 5: b |= uint64_t(m[4]) << 32;
    case 4: b |= uint64_t(m[3]) << 24;
    case 3: b |= uint64_t(m[2]) << 16;
    case 2: b |= uint64_t(m[1]) << 8;
    case 1: b |= uint64_t(m[0]);
    }

    v3 ^= b;
    DOUBLE_ROUND(v0,v1,v2,v3);
    v0 ^= b; v2 ^= 0xff;
    DOUBLE_ROUND(v0,v1,v2,v3);
    DOUBLE_ROUND(v0,v1,v2,v3);
    return (v0 ^ v1) ^ (v2 ^ v3);
}

// Assembly:
movq 0x30b13(%rip), %r8      # 0x3bb60
movabsq $0x736f6d6570736575, %rax # imm = 0x736F6D6570736575
xorq %r8, %rax
movq 0x30b07(%rip), %r9      # 0x3bb68
movabsq $0x646f72616e646f6d, %rdx # imm = 0x646F72616E646F6D
xorq %r9, %rdx
movabsq $0x6c7967656e657261, %rcx # imm = 0x6C7967656E657261
xorq %r8, %rcx
movabsq $0x7465646279746573, %r8 # imm = 0x7465646279746573
xorq %r9, %r8
movq %rsi, %r9
cmpq $0x8, %r9
jb 0xb104
movq (%rdi), %r10
addq $0x8, %rdi
addq $-0x8, %r9
xorq %r10, %r8
addq %rdx, %rax
addq %r8, %rcx
rolq $0xd, %rdx
xorq %rax, %rdx
rolq $0x10, %r8
rolq $0x20, %rax
xorq %rcx, %r8
addq %rdx, %rcx
rolq $0x11, %rdx
addq %r8, %rax
xorq %rcx, %rdx
rolq $0x15, %r8
xorq %rax, %r8
rolq $0x20, %rcx
addq %rdx, %rax
addq %r8, %rcx
rolq $0xd, %rdx
xorq %rax, %rdx
rolq $0x10, %r8
rolq $0x20, %rax
xorq %rcx, %r8
addq %rdx, %rcx
rolq $0x11, %rdx
addq %r8, %rax
xorq %rcx, %rdx
rolq $0x15, %r8
xorq %rax, %r8
rolq $0x20, %rcx
xorq %r10, %rax
jmp 0xb08b
shlq $0x38, %rsi
leaq 0x1b281(%rip), %r10     # 0x26390
movslq (%r10,%r9,4), %r9
addq %r10, %r9
jmpq *%r9
movzbl 0x6(%rdi), %r9d
shlq $0x30, %r9
orq %r9, %rsi
movzbl 0x5(%rdi), %r9d
shlq $0x28, %r9
orq %r9, %rsi
movzbl 0x4(%rdi), %r9d
shlq $0x20, %r9
orq %r9, %rsi
movzbl 0x3(%rdi), %r9d
shll $0x18, %r9d
orq %r9, %rsi
movzbl 0x2(%rdi), %r9d
shll $0x10, %r9d
orq %r9, %rsi
movzbl 0x1(%rdi), %r9d
shll $0x8, %r9d
orq %r9, %rsi
movzbl (%rdi), %edi
orq %rdi, %rsi
xorq %rsi, %r8
addq %rdx, %rax
rolq $0xd, %rdx
addq %r8, %rcx
xorq %rax, %rdx
rolq $0x10, %r8
xorq %rcx, %r8
rolq $0x20, %rax
addq %rdx, %rcx
addq %r8, %rax
rolq $0x11, %rdx
xorq %rcx, %rdx
rolq $0x15, %r8
rolq $0x20, %rcx
xorq %rax, %r8
addq %rdx, %rax
rolq $0xd, %rdx
addq %r8, %rcx
xorq %rax, %rdx
rolq $0x10, %r8
xorq %rcx, %r8
rolq $0x20, %rax
addq %rdx, %rcx
addq %r8, %rax
rolq $0x11, %rdx
xorq %rcx, %rdx
rolq $0x15, %r8
rolq $0x20, %rcx
xorq %rax, %r8
xorq %rsi, %rax
xorq $0xff, %rcx
addq %rdx, %rax
addq %r8, %rcx
rolq $0xd, %rdx
xorq %rax, %rdx
rolq $0x10, %r8
rolq $0x20, %rax
xorq %rcx, %r8
addq %rdx, %rcx
rolq $0x11, %rdx
addq %r8, %rax
xorq %rcx, %rdx
rolq $0x15, %r8
xorq %rax, %r8
rolq $0x20, %rcx
addq %rdx, %rax
addq %r8, %rcx
rolq $0xd, %rdx
xorq %rax, %rdx
rolq $0x10, %r8
rolq $0x20, %rax
xorq %rcx, %r8
addq %rdx, %rcx
rolq $0x11, %rdx
addq %r8, %rax
xorq %rcx, %rdx
rolq $0x15, %r8
xorq %rax, %r8
rolq $0x20, %rcx
addq %rdx, %rax
addq %r8, %rcx
rolq $0xd, %rdx
xorq %rax, %rdx
rolq $0x10, %r8
rolq $0x20, %rax
xorq %rcx, %r8
addq %rdx, %rcx
rolq $0x11, %rdx
addq %r8, %rax
xorq %rcx, %rdx
rolq $0x15, %r8
xorq %rax, %r8
rolq $0x20, %rcx
addq %rdx, %rax
addq %r8, %rcx
rolq $0xd, %rdx
xorq %rax, %rdx
rolq $0x10, %r8
xorq %rcx, %r8
addq %rdx, %rcx
rolq $0x11, %rdx
rolq $0x15, %r8
movq %rcx, %rax
rolq $0x20, %rax
xorq %rdx, %rax
xorq %r8, %rax
xorq %rcx, %rax
retq