// File: /workspace/github_c_makefile_star2_O0/Tarsnap[P]kivaloo/liball/../libcperciva/alg/crc32c_sse42.c
// Function: CRC32C_Update_SSE42
uint32_t
CRC32C_Update_SSE42(uint32_t state, const uint8_t * buf, size_t len)
{
	size_t pre_block;
	size_t remaining_bytes;
	size_t in_block;
	size_t i = 0;

	/* Sanity test. */
	assert(len >= 8);

	/*
	 * Calculate how many bytes are before an aligned block.  Assume that
	 * the (uintptr_t) value indicates the memory layout.
	 */
	pre_block = (8 - (uintptr_t)buf) & 7;

	/* Calculate how many bytes are in aligned blocks. */
	remaining_bytes = len - pre_block;
	in_block = remaining_bytes - (remaining_bytes % 8);

	/* Process bytes before the alignment. */
	for (; i < pre_block; i++)
		state = _mm_crc32_u8(state, buf[i]);

	/* If we would process a block, ensure that it's aligned. */
	assert(!((i < in_block) && !((((uintptr_t)&buf[i]) & 7) == 0)));

	/*
	 * Process blocks of 8.  It's ok if (i % 8 != 0), because we're
	 * checking that (i < in_block), not (i != in_block).  For example,
	 * if we start with i = 4 and want 1 block, we'll end up at i == 12.
	 */
	for (; i < in_block; i += 8) {
#ifdef CPUSUPPORT_X86_SSE42_64
		state = (uint32_t)_mm_crc32_u64(state,
		    *(const uint64_t *)&buf[i]);
#else
		/* Only process 32 bits at once. */
		state = (uint32_t)_mm_crc32_u32(state,
		    *(const uint32_t *)&buf[i]);
		state = (uint32_t)_mm_crc32_u32(state,
		    *(const uint32_t *)&buf[i + 4]);
#endif
	}

	/* Ensure that we don't have too many bytes remaining. */
	assert((len - i) < 8);

	/* Process any remaining bytes. */
	for (; i < len; i++)
		state = _mm_crc32_u8(state, buf[i]);

	return (state);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movl %edi, -0x24(%rbp)
movq %rsi, -0x30(%rbp)
movq %rdx, -0x38(%rbp)
movq $0x0, -0x58(%rbp)
cmpq $0x8, -0x38(%rbp)
jb 0xa5a4
jmp 0xa5c3
leaq 0x5a6c(%rip), %rdi      # 0x10017
leaq 0x5a6e(%rip), %rsi      # 0x10020
movl $0x22, %edx
leaq 0x5a84(%rip), %rcx      # 0x10042
callq 0x21a0
movq -0x30(%rbp), %rcx
movl $0x8, %eax
subq %rcx, %rax
andq $0x7, %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
subq -0x40(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq -0x48(%rbp), %rcx
andq $0x7, %rcx
subq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x58(%rbp), %rax
cmpq -0x40(%rbp), %rax
jae 0xa62e
movl -0x24(%rbp), %ecx
movq -0x30(%rbp), %rax
movq -0x58(%rbp), %rdx
movb (%rax,%rdx), %al
movl %ecx, -0x14(%rbp)
movb %al, -0x15(%rbp)
movl -0x14(%rbp), %eax
crc32b -0x15(%rbp), %eax
movl %eax, -0x24(%rbp)
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0xa5f6
movq -0x58(%rbp), %rax
cmpq -0x50(%rbp), %rax
jae 0xa64a
movq -0x30(%rbp), %rax
addq -0x58(%rbp), %rax
andq $0x7, %rax
cmpq $0x0, %rax
jne 0xa64c
jmp 0xa66b
leaq 0x5a2f(%rip), %rdi      # 0x10082
leaq 0x59c6(%rip), %rsi      # 0x10020
movl $0x33, %edx
leaq 0x59dc(%rip), %rcx      # 0x10042
callq 0x21a0
jmp 0xa66d
movq -0x58(%rbp), %rax
cmpq -0x50(%rbp), %rax
jae 0xa6ac
movl -0x24(%rbp), %eax
movl %eax, %ecx
movq -0x30(%rbp), %rax
movq -0x58(%rbp), %rdx
movq (%rax,%rdx), %rax
movq %rcx, -0x8(%rbp)
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rax
crc32q -0x10(%rbp), %rax
movl %eax, -0x24(%rbp)
movq -0x58(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x58(%rbp)
jmp 0xa66d
movq -0x38(%rbp), %rax
subq -0x58(%rbp), %rax
cmpq $0x8, %rax
jae 0xa6bc
jmp 0xa6db
leaq 0x59f7(%rip), %rdi      # 0x100ba
leaq 0x5956(%rip), %rsi      # 0x10020
movl $0x48, %edx
leaq 0x596c(%rip), %rcx      # 0x10042
callq 0x21a0
jmp 0xa6dd
movq -0x58(%rbp), %rax
cmpq -0x38(%rbp), %rax
jae 0xa715
movl -0x24(%rbp), %ecx
movq -0x30(%rbp), %rax
movq -0x58(%rbp), %rdx
movb (%rax,%rdx), %al
movl %ecx, -0x1c(%rbp)
movb %al, -0x1d(%rbp)
movl -0x1c(%rbp), %eax
crc32b -0x1d(%rbp), %eax
movl %eax, -0x24(%rbp)
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0xa6dd
movl -0x24(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nop