// File: BenLangmead[P]bowtie/./ebwt.h
// Function: Ebwt::countUpTo(SideLocus const&, int) const
inline TIndexOffU Ebwt::countUpTo(const SideLocus& l, int c) const {
	// Count occurrences of c in each 64-bit (using bit trickery);
	// Someday countInU64() and pop() functions should be
	// vectorized/SSE-ized in case that helps.
	TIndexOffU cCnt = 0;
	const uint8_t *side = l.side(this->_ebwt);
	int i = 0;
#if 1
    #ifdef POPCNT_CAPABILITY
    if ( _usePOPCNTinstruction) {
        for(; i + 7 < l._by; i += 8) {
            cCnt += countInU64<USE_POPCNT_INSTRUCTION>(c, *(uint64_t*)&side[i]);
        }
    }
    else {
        for(; i + 7 < l._by; i += 8) {
            cCnt += countInU64<USE_POPCNT_GENERIC>(c, *(uint64_t*)&side[i]);
        }
    }
    #else
    for(; i + 7 < l._by; i += 8) {
        cCnt += countInU64(c, *(uint64_t*)&side[i]);
    }
    #endif
#else
	for(; i + 2 < l._by; i += 2) {
		cCnt += cCntLUT_16b_4[c][*(uint16_t*)&side[i]];
	}
#endif
#ifdef SIXTY4_FORMAT
	// Calculate number of bit pairs to shift off the end
	const int bpShiftoff = 32 - (((l._by & 7) << 2) + l._bp);
	if(bpShiftoff < 32) {
		assert_lt(bpShiftoff, 32);
		const uint64_t sw = (*(uint64_t*)&side[i]) << (bpShiftoff << 1);

        #ifdef POPCNT_CAPABILITY
        if (_usePOPCNTinstruction) {
            cCnt += countInU64<USE_POPCNT_INSTRUCTION>(c, sw);
        }
        else {
            cCnt += countInU64<USE_POPCNT_GENERIC>(c, sw);
        }
        #else
		cCnt += countInU64(c, sw);
        #endif

		if(c == 0) cCnt -= bpShiftoff; // we turned these into As
	}
#else
	// Count occurences of c in the rest of the side (using LUT)
	for(; i < l._by; i++) {
		cCnt += cCntLUT_4[0][c][side[i]];
	}
	// Count occurences of c in the rest of the byte
	if(l._bp > 0) {
		cCnt += cCntLUT_4[(int)l._bp][c][side[i]];
	}
#endif
	return cCnt;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x38(%rbp)
movq $0x0, -0x20(%rbp)
movq -0x10(%rbp), %rdi
movq 0xc8(%rax), %rsi
callq 0x23610
movq %rax, %rcx
movq -0x38(%rbp), %rax
movq %rcx, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
testb $0x1, (%rax)
je 0x26559
jmp 0x2651c
movl -0x2c(%rbp), %eax
addl $0x7, %eax
movq -0x10(%rbp), %rcx
movswl 0x14(%rcx), %ecx
cmpl %ecx, %eax
jge 0x26557
movl -0x14(%rbp), %edi
movq -0x28(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq (%rax,%rcx), %rsi
callq 0x11ff0
cltq
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
movl -0x2c(%rbp), %eax
addl $0x8, %eax
movl %eax, -0x2c(%rbp)
jmp 0x2651c
jmp 0x26598
jmp 0x2655b
movl -0x2c(%rbp), %eax
addl $0x7, %eax
movq -0x10(%rbp), %rcx
movswl 0x14(%rcx), %ecx
cmpl %ecx, %eax
jge 0x26596
movl -0x14(%rbp), %edi
movq -0x28(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq (%rax,%rcx), %rsi
callq 0x12060
cltq
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
movl -0x2c(%rbp), %eax
addl $0x8, %eax
movl %eax, -0x2c(%rbp)
jmp 0x2655b
jmp 0x26598
jmp 0x2659a
movl -0x2c(%rbp), %eax
movq -0x10(%rbp), %rcx
movswl 0x14(%rcx), %ecx
cmpl %ecx, %eax
jge 0x265de
movslq -0x14(%rbp), %rcx
leaq 0x2405c(%rip), %rax     # 0x4a610
shlq $0x8, %rcx
addq %rcx, %rax
movq -0x28(%rbp), %rcx
movslq -0x2c(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
movzbl (%rax,%rcx), %eax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x2659a
movq -0x10(%rbp), %rax
movsbl 0x16(%rax), %eax
cmpl $0x0, %eax
jle 0x26627
movq -0x10(%rbp), %rax
movsbl 0x16(%rax), %eax
movslq %eax, %rcx
leaq 0x24013(%rip), %rax     # 0x4a610
shlq $0xa, %rcx
addq %rcx, %rax
movslq -0x14(%rbp), %rcx
shlq $0x8, %rcx
addq %rcx, %rax
movq -0x28(%rbp), %rcx
movslq -0x2c(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
movzbl (%rax,%rcx), %eax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)