// File: /workspace/github_c_makefile_star2_O3/nh13[P]ksw/src/parasail/src/sw_striped_sse41_128_64.c
// Function: parasail_sw_rowcol_striped_profile_sse41_128_64
parasail_result_t* PNAME(
        const parasail_profile_t * const restrict profile,
        const char * const restrict s2, const int s2Len,
        const int open, const int gap)
{
    /* declare local variables */
    int32_t i = 0;
    int32_t j = 0;
    int32_t k = 0;
    int32_t end_query = 0;
    int32_t end_ref = 0;
    int32_t s1Len = 0;
    const parasail_matrix_t *matrix = NULL;
    int32_t segWidth = 0;
    int32_t segLen = 0;
#ifdef PARASAIL_ROWCOL
    int32_t offset = 0;
    int32_t position = 0;
#endif
    __m128i* restrict vProfile = NULL;
    __m128i* restrict pvHStore = NULL;
    __m128i* restrict pvHLoad = NULL;
    __m128i* restrict pvHMax = NULL;
    __m128i* restrict pvE = NULL;
    __m128i vGapO;
    __m128i vGapE;
    __m128i vZero;
    __m128i vNegInf;
    int64_t score = 0;
    __m128i vMaxH;
    __m128i vMaxHUnit;
    int64_t maxp = 0;
    /*int64_t stop = 0;*/
    parasail_result_t *result = NULL;

    /* validate inputs */
    PARASAIL_CHECK_NULL(profile);
    PARASAIL_CHECK_NULL(profile->profile64.score);
    PARASAIL_CHECK_NULL(profile->matrix);
    PARASAIL_CHECK_GT0(profile->s1Len);
    PARASAIL_CHECK_NULL(s2);
    PARASAIL_CHECK_GT0(s2Len);
    PARASAIL_CHECK_GE0(open);
    PARASAIL_CHECK_GE0(gap);

    /* initialize stack variables */
    i = 0;
    j = 0;
    k = 0;
    end_query = 0;
    end_ref = 0;
    s1Len = profile->s1Len;
    matrix = profile->matrix;
    segWidth = 2; /* number of values in vector unit */
    segLen = (s1Len + segWidth - 1) / segWidth;
#ifdef PARASAIL_ROWCOL
    offset = (s1Len - 1) % segLen;
    position = (segWidth - 1) - (s1Len - 1) / segLen;
#endif
    vProfile = (__m128i*)profile->profile64.score;
    vGapO = _mm_set1_epi64x_rpl(open);
    vGapE = _mm_set1_epi64x_rpl(gap);
    vZero = _mm_setzero_si128();
    vNegInf = _mm_set1_epi64x_rpl(NEG_INF);
    score = NEG_INF;
    vMaxH = vNegInf;
    vMaxHUnit = vNegInf;
    maxp = INT64_MAX - (int64_t)(matrix->max+1);
    /*stop = profile->stop == INT32_MAX ?  INT64_MAX : (int64_t)profile->stop;*/

    /* initialize result */
#ifdef PARASAIL_TABLE
    result = parasail_result_new_table1(segLen*segWidth, s2Len);
#else
#ifdef PARASAIL_ROWCOL
    result = parasail_result_new_rowcol1(segLen*segWidth, s2Len);
#else
    result = parasail_result_new();
#endif
#endif
    if (!result) return NULL;

    /* set known flags */
    result->flag |= PARASAIL_FLAG_SW | PARASAIL_FLAG_STRIPED
        | PARASAIL_FLAG_BITS_64 | PARASAIL_FLAG_LANES_2;
#ifdef PARASAIL_TABLE
    result->flag |= PARASAIL_FLAG_TABLE;
#endif
#ifdef PARASAIL_ROWCOL
    result->flag |= PARASAIL_FLAG_ROWCOL;
#endif

    /* initialize heap variables */
    pvHStore = parasail_memalign___m128i(16, segLen);
    pvHLoad =  parasail_memalign___m128i(16, segLen);
    pvHMax = parasail_memalign___m128i(16, segLen);
    pvE = parasail_memalign___m128i(16, segLen);

    /* validate heap variables */
    if (!pvHStore) return NULL;
    if (!pvHLoad) return NULL;
    if (!pvHMax) return NULL;
    if (!pvE) return NULL;

    /* initialize H and E */
    parasail_memset___m128i(pvHStore, vZero, segLen);
    parasail_memset___m128i(pvE, _mm_set1_epi64x_rpl(-open), segLen);

    /* outer loop over database sequence */
    for (j=0; j<s2Len; ++j) {
        __m128i vE;
        __m128i vF;
        __m128i vH;
        const __m128i* vP = NULL;
        __m128i* pv = NULL;

        /* Initialize F value to 0.  Any errors to vH values will be
         * corrected in the Lazy_F loop. */
        vF = vZero;

        /* load final segment of pvHStore and shift left by 8 bytes */
        vH = _mm_load_si128(&pvHStore[segLen - 1]);
        vH = _mm_slli_si128(vH, 8);

        /* Correct part of the vProfile */
        vP = vProfile + matrix->mapper[(unsigned char)s2[j]] * segLen;

        if (end_ref == j-2) {
            /* Swap in the max buffer. */
            pv = pvHMax;
            pvHMax = pvHLoad;
            pvHLoad = pvHStore;
            pvHStore = pv;
        }
        else {
            /* Swap the 2 H buffers. */
            pv = pvHLoad;
            pvHLoad = pvHStore;
            pvHStore = pv;
        }

        /* inner loop to process the query sequence */
        for (i=0; i<segLen; ++i) {
            vH = _mm_add_epi64(vH, _mm_load_si128(vP + i));
            vE = _mm_load_si128(pvE + i);

            /* Get max from vH, vE and vF. */
            vH = _mm_max_epi64_rpl(vH, vE);
            vH = _mm_max_epi64_rpl(vH, vF);
            vH = _mm_max_epi64_rpl(vH, vZero);
            /* Save vH values. */
            _mm_store_si128(pvHStore + i, vH);
#ifdef PARASAIL_TABLE
            arr_store_si128(result->tables->score_table, vH, i, segLen, j, s2Len);
#endif
            vMaxH = _mm_max_epi64_rpl(vH, vMaxH);

            /* Update vE value. */
            vH = _mm_sub_epi64(vH, vGapO);
            vE = _mm_sub_epi64(vE, vGapE);
            vE = _mm_max_epi64_rpl(vE, vH);
            _mm_store_si128(pvE + i, vE);

            /* Update vF value. */
            vF = _mm_sub_epi64(vF, vGapE);
            vF = _mm_max_epi64_rpl(vF, vH);

            /* Load the next vH. */
            vH = _mm_load_si128(pvHLoad + i);
        }

        /* Lazy_F loop: has been revised to disallow adjecent insertion and
         * then deletion, so don't update E(i, i), learn from SWPS3 */
        for (k=0; k<segWidth; ++k) {
            vF = _mm_slli_si128(vF, 8);
            for (i=0; i<segLen; ++i) {
                vH = _mm_load_si128(pvHStore + i);
                vH = _mm_max_epi64_rpl(vH,vF);
                _mm_store_si128(pvHStore + i, vH);
#ifdef PARASAIL_TABLE
                arr_store_si128(result->tables->score_table, vH, i, segLen, j, s2Len);
#endif
                vMaxH = _mm_max_epi64_rpl(vH, vMaxH);
                vH = _mm_sub_epi64(vH, vGapO);
                vF = _mm_sub_epi64(vF, vGapE);
                if (! _mm_movemask_epi8(_mm_cmpgt_epi64_rpl(vF, vH))) goto end;
                /*vF = _mm_max_epi64_rpl(vF, vH);*/
            }
        }
end:
        {
        }

#ifdef PARASAIL_ROWCOL
        /* extract last value from the column */
        {
            vH = _mm_load_si128(pvHStore + offset);
            for (k=0; k<position; ++k) {
                vH = _mm_slli_si128(vH, 8);
            }
            result->rowcols->score_row[j] = (int64_t) _mm_extract_epi64_rpl (vH, 1);
        }
#endif

        {
            __m128i vCompare = _mm_cmpgt_epi64_rpl(vMaxH, vMaxHUnit);
            if (_mm_movemask_epi8(vCompare)) {
                score = _mm_hmax_epi64_rpl(vMaxH);
                /* if score has potential to overflow, abort early */
                if (score > maxp) {
                    result->flag |= PARASAIL_FLAG_SATURATED;
                    break;
                }
                vMaxHUnit = _mm_set1_epi64x_rpl(score);
                end_ref = j;
            }
        }

        /*if (score == stop) break;*/
    }

#ifdef PARASAIL_ROWCOL
    for (i=0; i<segLen; ++i) {
        __m128i vH = _mm_load_si128(pvHStore+i);
        arr_store_col(result->rowcols->score_col, vH, i, segLen);
    }
#endif

    if (score == INT64_MAX) {
        result->flag |= PARASAIL_FLAG_SATURATED;
    }

    if (parasail_result_is_saturated(result)) {
        score = INT64_MAX;
        end_query = 0;
        end_ref = 0;
    }
    else {
        if (end_ref == j-1) {
            /* end_ref was the last store column */
            __m128i *pv = pvHMax;
            pvHMax = pvHStore;
            pvHStore = pv;
        }
        else if (end_ref == j-2) {
            /* end_ref was the last load column */
            __m128i *pv = pvHMax;
            pvHMax = pvHLoad;
            pvHLoad = pv;
        }
        /* Trace the alignment ending position on read. */
        {
            int64_t *t = (int64_t*)pvHMax;
            int32_t column_len = segLen * segWidth;
            end_query = s1Len - 1;
            for (i = 0; i<column_len; ++i, ++t) {
                if (*t == score) {
                    int32_t temp = i / segWidth + i % segWidth * segLen;
                    if (temp < end_query) {
                        end_query = temp;
                    }
                }
            }
        }
    }

    result->score = score;
    result->end_query = end_query;
    result->end_ref = end_ref;

    parasail_free(pvE);
    parasail_free(pvHMax);
    parasail_free(pvHLoad);
    parasail_free(pvHStore);

    return result;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rsi, 0x48(%rsp)
testq %rdi, %rdi
je 0x45bb71
movq 0x60(%rdi), %rax
movq %rax, 0x58(%rsp)
testq %rax, %rax
je 0x45bb78
movq 0x10(%rdi), %rax
movq %rax, 0x40(%rsp)
testq %rax, %rax
je 0x45bb7f
movl 0x8(%rdi), %eax
testl %eax, %eax
jle 0x45bb86
cmpq $0x0, 0x48(%rsp)
je 0x45bb8d
movl %edx, %ebx
testl %edx, %edx
jle 0x45bb94
movl %ecx, %r15d
testl %ecx, %ecx
js 0x45bb9b
movl %r8d, %r12d
testl %r8d, %r8d
js 0x45bba2
movq %rax, %r14
incq %r14
movq %r14, %rbp
shrq %rbp
decl %eax
movl %eax, 0x14(%rsp)
xorl %edx, %edx
divl %ebp
movl %edx, %r13d
movq 0x40(%rsp), %rax
movslq 0x1c(%rax), %rax
movq %rax, 0x28(%rsp)
andl $0x7ffffffe, %r14d      # imm = 0x7FFFFFFE
movl %r14d, %edi
movl %ebx, %esi
callq 0x20ac53
testq %rax, %rax
je 0x45bba7
movl %r13d, 0x3c(%rsp)
movl %r12d, 0x30(%rsp)
movl %r15d, 0x18(%rsp)
movq %rbx, 0x20(%rsp)
movq %rax, 0x8(%rsp)
orl $0x2840804, 0xc(%rax)   # imm = 0x2840804
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2f600c
movq %rax, %r13
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2f600c
movq %rax, %rbx
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2f600c
movq %rax, %r15
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2f600c
movq %rax, %r12
testq %r13, %r13
sete %al
testq %rbx, %rbx
sete %cl
orb %al, %cl
testq %r15, %r15
sete %al
testq %r12, %r12
sete %dl
orb %al, %dl
orb %cl, %dl
jne 0x45bba7
movq %r14, 0x50(%rsp)
movabsq $0x7fffffffffffffff, %rcx # imm = 0x7FFFFFFFFFFFFFFF
movl 0x18(%rsp), %r14d
movd %r14d, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movdqa %xmm0, 0x70(%rsp)
movd 0x30(%rsp), %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movdqa %xmm0, 0x60(%rsp)
movq 0x28(%rsp), %rax
notq %rax
addq %rcx, %rax
movq %rax, 0x28(%rsp)
pxor %xmm0, %xmm0
movq %r13, %rdi
movq %rbp, %rsi
callq 0x2f6015
negl %r14d
movslq %r14d, %rax
movq %rax, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movq %r12, %rdi
movq %rbp, %rsi
callq 0x2f6015
pxor %xmm11, %xmm11
movdqa 0x60(%rsp), %xmm10
movdqa 0x70(%rsp), %xmm9
xorl %edi, %edi
leal -0x1(%rbp), %eax
movl 0x3c(%rsp), %ecx
movl 0x20(%rsp), %edx
movq %rdx, 0x30(%rsp)
movq %rbp, %rsi
shlq $0x4, %rsi
movabsq $-0x4000000000000000, %r14 # imm = 0xC000000000000000
movdqa 0x1ce7a1(%rip), %xmm3   # 0x629fb0
shlq $0x4, %rax
movq %rbp, 0x18(%rsp)
movslq %ebp, %r8
shlq $0x4, %rcx
xorl %edx, %edx
movdqa %xmm3, %xmm2
movq %r13, %rbp
movdqa (%r13,%rax), %xmm1
pslldq $0x8, %xmm1             # xmm1 = zero,zero,zero,zero,zero,zero,zero,zero,xmm1[0,1,2,3,4,5,6,7]
movq 0x40(%rsp), %r9
movq 0x10(%r9), %r9
movq 0x48(%rsp), %r10
movzbl (%r10,%rdx), %r10d
movslq (%r9,%r10,4), %r9
imulq %r8, %r9
shlq $0x4, %r9
addq 0x58(%rsp), %r9
leal -0x2(%rdx), %r10d
cmpl %r10d, %edi
movq %rbx, %r13
cmoveq %r15, %r13
xorl %r11d, %r11d
pxor %xmm4, %xmm4
paddq (%r9,%r11), %xmm1
movdqa (%r12,%r11), %xmm5
movdqa %xmm1, %xmm0
pcmpgtq %xmm5, %xmm0
movdqa %xmm5, %xmm6
blendvpd %xmm0, %xmm1, %xmm6
movapd %xmm6, %xmm0
pcmpgtq %xmm4, %xmm0
movdqa %xmm4, %xmm7
blendvpd %xmm0, %xmm6, %xmm4
movapd %xmm4, %xmm6
pcmpgtq %xmm11, %xmm6
pand %xmm4, %xmm6
movdqa %xmm6, %xmm0
pcmpgtq %xmm2, %xmm0
blendvpd %xmm0, %xmm6, %xmm2
movaps %xmm6, (%r13,%r11)
psubq %xmm9, %xmm6
psubq %xmm10, %xmm5
movdqa %xmm5, %xmm0
pcmpgtq %xmm6, %xmm0
psubq %xmm10, %xmm7
movdqa %xmm7, %xmm1
pcmpgtq %xmm6, %xmm1
movdqa %xmm6, %xmm8
blendvpd %xmm0, %xmm5, %xmm8
movdqa %xmm6, %xmm4
movdqa %xmm1, %xmm0
blendvpd %xmm0, %xmm7, %xmm4
movapd %xmm8, (%r12,%r11)
movapd (%rbp,%r11), %xmm1
addq $0x10, %r11
cmpq %r11, %rsi
jne 0x45b86d
cmpl %r10d, %edi
cmoveq %rbx, %r15
movb $0x1, %r9b
pslldq $0x8, %xmm4             # xmm4 = zero,zero,zero,zero,zero,zero,zero,zero,xmm4[0,1,2,3,4,5,6,7]
xorl %r10d, %r10d
movdqa (%r13,%r10), %xmm1
movdqa %xmm1, %xmm0
pcmpgtq %xmm4, %xmm0
movdqa %xmm4, %xmm5
blendvpd %xmm0, %xmm1, %xmm5
movapd %xmm5, (%r13,%r10)
movapd %xmm5, %xmm0
pcmpgtq %xmm2, %xmm0
blendvpd %xmm0, %xmm5, %xmm2
psubq %xmm9, %xmm5
psubq %xmm10, %xmm4
movdqa %xmm4, %xmm0
pcmpgtq %xmm5, %xmm0
movmskpd %xmm0, %r11d
testl %r11d, %r11d
je 0x45b984
addq $0x10, %r10
cmpq %r10, %rsi
jne 0x45b924
testb $0x1, %r9b
movl $0x0, %r9d
jne 0x45b91c
movq %rdi, %rbx
movdqa (%r13,%rcx), %xmm0
movq 0x18(%rsp), %rdi
cmpl 0x14(%rsp), %edi
jbe 0x45b99e
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movq 0x8(%rsp), %rdi
movq 0x10(%rdi), %r9
movq (%r9), %r9
pextrd $0x2, %xmm0, (%r9,%rdx,4)
movapd %xmm2, %xmm0
pcmpgtq %xmm3, %xmm0
movmskpd %xmm0, %r9d
testl %r9d, %r9d
je 0x45b9ed
pextrq $0x1, %xmm2, %r14
movq %xmm2, %r9
cmpq %r14, %r9
cmovgq %r9, %r14
cmpq 0x28(%rsp), %r14
jg 0x45ba0b
movq %r14, %xmm0
pshufd $0x44, %xmm0, %xmm3     # xmm3 = xmm0[0,1,0,1]
movl %edx, %edi
jmp 0x45b9f0
movq %rbx, %rdi
incq %rdx
movq %rbp, %rbx
cmpq 0x30(%rsp), %rdx
jne 0x45b825
movq %rdi, %rbx
movq 0x8(%rsp), %rdi
jmp 0x45ba14
orb $0x40, 0xc(%rdi)
movq %rdx, 0x20(%rsp)
movl 0x18(%rsp), %eax
leaq (,%rax,4), %rcx
xorl %edx, %edx
movdqa (%r13,%rdx,4), %xmm0
movq 0x10(%rdi), %rsi
movq 0x8(%rsi), %rsi
movd %xmm0, (%rsi,%rdx)
addq %rdx, %rsi
pextrd $0x2, %xmm0, (%rcx,%rsi)
addq $0x4, %rdx
decq %rax
jne 0x45ba22
movabsq $0x7fffffffffffffff, %rax # imm = 0x7FFFFFFFFFFFFFFF
cmpq %rax, %r14
jne 0x45ba5c
orb $0x40, 0xc(%rdi)
callq 0x20be2e
testl %eax, %eax
je 0x45baa7
xorl %ebx, %ebx
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
xorl %edi, %edi
movq 0x8(%rsp), %rdx
movl %r14d, (%rdx)
movl %edi, 0x4(%rdx)
movl %ebx, 0x8(%rdx)
movq %r12, %rdi
callq 0x20a60d
movq %r15, %rdi
callq 0x20a60d
movq %rbp, %rdi
callq 0x20a60d
movq %r13, %rdi
callq 0x20a60d
movq 0x8(%rsp), %rax
jmp 0x45bba9
movq 0x20(%rsp), %rdx
leal -0x1(%rdx), %eax
addl $-0x2, %edx
movq %rbx, %rcx
cmpl %edx, %ecx
movq %rbp, %rsi
cmoveq %r15, %rsi
movq %r15, %rdx
cmoveq %rbp, %r15
cmpl %eax, %ecx
cmovneq %r13, %rdx
movq %rdx, %rax
cmoveq %rbp, %rsi
movq %rsi, %rbp
cmoveq %r13, %r15
movq 0x50(%rsp), %rsi
testl %esi, %esi
je 0x45bbbb
movq 0x8(%rsp), %rdx
movl 0x14(%rsp), %edi
movq %rax, %r13
je 0x45bbcc
movd %edi, %xmm0
pshufd $0x50, %xmm0, %xmm1     # xmm1 = xmm0[0,0,1,1]
movq %r14, %xmm0
pshufd $0x44, %xmm0, %xmm2     # xmm2 = xmm0[0,1,0,1]
movd 0x18(%rsp), %xmm0
pshufd $0x51, %xmm0, %xmm3     # xmm3 = xmm0[1,0,1,1]
pmovsxbd 0x1d0201(%rip), %xmm4   # 0x62bd20
xorl %eax, %eax
pmovsxbd 0x1d01fa(%rip), %xmm5   # 0x62bd24
movdqu (%r15,%rax,8), %xmm0
pcmpeqq %xmm2, %xmm0
pshufd $0xe8, %xmm0, %xmm0     # xmm0 = xmm0[0,2,2,3]
movdqa %xmm4, %xmm6
psrld $0x1, %xmm6
paddd %xmm3, %xmm6
pminsd %xmm1, %xmm6
blendvps %xmm0, %xmm6, %xmm1
addq $0x2, %rax
paddd %xmm5, %xmm4
cmpq %rax, %rsi
jne 0x45bb2a
pshufd $0x55, %xmm1, %xmm0     # xmm0 = xmm1[1,1,1,1]
pminsd %xmm1, %xmm0
movd %xmm0, %edi
jmp 0x45ba74
callq 0x1d3f45
jmp 0x45bba7
callq 0x1d3f1f
jmp 0x45bba7
callq 0x1d3ef9
jmp 0x45bba7
callq 0x1d3ed3
jmp 0x45bba7
callq 0x1d3ead
jmp 0x45bba7
callq 0x1d3e87
jmp 0x45bba7
callq 0x1d3e61
jmp 0x45bba7
callq 0x1d3e3b
xorl %eax, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rsp), %rdx
movl 0x14(%rsp), %edi
movq %rax, %r13
jmp 0x45ba74
xorl %eax, %eax
movl %eax, %ecx
shrl %ecx
cmpl %edi, %ecx
cmovgel %edi, %ecx
cmpq %r14, (%r15,%rax,8)
cmovel %ecx, %edi
incq %rax
cmpl %eax, %esi
jne 0x45bbce
jmp 0x45ba74
nop