// File: 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:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
shlq $0x38, %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x20(%rbp)
movabsq $0x736f6d6570736575, %rax # imm = 0x736F6D6570736575
xorq 0x99a2b(%rip), %rax     # 0xafca0
movq %rax, -0x28(%rbp)
movabsq $0x646f72616e646f6d, %rax # imm = 0x646F72616E646F6D
xorq 0x99a1e(%rip), %rax     # 0xafca8
movq %rax, -0x30(%rbp)
movabsq $0x6c7967656e657261, %rax # imm = 0x6C7967656E657261
xorq 0x99a01(%rip), %rax     # 0xafca0
movq %rax, -0x38(%rbp)
movabsq $0x7465646279746573, %rax # imm = 0x7465646279746573
xorq 0x999f4(%rip), %rax     # 0xafca8
movq %rax, -0x40(%rbp)
cmpq $0x8, -0x10(%rbp)
jb 0x164a4
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
callq 0x16230
movq %rax, -0x48(%rbp)
movq -0x20(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
subq $0x8, %rax
movq %rax, -0x10(%rbp)
movq -0x48(%rbp), %rax
xorq -0x40(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x40(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
shlq $0xd, %rax
movq -0x30(%rbp), %rcx
shrq $0x33, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x10, %rax
movq -0x40(%rbp), %rcx
shrq $0x30, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
shlq $0x20, %rax
movq -0x28(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
shlq $0x11, %rax
movq -0x30(%rbp), %rcx
shrq $0x2f, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x15, %rax
movq -0x40(%rbp), %rcx
shrq $0x2b, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq $0x20, %rax
movq -0x38(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x40(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
shlq $0xd, %rax
movq -0x30(%rbp), %rcx
shrq $0x33, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x10, %rax
movq -0x40(%rbp), %rcx
shrq $0x30, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
shlq $0x20, %rax
movq -0x28(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
shlq $0x11, %rax
movq -0x30(%rbp), %rcx
shrq $0x2f, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x15, %rax
movq -0x40(%rbp), %rcx
shrq $0x2b, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq $0x20, %rax
movq -0x38(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x48(%rbp), %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x162b8
movq -0x10(%rbp), %rax
decq %rax
movq %rax, -0x50(%rbp)
subq $0x6, %rax
ja 0x16554
movq -0x50(%rbp), %rax
leaq 0x63f0c(%rip), %rcx     # 0x7a3d0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x20(%rbp), %rax
movzbl 0x6(%rax), %eax
shlq $0x30, %rax
orq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x5(%rax), %eax
shlq $0x28, %rax
orq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x4(%rax), %eax
shlq $0x20, %rax
orq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x3(%rax), %eax
shlq $0x18, %rax
orq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x2(%rax), %eax
shlq $0x10, %rax
orq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x1(%rax), %eax
shlq $0x8, %rax
orq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
orq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
xorq -0x40(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x40(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
shlq $0xd, %rax
movq -0x30(%rbp), %rcx
shrq $0x33, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x10, %rax
movq -0x40(%rbp), %rcx
shrq $0x30, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
shlq $0x20, %rax
movq -0x28(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
shlq $0x11, %rax
movq -0x30(%rbp), %rcx
shrq $0x2f, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x15, %rax
movq -0x40(%rbp), %rcx
shrq $0x2b, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq $0x20, %rax
movq -0x38(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x40(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
shlq $0xd, %rax
movq -0x30(%rbp), %rcx
shrq $0x33, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x10, %rax
movq -0x40(%rbp), %rcx
shrq $0x30, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
shlq $0x20, %rax
movq -0x28(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
shlq $0x11, %rax
movq -0x30(%rbp), %rcx
shrq $0x2f, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x15, %rax
movq -0x40(%rbp), %rcx
shrq $0x2b, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq $0x20, %rax
movq -0x38(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x18(%rbp), %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x38(%rbp), %rax
xorq $0xff, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x40(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
shlq $0xd, %rax
movq -0x30(%rbp), %rcx
shrq $0x33, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x10, %rax
movq -0x40(%rbp), %rcx
shrq $0x30, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
shlq $0x20, %rax
movq -0x28(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
shlq $0x11, %rax
movq -0x30(%rbp), %rcx
shrq $0x2f, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x15, %rax
movq -0x40(%rbp), %rcx
shrq $0x2b, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq $0x20, %rax
movq -0x38(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x40(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
shlq $0xd, %rax
movq -0x30(%rbp), %rcx
shrq $0x33, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x10, %rax
movq -0x40(%rbp), %rcx
shrq $0x30, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
shlq $0x20, %rax
movq -0x28(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
shlq $0x11, %rax
movq -0x30(%rbp), %rcx
shrq $0x2f, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x15, %rax
movq -0x40(%rbp), %rcx
shrq $0x2b, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq $0x20, %rax
movq -0x38(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x40(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
shlq $0xd, %rax
movq -0x30(%rbp), %rcx
shrq $0x33, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x10, %rax
movq -0x40(%rbp), %rcx
shrq $0x30, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
shlq $0x20, %rax
movq -0x28(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
shlq $0x11, %rax
movq -0x30(%rbp), %rcx
shrq $0x2f, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x15, %rax
movq -0x40(%rbp), %rcx
shrq $0x2b, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq $0x20, %rax
movq -0x38(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x40(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
shlq $0xd, %rax
movq -0x30(%rbp), %rcx
shrq $0x33, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x10, %rax
movq -0x40(%rbp), %rcx
shrq $0x30, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
shlq $0x20, %rax
movq -0x28(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x30(%rbp), %rax
shlq $0x11, %rax
movq -0x30(%rbp), %rcx
shrq $0x2f, %rcx
orq %rcx, %rax
xorq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rax
shlq $0x15, %rax
movq -0x40(%rbp), %rcx
shrq $0x2b, %rcx
orq %rcx, %rax
xorq -0x28(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq $0x20, %rax
movq -0x38(%rbp), %rcx
shrq $0x20, %rcx
orq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rax
xorq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
xorq -0x40(%rbp), %rcx
xorq %rcx, %rax
addq $0x50, %rsp
popq %rbp
retq
nop