// File: /workspace/github_cpp_makefile_star2_O3/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 %r15
pushq %r14
pushq %r12
pushq %rbx
movq 0xc8(%rdi), %rax
movzwl 0x14(%rsi), %r10d
addq (%rsi), %rax
cmpb $0x0, (%rdi)
je 0x1df7d
cmpw $0x8, %r10w
jl 0x1e0f7
movabsq $0x5555555555555555, %rdi # imm = 0x5555555555555555
xorl %ecx, %ecx
movdqa 0xe1c4(%rip), %xmm0     # 0x2c0a0
movq %rcx, %r8
movq (%rax,%rcx), %rcx
movq %rcx, %r9
notq %r9
movq %r9, %r10
shrq %r10
movq %r9, %r11
andq %rdi, %r11
andq %r10, %r11
popcntq %r11, %r10
movq %rcx, %r11
shrq %r11
andq %rdi, %r11
movq %r11, %rbx
xorq %rdi, %rbx
andq %rcx, %rbx
popcntq %rbx, %r14
movq %r10, %xmm1
movq %r14, %xmm2
punpcklqdq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0]
pand %xmm0, %xmm1
movdqu (%rdx), %xmm2
paddq %xmm1, %xmm2
movdqu 0x10(%rdx), %xmm1
movdqu %xmm2, (%rdx)
andq %r11, %r9
popcntq %r9, %r10
andq %rcx, %r11
popcntq %r11, %rcx
movq %rcx, %xmm2
movq %r10, %xmm3
punpcklqdq %xmm2, %xmm3    # xmm3 = xmm3[0],xmm2[0]
pand %xmm0, %xmm3
paddq %xmm1, %xmm3
movdqu %xmm3, 0x10(%rdx)
leaq 0x8(%r8), %rcx
movswq 0x14(%rsi), %r10
addq $0xf, %r8
cmpq %r10, %r8
jl 0x1dedc
jmp 0x1e0f9
cmpw $0x8, %r10w
jl 0x1e0f7
movabsq $0x5555555555555555, %rdi # imm = 0x5555555555555555
movabsq $0x1111111111111111, %r8 # imm = 0x1111111111111111
movdqu (%rdx), %xmm0
movdqu 0x10(%rdx), %xmm1
xorl %ecx, %ecx
movdqa 0xe0d1(%rip), %xmm2     # 0x2c080
movdqa 0xe0d9(%rip), %xmm3     # 0x2c090
movq %rcx, %r9
movq (%rax,%rcx), %r10
movq %r10, %rcx
notq %rcx
movq %rcx, %rbx
shrq %rbx
andq %rcx, %rbx
movq %rbx, %r14
andq %r8, %r14
shrq $0x2, %rbx
andq %r8, %rbx
movq %r10, %r11
shrq %r11
movq %r11, %r15
xorq %rdi, %r15
andq %r10, %r15
movq %r15, %r12
andq %r8, %r12
shrq $0x2, %r15
andq %r8, %r15
movq %r15, %xmm4
movq %rbx, %xmm5
punpcklqdq %xmm4, %xmm5    # xmm5 = xmm5[0],xmm4[0]
movq %r12, %xmm4
movq %r14, %xmm6
punpcklqdq %xmm4, %xmm6    # xmm6 = xmm6[0],xmm4[0]
paddq %xmm5, %xmm6
movdqa %xmm6, %xmm4
psrlq $0x4, %xmm4
paddq %xmm6, %xmm4
pand %xmm2, %xmm4
movdqa %xmm4, %xmm5
psrlq $0x8, %xmm5
paddq %xmm4, %xmm5
movdqa %xmm5, %xmm4
psrlq $0x10, %xmm4
paddq %xmm5, %xmm4
movdqa %xmm4, %xmm5
psrlq $0x20, %xmm5
paddq %xmm4, %xmm5
pand %xmm3, %xmm5
paddq %xmm5, %xmm0
movdqu %xmm0, (%rdx)
andq %r11, %rcx
movq %rcx, %rbx
andq %r8, %rbx
shrq $0x2, %rcx
andq %r8, %rcx
andq %r10, %r11
movq %r11, %r10
andq %r8, %r10
shrq $0x2, %r11
andq %r8, %r11
movq %r11, %xmm4
movq %rcx, %xmm5
punpcklqdq %xmm4, %xmm5    # xmm5 = xmm5[0],xmm4[0]
movq %r10, %xmm4
movq %rbx, %xmm6
punpcklqdq %xmm4, %xmm6    # xmm6 = xmm6[0],xmm4[0]
paddq %xmm5, %xmm6
movdqa %xmm6, %xmm4
psrlq $0x4, %xmm4
paddq %xmm6, %xmm4
pand %xmm2, %xmm4
movdqa %xmm4, %xmm5
psrlq $0x8, %xmm5
paddq %xmm4, %xmm5
movdqa %xmm5, %xmm4
psrlq $0x10, %xmm4
paddq %xmm5, %xmm4
movdqa %xmm4, %xmm5
psrlq $0x20, %xmm5
paddq %xmm4, %xmm5
pand %xmm3, %xmm5
paddq %xmm5, %xmm1
movdqu %xmm1, 0x10(%rdx)
leaq 0x8(%r9), %rcx
movswq 0x14(%rsi), %r10
addq $0xf, %r9
cmpq %r10, %r9
jl 0x1dfb7
jmp 0x1e0f9
xorl %ecx, %ecx
movswl %r10w, %edi
cmpl %edi, %ecx
jge 0x1e171
movl %ecx, %ecx
movq (%rdx), %rdi
movq 0x8(%rdx), %r8
movq 0x10(%rdx), %r9
movq 0x18(%rdx), %r10
leaq 0x19417(%rip), %r11     # 0x37530
movzbl (%rax,%rcx), %ebx
movzbl (%r11,%rbx), %ebx
addq %rbx, %rdi
movq %rdi, (%rdx)
movzbl (%rax,%rcx), %ebx
movzbl 0x100(%r11,%rbx), %ebx
addq %rbx, %r8
movq %r8, 0x8(%rdx)
movzbl (%rax,%rcx), %ebx
movzbl 0x200(%r11,%rbx), %ebx
addq %rbx, %r9
movq %r9, 0x10(%rdx)
movzbl (%rax,%rcx), %ebx
movzbl 0x300(%r11,%rbx), %ebx
addq %rbx, %r10
movq %r10, 0x18(%rdx)
incq %rcx
movswq 0x14(%rsi), %rbx
cmpq %rbx, %rcx
jl 0x1e119
movsbq 0x16(%rsi), %r8
testq %r8, %r8
jle 0x1e1f0
shlq $0xa, %r8
leaq 0x193aa(%rip), %rdi     # 0x37530
addq %rdi, %r8
movl %ecx, %ecx
movzbl (%rax,%rcx), %r9d
movzbl (%r9,%r8), %r8d
addq %r8, (%rdx)
movsbq 0x16(%rsi), %r8
movzbl (%rax,%rcx), %r9d
shlq $0xa, %r8
addq %rdi, %r8
movzbl 0x100(%r9,%r8), %r8d
addq %r8, 0x8(%rdx)
movsbq 0x16(%rsi), %r8
movzbl (%rax,%rcx), %r9d
shlq $0xa, %r8
addq %rdi, %r8
movzbl 0x200(%r9,%r8), %r8d
addq %r8, 0x10(%rdx)
movsbq 0x16(%rsi), %rsi
movzbl (%rax,%rcx), %eax
shlq $0xa, %rsi
addq %rdi, %rsi
movzbl 0x300(%rax,%rsi), %eax
addq %rax, 0x18(%rdx)
popq %rbx
popq %r12
popq %r14
popq %r15
retq