// File: sgielen[P]clife/./xxhash/xxhash.h
// Function: XXH3_len_9to16_128b(unsigned char const*, unsigned long, unsigned char const*, unsigned long)
XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t
XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
{
    XXH_ASSERT(input != NULL);
    XXH_ASSERT(secret != NULL);
    XXH_ASSERT(9 <= len && len <= 16);
    {   xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed;
        xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed;
        xxh_u64 const input_lo = XXH_readLE64(input);
        xxh_u64       input_hi = XXH_readLE64(input + len - 8);
        XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1);
        /*
         * Put len in the middle of m128 to ensure that the length gets mixed to
         * both the low and high bits in the 128x64 multiply below.
         */
        m128.low64 += (xxh_u64)(len - 1) << 54;
        input_hi   ^= bitfliph;
        /*
         * Add the high 32 bits of input_hi to the high 32 bits of m128, then
         * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to
         * the high 64 bits of m128.
         *
         * The best approach to this operation is different on 32-bit and 64-bit.
         */
        if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */
            /*
             * 32-bit optimized version, which is more readable.
             *
             * On 32-bit, it removes an ADC and delays a dependency between the two
             * halves of m128.high64, but it generates an extra mask on 64-bit.
             */
            m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2);
        } else {
            /*
             * 64-bit optimized (albeit more confusing) version.
             *
             * Uses some properties of addition and multiplication to remove the mask:
             *
             * Let:
             *    a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF)
             *    b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000)
             *    c = XXH_PRIME32_2
             *
             *    a + (b * c)
             * Inverse Property: x + y - x == y
             *    a + (b * (1 + c - 1))
             * Distributive Property: x * (y + z) == (x * y) + (x * z)
             *    a + (b * 1) + (b * (c - 1))
             * Identity Property: x * 1 == x
             *    a + b + (b * (c - 1))
             *
             * Substitute a, b, and c:
             *    input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))
             *
             * Since input_hi.hi + input_hi.lo == input_hi, we get this:
             *    input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))
             */
            m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1);
        }
        /* m128 ^= XXH_swap64(m128 >> 64); */
        m128.low64  ^= XXH_swap64(m128.high64);

        {   /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */
            XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2);
            h128.high64 += m128.high64 * XXH_PRIME64_2;

            h128.low64   = XXH3_avalanche(h128.low64);
            h128.high64  = XXH3_avalanche(h128.high64);
            return h128;
    }   }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x18(%rbp)
movq %rsi, -0x20(%rbp)
movq %rdx, -0x28(%rbp)
movq %rcx, -0x30(%rbp)
movq -0x28(%rbp), %rdi
addq $0x20, %rdi
callq 0x32e0
movq %rax, -0x78(%rbp)
movq -0x28(%rbp), %rdi
addq $0x28, %rdi
callq 0x32e0
movq %rax, %rcx
movq -0x78(%rbp), %rax
xorq %rcx, %rax
movq -0x30(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rdi
addq $0x30, %rdi
callq 0x32e0
movq %rax, -0x70(%rbp)
movq -0x28(%rbp), %rdi
addq $0x38, %rdi
callq 0x32e0
movq %rax, %rcx
movq -0x70(%rbp), %rax
xorq %rcx, %rax
movq -0x30(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rdi
callq 0x32e0
movq %rax, -0x48(%rbp)
movq -0x18(%rbp), %rax
movq -0x20(%rbp), %rcx
leaq -0x8(%rax,%rcx), %rdi
callq 0x32e0
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rdi
movq -0x50(%rbp), %rax
xorq %rax, %rdi
movq -0x38(%rbp), %rax
xorq %rax, %rdi
movabsq $-0x61c8864e7a143579, %rsi # imm = 0x9E3779B185EBCA87
callq 0x6450
movq %rax, -0x60(%rbp)
movq %rdx, -0x58(%rbp)
movl -0x20(%rbp), %eax
decl %eax
movl %eax, %ecx
shlq $0x36, %rcx
movq -0x60(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x40(%rbp), %rcx
movq -0x50(%rbp), %rax
xorq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rcx
movl %ecx, %eax
movl %eax, %eax
movl $0x85ebca76, %edx       # imm = 0x85EBCA76
imulq %rdx, %rax
addq %rax, %rcx
movq -0x58(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rdi
callq 0x3610
movq %rax, %rcx
movq -0x60(%rbp), %rax
xorq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rdi
movabsq $-0x3d4d51c2d82b14b1, %rsi # imm = 0xC2B2AE3D27D4EB4F
movq %rsi, -0x68(%rbp)
callq 0x6450
movq %rax, %rcx
movq -0x68(%rbp), %rax
movq %rcx, -0x10(%rbp)
movq %rdx, -0x8(%rbp)
movq -0x58(%rbp), %rcx
imulq %rax, %rcx
movq -0x8(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x6400
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rdi
callq 0x6400
movq %rax, -0x8(%rbp)
movq -0x10(%rbp), %rax
movq -0x8(%rbp), %rdx
addq $0x80, %rsp
popq %rbp
retq
nopl (%rax)