// File: /workspace/github_c_makefile_star2_O0/nh13[P]ksw/src/parasail/contrib/ssw/ssw.c
// Function: ssw_align
s_align* ssw_align (const s_profile* prof,
					const int8_t* ref,
				  	int32_t refLen,
				  	const uint8_t weight_gapO,
				  	const uint8_t weight_gapE,
					const uint8_t flag,	/*  (from high to low) bit 5: return the best alignment beginning position; 6: if (ref_end1 - ref_begin1 <= filterd) && (read_end1 - read_begin1 <= filterd), return cigar; 7: if max score >= filters, return cigar; 8: always return cigar; if 6 & 7 are both setted, only return cigar when both filter fulfilled */
					const uint16_t filters,
					const int32_t filterd,
					const int32_t maskLen) {

	alignment_end* bests = 0, *bests_reverse = 0;
	__m128i* vP = 0;
	int32_t word = 0, band_width = 0, readLen = prof->readLen;
	int8_t* read_reverse = 0;
	cigar* path;
	s_align* r = (s_align*)calloc(1, sizeof(s_align));
	r->ref_begin1 = -1;
	r->read_begin1 = -1;
	r->cigar = 0;
	r->cigarLen = 0;
	if (maskLen < 15) {
		fprintf(stderr, "When maskLen < 15, the function ssw_align doesn't return 2nd best alignment information.\n");
	}

	// Find the alignment scores and ending positions
	if (prof->profile_byte) {
		bests = sw_sse2_byte(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_byte, -1, prof->bias, maskLen);
		if (prof->profile_word && bests[0].score == 255) {
            r->saturated = 1;
			free(bests);
			bests = sw_sse2_word(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_word, -1, maskLen);
			word = 1;
		} else if (bests[0].score == 255) {
			fprintf(stderr, "Please set 2 to the score_size parameter of the function ssw_init, otherwise the alignment results will be incorrect.\n");
			free(r);
			return NULL;
		}
	}else if (prof->profile_word) {
		bests = sw_sse2_word(ref, 0, refLen, readLen, weight_gapO, weight_gapE, prof->profile_word, -1, maskLen);
		word = 1;
	}else {
		fprintf(stderr, "Please call the function ssw_init before ssw_align.\n");
		free(r);
		return NULL;
	}
	r->score1 = bests[0].score;
	r->ref_end1 = bests[0].ref;
	r->read_end1 = bests[0].read;
	if (maskLen >= 15) {
		r->score2 = bests[1].score;
		r->ref_end2 = bests[1].ref;
	} else {
		r->score2 = 0;
		r->ref_end2 = -1;
	}
	free(bests);
	if (flag == 0 || (flag == 2 && r->score1 < filters)) goto end;

	// Find the beginning position of the best alignment.
	read_reverse = seq_reverse(prof->read, r->read_end1);
	if (word == 0) {
		vP = qP_byte(read_reverse, prof->mat, r->read_end1 + 1, prof->n, prof->bias);
		bests_reverse = sw_sse2_byte(ref, 1, r->ref_end1 + 1, r->read_end1 + 1, weight_gapO, weight_gapE, vP, r->score1, prof->bias, maskLen);
	} else {
		vP = qP_word(read_reverse, prof->mat, r->read_end1 + 1, prof->n);
		bests_reverse = sw_sse2_word(ref, 1, r->ref_end1 + 1, r->read_end1 + 1, weight_gapO, weight_gapE, vP, r->score1, maskLen);
	}
	free(vP);
	free(read_reverse);
	r->ref_begin1 = bests_reverse[0].ref;
	r->read_begin1 = r->read_end1 - bests_reverse[0].read;
	free(bests_reverse);
	if ((7&flag) == 0 || ((2&flag) != 0 && r->score1 < filters) || ((4&flag) != 0 && (r->ref_end1 - r->ref_begin1 > filterd || r->read_end1 - r->read_begin1 > filterd))) goto end;

	// Generate cigar.
	refLen = r->ref_end1 - r->ref_begin1 + 1;
	readLen = r->read_end1 - r->read_begin1 + 1;
	band_width = abs(refLen - readLen) + 1;
	path = banded_sw(ref + r->ref_begin1, prof->read + r->read_begin1, refLen, readLen, r->score1, weight_gapO, weight_gapE, band_width, prof->mat, prof->n);
	if (path == 0) {
		free(r);
		r = NULL;
	}
	else {
		r->cigar = path->seq;
		r->cigarLen = path->length;
		free(path);
	}

end:
	return r;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
subq $0x98, %rsp
movl %r8d, -0x7c(%rbp)
movl %ecx, %eax
movl -0x7c(%rbp), %ecx
movl %eax, -0x78(%rbp)
movl %edx, %eax
movl -0x78(%rbp), %edx
movl %eax, -0x74(%rbp)
movq %rsi, %rax
movl -0x74(%rbp), %esi
movq %rax, -0x70(%rbp)
movq %rdi, %r8
movq -0x70(%rbp), %rdi
movb %r9b, %al
movl 0x20(%rbp), %r9d
movl 0x18(%rbp), %r9d
movw 0x10(%rbp), %r9w
movq %r8, -0x18(%rbp)
movq %rdi, -0x20(%rbp)
movl %esi, -0x24(%rbp)
movb %dl, -0x25(%rbp)
movb %cl, -0x26(%rbp)
movb %al, -0x27(%rbp)
movq $0x0, -0x30(%rbp)
movq $0x0, -0x38(%rbp)
movq $0x0, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
movl $0x0, -0x48(%rbp)
movq -0x18(%rbp), %rax
movl 0x20(%rax), %eax
movl %eax, -0x4c(%rbp)
movq $0x0, -0x58(%rbp)
movl $0x1, %edi
movl $0x28, %esi
callq 0x29b0c0
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movl $0xffffffff, 0x4(%rax)  # imm = 0xFFFFFFFF
movq -0x68(%rbp), %rax
movl $0xffffffff, 0xc(%rax)  # imm = 0xFFFFFFFF
movq -0x68(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x68(%rbp), %rax
movl $0x0, 0x20(%rax)
cmpl $0xf, 0x20(%rbp)
jge 0x29ccfb
movq 0xc902f6(%rip), %rax    # 0xf2cfe0
movq (%rax), %rdi
leaq 0xacf74c(%rip), %rsi    # 0xd6c440
movb $0x0, %al
callq 0x29b1b0
movq -0x18(%rbp), %rax
cmpq $0x0, (%rax)
je 0x29ce12
movq -0x20(%rbp), %rdi
movl -0x24(%rbp), %edx
movl -0x4c(%rbp), %ecx
movb -0x25(%rbp), %r8b
movb -0x26(%rbp), %r9b
movq -0x18(%rbp), %rax
movq (%rax), %r11
movq -0x18(%rbp), %rax
movb 0x28(%rax), %r10b
movl 0x20(%rbp), %eax
xorl %esi, %esi
movzbl %r8b, %r8d
movzbl %r9b, %r9d
movq %r11, (%rsp)
movl $0xff, 0x8(%rsp)
movzbl %r10b, %r10d
movl %r10d, 0x10(%rsp)
movl %eax, 0x18(%rsp)
callq 0x29d200
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x29cdcf
movq -0x30(%rbp), %rax
movzwl (%rax), %eax
cmpl $0xff, %eax
jne 0x29cdcf
movq -0x68(%rbp), %rax
movl $0x1, 0x24(%rax)
movq -0x30(%rbp), %rdi
callq 0x29b160
movq -0x20(%rbp), %rdi
movl -0x24(%rbp), %edx
movl -0x4c(%rbp), %ecx
movb -0x25(%rbp), %r8b
movb -0x26(%rbp), %r9b
movq -0x18(%rbp), %rax
movq 0x8(%rax), %r10
movl 0x20(%rbp), %eax
xorl %esi, %esi
movzbl %r8b, %r8d
movzbl %r9b, %r9d
movq %r10, (%rsp)
movl $0xffff, 0x8(%rsp)      # imm = 0xFFFF
movl %eax, 0x10(%rsp)
callq 0x29e5c0
movq %rax, -0x30(%rbp)
movl $0x1, -0x44(%rbp)
jmp 0x29ce0d
movq -0x30(%rbp), %rax
movzwl (%rax), %eax
cmpl $0xff, %eax
jne 0x29ce0b
movq 0xc901fc(%rip), %rax    # 0xf2cfe0
movq (%rax), %rdi
leaq 0xacf6ac(%rip), %rsi    # 0xd6c49a
movb $0x0, %al
callq 0x29b1b0
movq -0x68(%rbp), %rdi
callq 0x29b160
movq $0x0, -0x10(%rbp)
jmp 0x29d1e9
jmp 0x29ce0d
jmp 0x29ce96
movq -0x18(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x29ce66
movq -0x20(%rbp), %rdi
movl -0x24(%rbp), %edx
movl -0x4c(%rbp), %ecx
movb -0x25(%rbp), %r8b
movb -0x26(%rbp), %r9b
movq -0x18(%rbp), %rax
movq 0x8(%rax), %r10
movl 0x20(%rbp), %eax
xorl %esi, %esi
movzbl %r8b, %r8d
movzbl %r9b, %r9d
movq %r10, (%rsp)
movl $0xffff, 0x8(%rsp)      # imm = 0xFFFF
movl %eax, 0x10(%rsp)
callq 0x29e5c0
movq %rax, -0x30(%rbp)
movl $0x1, -0x44(%rbp)
jmp 0x29ce94
movq 0xc90173(%rip), %rax    # 0xf2cfe0
movq (%rax), %rdi
leaq 0xacf69a(%rip), %rsi    # 0xd6c511
movb $0x0, %al
callq 0x29b1b0
movq -0x68(%rbp), %rdi
callq 0x29b160
movq $0x0, -0x10(%rbp)
jmp 0x29d1e9
jmp 0x29ce96
movq -0x30(%rbp), %rax
movw (%rax), %cx
movq -0x68(%rbp), %rax
movw %cx, (%rax)
movq -0x30(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x68(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x30(%rbp), %rax
movl 0x8(%rax), %ecx
movq -0x68(%rbp), %rax
movl %ecx, 0x10(%rax)
cmpl $0xf, 0x20(%rbp)
jl 0x29cee6
movq -0x30(%rbp), %rax
movw 0xc(%rax), %cx
movq -0x68(%rbp), %rax
movw %cx, 0x2(%rax)
movq -0x30(%rbp), %rax
movl 0x10(%rax), %ecx
movq -0x68(%rbp), %rax
movl %ecx, 0x14(%rax)
jmp 0x29cefb
movq -0x68(%rbp), %rax
movw $0x0, 0x2(%rax)
movq -0x68(%rbp), %rax
movl $0xffffffff, 0x14(%rax) # imm = 0xFFFFFFFF
movq -0x30(%rbp), %rdi
callq 0x29b160
movzbl -0x27(%rbp), %eax
cmpl $0x0, %eax
je 0x29cf25
movzbl -0x27(%rbp), %eax
cmpl $0x2, %eax
jne 0x29cf2a
movq -0x68(%rbp), %rax
movzwl (%rax), %eax
movzwl 0x10(%rbp), %ecx
cmpl %ecx, %eax
jge 0x29cf2a
jmp 0x29d1e1
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x68(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x29f590
movq %rax, -0x58(%rbp)
cmpl $0x0, -0x44(%rbp)
jne 0x29cfe6
movq -0x58(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x68(%rbp), %rax
movl 0x10(%rax), %edx
addl $0x1, %edx
movq -0x18(%rbp), %rax
movl 0x24(%rax), %ecx
movq -0x18(%rbp), %rax
movzbl 0x28(%rax), %r8d
callq 0x29c970
movq %rax, -0x40(%rbp)
movq -0x20(%rbp), %rdi
movq -0x68(%rbp), %rax
movl 0x8(%rax), %edx
addl $0x1, %edx
movq -0x68(%rbp), %rax
movl 0x10(%rax), %ecx
addl $0x1, %ecx
movb -0x25(%rbp), %r8b
movb -0x26(%rbp), %r9b
movq -0x40(%rbp), %rbx
movq -0x68(%rbp), %rax
movw (%rax), %ax
movb %al, %r11b
movq -0x18(%rbp), %rax
movb 0x28(%rax), %r10b
movl 0x20(%rbp), %eax
movl $0x1, %esi
movzbl %r8b, %r8d
movzbl %r9b, %r9d
movq %rbx, (%rsp)
movzbl %r11b, %r11d
movl %r11d, 0x8(%rsp)
movzbl %r10b, %r10d
movl %r10d, 0x10(%rsp)
movl %eax, 0x18(%rsp)
callq 0x29d200
movq %rax, -0x38(%rbp)
jmp 0x29d062
movq -0x58(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x68(%rbp), %rax
movl 0x10(%rax), %edx
addl $0x1, %edx
movq -0x18(%rbp), %rax
movl 0x24(%rax), %ecx
callq 0x29caa0
movq %rax, -0x40(%rbp)
movq -0x20(%rbp), %rdi
movq -0x68(%rbp), %rax
movl 0x8(%rax), %edx
addl $0x1, %edx
movq -0x68(%rbp), %rax
movl 0x10(%rax), %ecx
addl $0x1, %ecx
movb -0x25(%rbp), %r8b
movb -0x26(%rbp), %r9b
movq -0x40(%rbp), %r11
movq -0x68(%rbp), %rax
movw (%rax), %r10w
movl 0x20(%rbp), %eax
movl $0x1, %esi
movzbl %r8b, %r8d
movzbl %r9b, %r9d
movq %r11, (%rsp)
movzwl %r10w, %r10d
movl %r10d, 0x8(%rsp)
movl %eax, 0x10(%rsp)
callq 0x29e5c0
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rdi
callq 0x29b160
movq -0x58(%rbp), %rdi
callq 0x29b160
movq -0x38(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x68(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x68(%rbp), %rax
movl 0x10(%rax), %ecx
movq -0x38(%rbp), %rax
subl 0x8(%rax), %ecx
movq -0x68(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0x38(%rbp), %rdi
callq 0x29b160
movzbl -0x27(%rbp), %eax
andl $0x7, %eax
cmpl $0x0, %eax
je 0x29d0f9
movzbl -0x27(%rbp), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x29d0c7
movq -0x68(%rbp), %rax
movzwl (%rax), %eax
movzwl 0x10(%rbp), %ecx
cmpl %ecx, %eax
jl 0x29d0f9
movzbl -0x27(%rbp), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x29d0fe
movq -0x68(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x68(%rbp), %rcx
subl 0x4(%rcx), %eax
cmpl 0x18(%rbp), %eax
jg 0x29d0f9
movq -0x68(%rbp), %rax
movl 0x10(%rax), %eax
movq -0x68(%rbp), %rcx
subl 0xc(%rcx), %eax
cmpl 0x18(%rbp), %eax
jle 0x29d0fe
jmp 0x29d1e1
movq -0x68(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x68(%rbp), %rcx
subl 0x4(%rcx), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
movq -0x68(%rbp), %rax
movl 0x10(%rax), %eax
movq -0x68(%rbp), %rcx
subl 0xc(%rcx), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
movl -0x24(%rbp), %eax
subl -0x4c(%rbp), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
movq -0x20(%rbp), %rdi
movq -0x68(%rbp), %rax
movslq 0x4(%rax), %rax
addq %rax, %rdi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rsi
movq -0x68(%rbp), %rax
movslq 0xc(%rax), %rax
addq %rax, %rsi
movl -0x24(%rbp), %edx
movl -0x4c(%rbp), %ecx
movq -0x68(%rbp), %rax
movzwl (%rax), %r8d
movzbl -0x25(%rbp), %r9d
movzbl -0x26(%rbp), %ebx
movl -0x48(%rbp), %r11d
movq -0x18(%rbp), %rax
movq 0x18(%rax), %r10
movq -0x18(%rbp), %rax
movl 0x24(%rax), %eax
movl %ebx, (%rsp)
movl %r11d, 0x8(%rsp)
movq %r10, 0x10(%rsp)
movl %eax, 0x18(%rsp)
callq 0x29f620
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
jne 0x29d1b9
movq -0x68(%rbp), %rdi
callq 0x29b160
movq $0x0, -0x68(%rbp)
jmp 0x29d1df
movq -0x60(%rbp), %rax
movq (%rax), %rcx
movq -0x68(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x60(%rbp), %rax
movl 0x8(%rax), %ecx
movq -0x68(%rbp), %rax
movl %ecx, 0x20(%rax)
movq -0x60(%rbp), %rdi
callq 0x29b160
jmp 0x29d1e1
movq -0x68(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
addq $0x98, %rsp
popq %rbx
popq %rbp
retq
nopw (%rax,%rax)