// File: BU-DiSC[P]BF-Shared-Hashing/hash/Crc32.cpp
// Function: crc32_8bytes(void const*, unsigned long, unsigned int)
uint32_t crc32_8bytes(const void* data, size_t length, uint32_t previousCrc32)
{
  uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
  const uint32_t* current = (const uint32_t*) data;

  // process eight bytes at once (Slicing-by-8)
  while (length >= 8)
  {
#if __BYTE_ORDER == __BIG_ENDIAN
    uint32_t one = *current++ ^ swap(crc);
    uint32_t two = *current++;
    crc = Crc32Lookup[0][ two      & 0xFF] ^
          Crc32Lookup[1][(two>> 8) & 0xFF] ^
          Crc32Lookup[2][(two>>16) & 0xFF] ^
          Crc32Lookup[3][(two>>24) & 0xFF] ^
          Crc32Lookup[4][ one      & 0xFF] ^
          Crc32Lookup[5][(one>> 8) & 0xFF] ^
          Crc32Lookup[6][(one>>16) & 0xFF] ^
          Crc32Lookup[7][(one>>24) & 0xFF];
#else
    uint32_t one = *current++ ^ crc;
    uint32_t two = *current++;
    crc = Crc32Lookup[0][(two>>24) & 0xFF] ^
          Crc32Lookup[1][(two>>16) & 0xFF] ^
          Crc32Lookup[2][(two>> 8) & 0xFF] ^
          Crc32Lookup[3][ two      & 0xFF] ^
          Crc32Lookup[4][(one>>24) & 0xFF] ^
          Crc32Lookup[5][(one>>16) & 0xFF] ^
          Crc32Lookup[6][(one>> 8) & 0xFF] ^
          Crc32Lookup[7][ one      & 0xFF];
#endif

    length -= 8;
  }

  const uint8_t* currentChar = (const uint8_t*) current;
  // remaining 1 to 7 bytes (standard algorithm)
  while (length-- != 0)
    crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++];

  return ~crc; // same as crc ^ 0xFFFFFFFF
}

// Assembly:
movq %rdi, -0x8(%rsp)
movq %rsi, -0x10(%rsp)
movl %edx, -0x14(%rsp)
movl -0x14(%rsp), %eax
xorl $-0x1, %eax
movl %eax, -0x18(%rsp)
movq -0x8(%rsp), %rax
movq %rax, -0x20(%rsp)
cmpq $0x8, -0x10(%rsp)
jb 0x60595
movq -0x20(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x20(%rsp)
movl (%rax), %eax
xorl -0x18(%rsp), %eax
movl %eax, -0x24(%rsp)
movq -0x20(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x20(%rsp)
movl (%rax), %eax
movl %eax, -0x28(%rsp)
movl -0x28(%rsp), %eax
shrl $0x18, %eax
andl $0xff, %eax
movl %eax, %eax
movl %eax, %ecx
leaq 0x5328(%rip), %rax      # 0x657d0
movl (%rax,%rcx,4), %eax
movl -0x28(%rsp), %ecx
shrl $0x10, %ecx
andl $0xff, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x530d(%rip), %rcx      # 0x657d0
xorl 0x400(%rcx,%rdx,4), %eax
movl -0x28(%rsp), %ecx
shrl $0x8, %ecx
andl $0xff, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x52ee(%rip), %rcx      # 0x657d0
xorl 0x800(%rcx,%rdx,4), %eax
movl -0x28(%rsp), %ecx
andl $0xff, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x52d2(%rip), %rcx      # 0x657d0
xorl 0xc00(%rcx,%rdx,4), %eax
movl -0x24(%rsp), %ecx
shrl $0x18, %ecx
andl $0xff, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x52b3(%rip), %rcx      # 0x657d0
xorl 0x1000(%rcx,%rdx,4), %eax
movl -0x24(%rsp), %ecx
shrl $0x10, %ecx
andl $0xff, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x5294(%rip), %rcx      # 0x657d0
xorl 0x1400(%rcx,%rdx,4), %eax
movl -0x24(%rsp), %ecx
shrl $0x8, %ecx
andl $0xff, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x5275(%rip), %rcx      # 0x657d0
xorl 0x1800(%rcx,%rdx,4), %eax
movl -0x24(%rsp), %ecx
andl $0xff, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x5259(%rip), %rcx      # 0x657d0
xorl 0x1c00(%rcx,%rdx,4), %eax
movl %eax, -0x18(%rsp)
movq -0x10(%rsp), %rax
subq $0x8, %rax
movq %rax, -0x10(%rsp)
jmp 0x60453
movq -0x20(%rsp), %rax
movq %rax, -0x30(%rsp)
movq -0x10(%rsp), %rax
movq %rax, %rcx
addq $-0x1, %rcx
movq %rcx, -0x10(%rsp)
cmpq $0x0, %rax
je 0x605f1
movl -0x18(%rsp), %eax
shrl $0x8, %eax
movl -0x18(%rsp), %ecx
andl $0xff, %ecx
movq -0x30(%rsp), %rdx
movq %rdx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rsp)
movzbl (%rdx), %edx
xorl %edx, %ecx
movl %ecx, %ecx
movl %ecx, %edx
leaq 0x51e8(%rip), %rcx      # 0x657d0
xorl (%rcx,%rdx,4), %eax
movl %eax, -0x18(%rsp)
jmp 0x6059f
movl -0x18(%rsp), %eax
xorl $-0x1, %eax
retq
nopl (%rax)