// File: /workspace/github_c_makefile_star2_O0/dlbeer[P]dhara/ecc/hamming.c
// Function: parity_scan
static hamming_ecc_t parity_scan(const uint8_t *chunk, size_t len)
{
	uint8_t column = 0;
	uint16_t line = 0;
	uint16_t line_bar = 0;
	hamming_ecc_t out = 0;
	int i;

	/* Let the bits in chunk be partitioned into the following
	 * subsets:
	 *
	 *    P0 : bits  0,  2,  4,  6,  8, 10, 12, 14...
	 *    P0': bits  1,  3,  5,  7,  9, 11, 13, 15...
	 *    P1 : bits  0,  1,  4,  5,  8,  9, 12, 13...
	 *    P1': bits  2,  3,  6,  7, 10, 11, 14, 15...
	 *    P2 : bits  0,  1,  2,  3,  8,  9, 10, 11...
	 *    P2': bits  4,  5,  6,  7, 12, 13, 14, 15...
         *    P3 : bits  0,  1,  2,  3,  4,  5,  6,  7...
	 *    P3': bits  8,  9, 10, 11, 12, 13, 14, 15...
	 *
	 * That is, given a bit position i, and a pair of sets (Pm,
	 * Pm'), then i belongs to Pm if bit m in i is clear. Otherwise,
	 * it belongs to Pm'.
	 */
	for (i = 0; i < len; i++) {
		const uint8_t c = chunk[i];

		column ^= c;

		if (bit_count[c] & 1) {
			line ^= i;
			line_bar ^= ~i;
		}
	}

	/* The output checksum is the parity of the sets, in the
	 * following order:
	 *
	 *     ...P3', P3, P2', P2, P1', P1, P0', P0
	 *
	 * This is a linear code: the parity of the difference of two
	 * blocks is equal to the difference of their parities.
	 *
	 * If the bit at position i is flipped, then it flips the parity
	 * of exactly one of each pair of sets (position i belongs to
	 * one of each pair of sets).
	 *
	 * By observing which of each pair has changed parity, we can
	 * determine each bit of i.
	 */
	for (i = 0; i < HAMMING_LOG2_CHUNK_SIZE; i++) {
		out <<= 1;
		out |= (line_bar >> 8) & 1;

		out <<= 1;
		out |= (line >> 8) & 1;

		line <<= 1;
		line_bar <<= 1;
	}

	out = (out << 1) | (bit_count[column & 0x0f] & 1);
	out = (out << 1) | (bit_count[column & 0xf0] & 1);
	out = (out << 1) | (bit_count[column & 0x33] & 1);
	out = (out << 1) | (bit_count[column & 0xcc] & 1);
	out = (out << 1) | (bit_count[column & 0x55] & 1);
	out = (out << 1) | (bit_count[column & 0xaa] & 1);

	return out ^ 0xffffff;
}

// Assembly:
movq %rdi, -0x8(%rsp)
movq %rsi, -0x10(%rsp)
movb $0x0, -0x11(%rsp)
movw $0x0, -0x14(%rsp)
movw $0x0, -0x16(%rsp)
movl $0x0, -0x1c(%rsp)
movl $0x0, -0x20(%rsp)
movslq -0x20(%rsp), %rax
cmpq -0x10(%rsp), %rax
jae 0x12a6
movq -0x8(%rsp), %rax
movslq -0x20(%rsp), %rcx
movb (%rax,%rcx), %al
movb %al, -0x21(%rsp)
movzbl -0x21(%rsp), %ecx
movzbl -0x11(%rsp), %eax
xorl %ecx, %eax
movb %al, -0x11(%rsp)
movzbl -0x21(%rsp), %eax
movl %eax, %ecx
leaq 0xda8(%rip), %rax       # 0x2010
movzbl (%rax,%rcx), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x1297
movl -0x20(%rsp), %ecx
movzwl -0x14(%rsp), %eax
xorl %ecx, %eax
movw %ax, -0x14(%rsp)
movl -0x20(%rsp), %ecx
xorl $-0x1, %ecx
movzwl -0x16(%rsp), %eax
xorl %ecx, %eax
movw %ax, -0x16(%rsp)
jmp 0x1299
movl -0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rsp)
jmp 0x122d
movl $0x0, -0x20(%rsp)
cmpl $0x9, -0x20(%rsp)
jge 0x1314
movl -0x1c(%rsp), %eax
shll %eax
movl %eax, -0x1c(%rsp)
movzwl -0x16(%rsp), %eax
sarl $0x8, %eax
andl $0x1, %eax
orl -0x1c(%rsp), %eax
movl %eax, -0x1c(%rsp)
movl -0x1c(%rsp), %eax
shll %eax
movl %eax, -0x1c(%rsp)
movzwl -0x14(%rsp), %eax
sarl $0x8, %eax
andl $0x1, %eax
orl -0x1c(%rsp), %eax
movl %eax, -0x1c(%rsp)
movzwl -0x14(%rsp), %eax
shll %eax
movw %ax, -0x14(%rsp)
movzwl -0x16(%rsp), %eax
shll %eax
movw %ax, -0x16(%rsp)
movl -0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rsp)
jmp 0x12ae
movl -0x1c(%rsp), %eax
shll %eax
movzbl -0x11(%rsp), %ecx
andl $0xf, %ecx
movslq %ecx, %rdx
leaq 0xce4(%rip), %rcx       # 0x2010
movzbl (%rcx,%rdx), %ecx
andl $0x1, %ecx
orl %ecx, %eax
movl %eax, -0x1c(%rsp)
movl -0x1c(%rsp), %eax
shll %eax
movzbl -0x11(%rsp), %ecx
andl $0xf0, %ecx
movslq %ecx, %rdx
leaq 0xcbc(%rip), %rcx       # 0x2010
movzbl (%rcx,%rdx), %ecx
andl $0x1, %ecx
orl %ecx, %eax
movl %eax, -0x1c(%rsp)
movl -0x1c(%rsp), %eax
shll %eax
movzbl -0x11(%rsp), %ecx
andl $0x33, %ecx
movslq %ecx, %rdx
leaq 0xc97(%rip), %rcx       # 0x2010
movzbl (%rcx,%rdx), %ecx
andl $0x1, %ecx
orl %ecx, %eax
movl %eax, -0x1c(%rsp)
movl -0x1c(%rsp), %eax
shll %eax
movzbl -0x11(%rsp), %ecx
andl $0xcc, %ecx
movslq %ecx, %rdx
leaq 0xc6f(%rip), %rcx       # 0x2010
movzbl (%rcx,%rdx), %ecx
andl $0x1, %ecx
orl %ecx, %eax
movl %eax, -0x1c(%rsp)
movl -0x1c(%rsp), %eax
shll %eax
movzbl -0x11(%rsp), %ecx
andl $0x55, %ecx
movslq %ecx, %rdx
leaq 0xc4a(%rip), %rcx       # 0x2010
movzbl (%rcx,%rdx), %ecx
andl $0x1, %ecx
orl %ecx, %eax
movl %eax, -0x1c(%rsp)
movl -0x1c(%rsp), %eax
shll %eax
movzbl -0x11(%rsp), %ecx
andl $0xaa, %ecx
movslq %ecx, %rdx
leaq 0xc22(%rip), %rcx       # 0x2010
movzbl (%rcx,%rdx), %ecx
andl $0x1, %ecx
orl %ecx, %eax
movl %eax, -0x1c(%rsp)
movl -0x1c(%rsp), %eax
xorl $0xffffff, %eax         # imm = 0xFFFFFF
retq
nopw %cs:(%rax,%rax)