// File: /workspace/github_c_makefile_star2_O1/ToniWestbrook[P]paladin/protein.c
// Function: getSequenceORF
int getSequenceORF(char * passSequence, unsigned long passLength, int passTrans, mem_opt_t * passOptions, CDS * * retCDS, unsigned long * retCount) {
	int frameIdx, addIdx, strandDir, relFrame;
	long seqIdx, absIdx, lastStart;
	long endSeqPos, endOrfPos;
	unsigned char currentCodon;
	long * history[2][6], historySize[6];

	// Initialize values
	*retCDS = NULL;
	*retCount = 0;
	for (frameIdx = 0 ; frameIdx < 6 ; frameIdx++) {
		history[0][frameIdx] = NULL;
		history[1][frameIdx] = NULL;
		historySize[frameIdx] = 0;
	}

	for (frameIdx = 0 ; frameIdx < 6 ; frameIdx++) {
		strandDir = (frameIdx < 3 ? 1 : -1);
		relFrame = frameIdx % 3;
		lastStart = relFrame;
		endSeqPos = getLastAlignedPos(passLength, relFrame);
		endOrfPos = getLastAlignedOrfPos(passLength, relFrame, passOptions);

        // Treat entire sequence as ORF in transcript mode
        if (passOptions->proteinFlag & ALIGN_FLAG_MANUAL_TRANSCRIPT) {
            addORFHistory(history, historySize, frameIdx);
            history[0][frameIdx][historySize[frameIdx] - 1] = (strandDir == 1) ? relFrame : passLength - 1 - relFrame;
            history[1][frameIdx][historySize[frameIdx] - 1] = getLastAlignedPos(passLength, frameIdx);

            if (passOptions->proteinFlag & ALIGN_FLAG_BRUTE_ORF) {
                continue;
            }

            break;
        }

		// Adjust min ORF length if requested
		if ((passOptions->proteinFlag & ALIGN_FLAG_ADJUST_ORF) && (passLength < passOptions->min_orf_len)) {
			endOrfPos = getLastAlignedPos(passLength, relFrame);
		}

		// Iterate through all codons in this read frame
		for (seqIdx = relFrame ; seqIdx + 2 <= endSeqPos ; seqIdx += 3) {
			// Calculate absolute index from relative
			absIdx = seqIdx;
			if (strandDir == -1) absIdx = absIdx * -1 + passLength - 1;

			// Encode codon
			currentCodon = encodeCodon(passSequence + absIdx, strandDir);

			// Check for stop codon or EOS
			if ((codon_aa_hash[passTrans][currentCodon] == '*') || (seqIdx + 2 == endSeqPos)) {
				if (seqIdx + relFrame + 2 - lastStart >= endOrfPos) {
					// Translate current (non-brute) or all frames (brute)
					for (addIdx = 0 ; addIdx < 6 ; addIdx++) {
						if ((passOptions->proteinFlag & ALIGN_FLAG_BRUTE_ORF) || (addIdx == frameIdx)) {
							strandDir = (addIdx < 3 ? 1 : -1);
							relFrame = addIdx % 3;

							addORFHistory(history, historySize, addIdx);
							history[0][addIdx][historySize[addIdx] - 1] = (strandDir == 1) ? relFrame : passLength - 1 - relFrame;
							history[1][addIdx][historySize[addIdx] - 1] = getLastAlignedPos(passLength, addIdx);
						}
					}

					break;
				}

				lastStart = seqIdx + 3;
			}
		}

		// If we have brute-force match, end processing
		if (frameIdx < 5) {
			if (historySize[frameIdx + 1]) break;
		}
	}

	// Convert history array into CDS entries
	compileORFHistory(history, historySize, retCDS, retCount);

	for (frameIdx = 0 ; frameIdx < 6 ; frameIdx++) {
		free(history[0][frameIdx]);
		free(history[1][frameIdx]);
	}

	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movq %rcx, %r15
movl %edx, %ecx
movq %rsi, %r12
movq %rdi, 0x48(%rsp)
xorl %ebp, %ebp
movq %r8, 0x8(%rsp)
movq %rbp, (%r8)
movq %r9, 0x10(%rsp)
movq %rbp, (%r9)
xorps %xmm0, %xmm0
leaq 0x80(%rsp), %rax
movaps %xmm0, 0x50(%rax)
movaps %xmm0, 0x40(%rax)
movaps %xmm0, 0x30(%rax)
movaps %xmm0, 0x20(%rax)
movaps %xmm0, 0x10(%rax)
movaps %xmm0, (%rax)
leaq 0x50(%rsp), %rax
movaps %xmm0, (%rax)
movaps %xmm0, 0x10(%rax)
movaps %xmm0, 0x20(%rax)
movabsq $0x5555555555555556, %rdx # imm = 0x5555555555555556
movq %rsi, %rax
imulq %rdx
movq %rdx, %rax
shrq $0x3f, %rax
addq %rdx, %rax
leaq (%rax,%rax,2), %rax
movq %rsi, %rdx
movq %rax, 0x20(%rsp)
subq %rax, %rdx
movq %rdx, (%rsp)
movq %rdx, %rbx
notq %rbx
addq %rsi, %rbx
movslq %ecx, %rax
shlq $0x6, %rax
addq 0x26a81(%rip), %rax     # 0x2fff8
movq %rax, 0x40(%rsp)
movq %r15, 0x30(%rsp)
movq %rbx, 0x18(%rsp)
movq %rsi, 0x28(%rsp)
movl %ebp, %eax
movl $0xaaaaaaab, %ecx       # imm = 0xAAAAAAAB
imulq %rcx, %rax
shrq $0x21, %rax
leal (%rax,%rax,2), %eax
movl %ebp, %r14d
subl %eax, %r14d
leaq (%rbx,%r14), %rax
cmpq %r12, %rax
leaq -0x3(%rbx,%r14), %r13
cmovlq %rax, %r13
movq %r12, %rdi
movl %r14d, %esi
movq %r15, %rdx
callq 0x91dc
movl 0x4c(%r15), %ecx
testb $0x20, %cl
jne 0x96a8
testb $0x8, %cl
je 0x95de
movslq 0x68(%r15), %rcx
cmpq %r12, %rcx
cmovaq %r13, %rax
leaq 0x2(%r14), %rsi
cmpq %r13, %rsi
jg 0x980f
leaq 0x2(%r14), %rcx
movq %r14, %rdx
movq %rdx, %rdi
notq %rdi
addq %r12, %rdi
cmpq $0x3, %rbp
cmovbq %rdx, %rdi
addq 0x48(%rsp), %rdi
xorl %r9d, %r9d
xorl %r10d, %r10d
xorl %r8d, %r8d
leaq 0x27528(%rip), %rbx     # 0x30b40
cmpq $0x3, %rbp
movl %r10d, %r11d
cmovael %r9d, %r11d
movslq %r11d, %r11
movsbq (%rdi,%r11), %r11
movb (%rbx,%r11), %r11b
cmpb $0x3, %r11b
ja 0x9662
shlb $0x2, %r8b
orb %r11b, %r8b
incl %r10d
decl %r9d
cmpl $-0x3, %r9d
jne 0x9618
movzbl %r8b, %edi
xorb $0x3f, %r8b
cmpq $0x3, %rbp
movzbl %r8b, %r8d
cmovbl %edi, %r8d
movzbl %r8b, %edi
jmp 0x9667
movl $0xff, %edi
movq 0x40(%rsp), %r8
cmpb $0x2a, (%rdi,%r8)
je 0x9678
cmpq %r13, %rsi
jne 0x968c
leaq (%rcx,%rdx), %rsi
subq %r14, %rsi
cmpq %rax, %rsi
jge 0x9723
leaq 0x3(%rdx), %r14
leaq 0x3(%rdx), %rdi
addq $0x5, %rdx
movq %rdx, %rsi
cmpq %r13, %rdx
movq %rdi, %rdx
jle 0x95f2
jmp 0x980f
leaq 0x80(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movq %rbp, %rdx
callq 0x9319
movq %r14, %rcx
notq %rcx
addq %r12, %rcx
cmpq $0x3, %rbp
cmovbq %r14, %rcx
movq 0x80(%rsp,%rbp,8), %rdx
movq 0x50(%rsp,%rbp,8), %rax
movq %rcx, -0x8(%rdx,%rax,8)
jae 0x96f4
leaq (%rbx,%rbp), %rdx
cmpq %r12, %rdx
leaq -0x3(%rbx,%rbp), %rcx
cmovlq %rdx, %rcx
jmp 0x9706
movq (%rsp), %rdx
subq %r14, %rdx
leaq 0x3(%rdx), %rcx
testq %rdx, %rdx
cmovnsq %rdx, %rcx
movq 0xb0(%rsp,%rbp,8), %rdx
movq %rcx, -0x8(%rdx,%rax,8)
testb $0x1, 0x4c(%r15)
jne 0x9822
jmp 0x982f
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
movq (%rsp), %rbx
xorl %r14d, %r14d
movq %r14, %rax
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
mulq %rcx
cmpq %r14, %rbp
je 0x9752
movl 0x4c(%r15), %eax
andl $0x1, %eax
je 0x97fc
shrq %rdx
leaq (%rdx,%rdx,2), %rax
movq %rax, 0x38(%rsp)
movq %rax, %r12
negq %r12
movl %r14d, %eax
movl $0xaaaaaaab, %ecx       # imm = 0xAAAAAAAB
imulq %rcx, %rax
shrq $0x21, %rax
leal (%rax,%rax,2), %r15d
addl %r13d, %r15d
leaq 0x80(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movq %r14, %rdx
callq 0x9319
movq 0x28(%rsp), %rsi
addq %r14, %r12
movslq %r15d, %rcx
addq %rsi, %rcx
cmpq $0x3, %r14
cmovbq %r12, %rcx
movq 0x80(%rsp,%r14,8), %rdx
movq 0x50(%rsp,%r14,8), %rax
movq %rcx, -0x8(%rdx,%rax,8)
jae 0x97d4
movq 0x20(%rsp), %rcx
leaq (%rcx,%r14), %rdx
decq %rdx
cmpq %rsi, %rdx
leaq -0x4(%rcx,%r14), %rcx
cmovlq %rdx, %rcx
jmp 0x97e7
movq 0x38(%rsp), %rdx
addq %rbx, %rdx
leaq 0x3(%rdx), %rcx
testq %rdx, %rdx
cmovnsq %rdx, %rcx
movq %rsi, %r12
movq 0xb0(%rsp,%r14,8), %rdx
movq %rcx, -0x8(%rdx,%rax,8)
movq 0x30(%rsp), %r15
incq %r14
decq %rbx
decl %r13d
cmpq $0x6, %r14
jne 0x9730
cmpq $0x5, %rbp
movq 0x18(%rsp), %rbx
je 0x9822
cmpq $0x0, 0x58(%rsp,%rbp,8)
jne 0x982f
incq %rbp
cmpq $0x6, %rbp
jne 0x958b
leaq 0x80(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movq 0x8(%rsp), %rdx
movq 0x10(%rsp), %rcx
callq 0x93e7
xorl %ebx, %ebx
movq 0x80(%rsp,%rbx,8), %rdi
callq 0x3390
movq 0xb0(%rsp,%rbx,8), %rdi
callq 0x3390
incq %rbx
cmpq $0x6, %rbx
jne 0x984d
xorl %eax, %eax
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq