// File: BenLangmead[P]bowtie/./ebwt.h
// Function: Ebwt::countUpToEx(SideLocus const&, unsigned long*) const
inline void Ebwt::countUpToEx(const SideLocus& l, TIndexOffU* arrs) const {
	int i = 0;
	// Count occurrences of c in each 64-bit (using bit trickery);
	// note: this seems does not seem to lend a significant boost to
	// performance.  If you comment out this whole loop (which won't
	// affect correctness - it will just cause the following loop to
	// take up the slack) then runtime does not change noticeably.
	// Someday the countInU64() and pop() functions should be
	// vectorized/SSE-ized in case that helps.
	const uint8_t *side = l.side(this->_ebwt);

#ifdef POPCNT_CAPABILITY
    if (_usePOPCNTinstruction) {
        for(; i+7 < l._by; i += 8) {
            countInU64Ex<USE_POPCNT_INSTRUCTION>(*(uint64_t*)&side[i], arrs);
        }
    }
    else {
        for(; i+7 < l._by; i += 8) {
            countInU64Ex<USE_POPCNT_GENERIC>(*(uint64_t*)&side[i], arrs);
        }
    }
#else
	for(; i+7 < l._by; i += 8) {
		countInU64Ex(*(uint64_t*)&side[i], arrs);
	}
#endif

#ifdef SIXTY4_FORMAT
	// Calculate number of bit pairs to shift off the end
	const int bpShiftoff = 32 - (((l._by & 7) << 2) + l._bp);
	assert_leq(bpShiftoff, 32);
	if(bpShiftoff < 32) {
		const uint64_t sw = (*(uint64_t*)&l.side(this->_ebwt)[i]) << (bpShiftoff << 1);

#ifdef POPCNT_CAPABILITY
        if (_usePOPCNTinstruction) {
            countInU64Ex<USE_POPCNT_INSTRUCTION>(sw, arrs);
        }
        else{
            countInU64Ex<USE_POPCNT_GENERIC>(sw, arrs);
        }
#else
		countInU64Ex(sw, arrs);
#endif

		arrs[0] -= bpShiftoff;
	}
#else
	// Count occurences of c in the rest of the side (using LUT)
	for(; i < l._by; i++) {
		arrs[0] += cCntLUT_4[0][0][side[i]];
		arrs[1] += cCntLUT_4[0][1][side[i]];
		arrs[2] += cCntLUT_4[0][2][side[i]];
		arrs[3] += cCntLUT_4[0][3][side[i]];
	}
	// Count occurences of c in the rest of the byte
	if(l._bp > 0) {
		arrs[0] += cCntLUT_4[(int)l._bp][0][side[i]];
		arrs[1] += cCntLUT_4[(int)l._bp][1][side[i]];
		arrs[2] += cCntLUT_4[(int)l._bp][2][side[i]];
		arrs[3] += cCntLUT_4[(int)l._bp][3][side[i]];
	}
#endif
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x30(%rbp)
movl $0x0, -0x1c(%rbp)
movq -0x10(%rbp), %rdi
movq 0xc8(%rax), %rsi
callq 0x23610
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, -0x28(%rbp)
testb $0x1, (%rax)
je 0x2ac39
jmp 0x2ac05
movl -0x1c(%rbp), %eax
addl $0x7, %eax
movq -0x10(%rbp), %rcx
movswl 0x14(%rcx), %ecx
cmpl %ecx, %eax
jge 0x2ac37
movq -0x28(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx), %rdi
movq -0x18(%rbp), %rsi
callq 0x120d0
movl -0x1c(%rbp), %eax
addl $0x8, %eax
movl %eax, -0x1c(%rbp)
jmp 0x2ac05
jmp 0x2ac6f
jmp 0x2ac3b
movl -0x1c(%rbp), %eax
addl $0x7, %eax
movq -0x10(%rbp), %rcx
movswl 0x14(%rcx), %ecx
cmpl %ecx, %eax
jge 0x2ac6d
movq -0x28(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx), %rdi
movq -0x18(%rbp), %rsi
callq 0x12270
movl -0x1c(%rbp), %eax
addl $0x8, %eax
movl %eax, -0x1c(%rbp)
jmp 0x2ac3b
jmp 0x2ac6f
jmp 0x2ac71
movl -0x1c(%rbp), %eax
movq -0x10(%rbp), %rcx
movswl 0x14(%rcx), %ecx
cmpl %ecx, %eax
jge 0x2ad38
movq -0x28(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x1f977(%rip), %rax     # 0x4a610
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x1f952(%rip), %rax     # 0x4a610
movzbl 0x100(%rax,%rcx), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
addq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
movq -0x28(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x1f927(%rip), %rax     # 0x4a610
movzbl 0x200(%rax,%rcx), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
addq 0x10(%rax), %rcx
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x1f8fc(%rip), %rax     # 0x4a610
movzbl 0x300(%rax,%rcx), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
addq 0x18(%rax), %rcx
movq %rcx, 0x18(%rax)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x2ac71
movq -0x10(%rbp), %rax
movsbl 0x16(%rax), %eax
cmpl $0x0, %eax
jle 0x2ae2f
movq -0x10(%rbp), %rax
movsbl 0x16(%rax), %eax
movslq %eax, %rcx
leaq 0x1f8b5(%rip), %rax     # 0x4a610
shlq $0xa, %rcx
addq %rcx, %rax
movq -0x28(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movsbl 0x16(%rax), %eax
movslq %eax, %rcx
leaq 0x1f880(%rip), %rax     # 0x4a610
shlq $0xa, %rcx
addq %rcx, %rax
movq -0x28(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
movzbl 0x100(%rax,%rcx), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
addq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rax
movsbl 0x16(%rax), %eax
movslq %eax, %rcx
leaq 0x1f845(%rip), %rax     # 0x4a610
shlq $0xa, %rcx
addq %rcx, %rax
movq -0x28(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
movzbl 0x200(%rax,%rcx), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
addq 0x10(%rax), %rcx
movq %rcx, 0x10(%rax)
movq -0x10(%rbp), %rax
movsbl 0x16(%rax), %eax
movslq %eax, %rcx
leaq 0x1f80a(%rip), %rax     # 0x4a610
shlq $0xa, %rcx
addq %rcx, %rax
movq -0x28(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
movzbl 0x300(%rax,%rcx), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
addq 0x18(%rax), %rcx
movq %rcx, 0x18(%rax)
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop