// File: /workspace/github_c_makefile_star2_O2/lh3[P]minimap2/ksw2_ll_sse.c
// Function: ksw_ll_i16
int ksw_ll_i16(void *q_, int tlen, const uint8_t *target, int _gapo, int _gape, int *qe, int *te)
{
	kswq_t *q = (kswq_t*)q_;
	int slen, i, gmax = 0, qlen8;
	__m128i zero, gapoe, gape, *H0, *H1, *E, *Hmax;
	uint16_t *H8;

#define __max_8(ret, xx) do { \
		(xx) = _mm_max_epi16((xx), _mm_srli_si128((xx), 8)); \
		(xx) = _mm_max_epi16((xx), _mm_srli_si128((xx), 4)); \
		(xx) = _mm_max_epi16((xx), _mm_srli_si128((xx), 2)); \
		(ret) = _mm_extract_epi16((xx), 0); \
	} while (0)

	// initialization
	*qe = *te = -1;
	zero = _mm_set1_epi32(0);
	gapoe = _mm_set1_epi16(_gapo + _gape);
	gape = _mm_set1_epi16(_gape);
	H0 = q->H0; H1 = q->H1; E = q->E; Hmax = q->Hmax;
	slen = q->slen, qlen8 = slen * 8;
	memset(E,    0, slen * sizeof(__m128i));
	memset(H0,   0, slen * sizeof(__m128i));
	memset(Hmax, 0, slen * sizeof(__m128i));
	// the core loop
	for (i = 0; i < tlen; ++i) {
		int j, k, imax;
		__m128i e, h, f = zero, max = zero, *S = q->qp + target[i] * slen; // s is the 1st score vector
		h = _mm_load_si128(H0 + slen - 1); // h={2,5,8,11,14,17,-1,-1} in the above example
		h = _mm_slli_si128(h, 2);
		for (j = 0; LIKELY(j < slen); ++j) {
			h = _mm_adds_epi16(h, *S++);
			e = _mm_load_si128(E + j);
			h = _mm_max_epi16(h, e);
			h = _mm_max_epi16(h, f);
			max = _mm_max_epi16(max, h);
			_mm_store_si128(H1 + j, h);
			h = _mm_subs_epu16(h, gapoe);
			e = _mm_subs_epu16(e, gape);
			e = _mm_max_epi16(e, h);
			_mm_store_si128(E + j, e);
			f = _mm_subs_epu16(f, gape);
			f = _mm_max_epi16(f, h);
			h = _mm_load_si128(H0 + j);
		}
		for (k = 0; LIKELY(k < 8); ++k) {
			f = _mm_slli_si128(f, 2);
			for (j = 0; LIKELY(j < slen); ++j) {
				h = _mm_load_si128(H1 + j);
				h = _mm_max_epi16(h, f);
				_mm_store_si128(H1 + j, h);
				h = _mm_subs_epu16(h, gapoe);
				f = _mm_subs_epu16(f, gape);
				if(UNLIKELY(!_mm_movemask_epi8(_mm_cmpgt_epi16(f, h)))) goto end_loop_i16;
			}
		}
end_loop_i16:
		__max_8(imax, max);
		if (imax >= gmax) {
			gmax = imax; *te = i;
			memcpy(Hmax, H1, slen * sizeof(__m128i));
		}
		S = H1; H1 = H0; H0 = S;
	}
	for (i = 0, H8 = (uint16_t*)Hmax; i < qlen8; ++i)
		if ((int)H8[i] == gmax) *qe = i / 8 + i % 8 * slen;
	return gmax;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq 0xa0(%rsp), %rax
orl $-0x1, (%rax)
movq %rdx, 0x38(%rsp)
movq %r9, 0x20(%rsp)
orl $-0x1, (%r9)
movq %rsi, 0x8(%rsp)
addl %r8d, %ecx
movd %ecx, %xmm0
pshuflw $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0,4,5,6,7]
pshufd $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
movdqa %xmm0, 0x50(%rsp)
movd %r8d, %xmm0
pshuflw $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0,4,5,6,7]
pshufd $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
movdqa %xmm0, 0x40(%rsp)
movq 0x18(%rdi), %r12
movq 0x20(%rdi), %r15
movq 0x28(%rdi), %rbx
movq 0x30(%rdi), %r13
movq %rdi, 0x30(%rsp)
movslq 0x4(%rdi), %rbp
movq %rbp, %r14
shlq $0x4, %r14
movq %rbx, %rdi
xorl %esi, %esi
movq %r14, %rdx
callq 0x21b0
movq %r12, %rdi
xorl %esi, %esi
movq %r14, %rdx
callq 0x21b0
movq %r13, 0x10(%rsp)
movq %r13, %rdi
xorl %esi, %esi
movq %r14, 0x18(%rsp)
movq %r14, %rdx
callq 0x21b0
xorl %r14d, %r14d
movq 0x8(%rsp), %rdi
movq %rbp, %r10
testl %r10d, %r10d
movl $0x0, %r13d
cmovgl %r10d, %r13d
testl %edi, %edi
cmovlel %r14d, %edi
shlq $0x4, %r13
xorl %eax, %eax
movq %rdi, 0x8(%rsp)
movq %rbp, 0x28(%rsp)
cmpq %rdi, %r14
je 0x1c0e4
movq %r15, %rbp
movq 0x38(%rsp), %rcx
movzbl (%rcx,%r14), %ecx
imull %r10d, %ecx
movslq %ecx, %rcx
shlq $0x4, %rcx
movq 0x30(%rsp), %rdx
addq 0x10(%rdx), %rcx
movq 0x18(%rsp), %rdx
movdqa -0x10(%r12,%rdx), %xmm2
pslldq $0x2, %xmm2             # xmm2 = zero,zero,xmm2[0,1,2,3,4,5,6,7,8,9,10,11,12,13]
pxor %xmm0, %xmm0
xorl %edx, %edx
pxor %xmm1, %xmm1
movdqa 0x50(%rsp), %xmm5
movdqa 0x40(%rsp), %xmm6
cmpq %rdx, %r13
je 0x1c035
paddsw (%rcx,%rdx), %xmm2
movdqa (%rbx,%rdx), %xmm3
movdqa %xmm3, %xmm4
pmaxsw %xmm0, %xmm4
pmaxsw %xmm2, %xmm4
pmaxsw %xmm4, %xmm1
movdqa %xmm4, (%rbp,%rdx)
psubusw %xmm5, %xmm4
psubusw %xmm6, %xmm3
pmaxsw %xmm4, %xmm3
movdqa %xmm3, (%rbx,%rdx)
psubusw %xmm6, %xmm0
pmaxsw %xmm4, %xmm0
movdqa (%r12,%rdx), %xmm2
addq $0x10, %rdx
jmp 0x1bfeb
xorl %ecx, %ecx
cmpl $0x8, %ecx
je 0x1c07a
pslldq $0x2, %xmm0             # xmm0 = zero,zero,xmm0[0,1,2,3,4,5,6,7,8,9,10,11,12,13]
xorl %edx, %edx
cmpq %rdx, %r13
je 0x1c076
movdqa (%rbp,%rdx), %xmm2
pmaxsw %xmm0, %xmm2
movdqa %xmm2, (%rbp,%rdx)
psubusw %xmm5, %xmm2
psubusw %xmm6, %xmm0
movdqa %xmm0, %xmm3
pcmpgtw %xmm2, %xmm3
pmovmskb %xmm3, %esi
testl %esi, %esi
je 0x1c07a
addq $0x10, %rdx
jmp 0x1c043
incl %ecx
jmp 0x1c037
movdqa %xmm1, %xmm0
psrldq $0x8, %xmm0             # xmm0 = xmm0[8,9,10,11,12,13,14,15],zero,zero,zero,zero,zero,zero,zero,zero
pmaxsw %xmm1, %xmm0
movdqa %xmm0, %xmm1
psrldq $0x4, %xmm1             # xmm1 = xmm1[4,5,6,7,8,9,10,11,12,13,14,15],zero,zero,zero,zero
pmaxsw %xmm0, %xmm1
movdqa %xmm1, %xmm0
psrldq $0x2, %xmm0             # xmm0 = xmm0[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero
pmaxsw %xmm1, %xmm0
pextrw $0x0, %xmm0, %r15d
cmpl %r15d, %eax
ja 0x1c0d6
movq 0xa0(%rsp), %rax
movl %r14d, (%rax)
movq 0x10(%rsp), %rdi
movq %rbp, %rsi
movq 0x18(%rsp), %rdx
callq 0x22a0
movq 0x8(%rsp), %rdi
movq 0x28(%rsp), %r10
movl %r15d, %eax
incq %r14
movq %r12, %r15
movq %rbp, %r12
jmp 0x1bf9a
leal (,%r10,8), %ecx
xorl %edx, %edx
testl %ecx, %ecx
cmovlel %edx, %ecx
movq 0x20(%rsp), %r8
movq 0x10(%rsp), %r9
cmpq %rdx, %rcx
je 0x1c123
movzwl (%r9,%rdx,2), %esi
cmpl %esi, %eax
jne 0x1c11e
movl %edx, %esi
shrl $0x3, %esi
movl %edx, %edi
andl $0x7, %edi
imull %r10d, %edi
addl %esi, %edi
movl %edi, (%r8)
incq %rdx
jmp 0x1c0fd
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop