// File: /workspace/github_c_makefile_star2_O3/nh13[P]ksw/src/parasail/src/nw_striped_sse41_128_64.c
// Function: parasail_nw_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;
    int s1Len = 0;
    int32_t end_query = 0;
    int32_t end_ref = 0;
    const parasail_matrix_t *matrix = NULL;
    int32_t segWidth = 0;
    int32_t segLen = 0;
    int32_t offset = 0;
    int32_t position = 0;
    __m128i* restrict vProfile = NULL;
    __m128i* restrict pvHStore = NULL;
    __m128i* restrict pvHLoad = NULL;
    __m128i* restrict pvE = NULL;
    int64_t* restrict boundary = NULL;
    __m128i vGapO;
    __m128i vGapE;
    int64_t NEG_LIMIT = 0;
    int64_t POS_LIMIT = 0;
    int64_t score = 0;
    __m128i vNegLimit;
    __m128i vPosLimit;
    __m128i vSaturationCheckMin;
    __m128i vSaturationCheckMax;
    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;
    s1Len = profile->s1Len;
    end_query = s1Len-1;
    end_ref = s2Len-1;
    matrix = profile->matrix;
    segWidth = 2; /* number of values in vector unit */
    segLen = (s1Len + segWidth - 1) / segWidth;
    offset = (s1Len - 1) % segLen;
    position = (segWidth - 1) - (s1Len - 1) / segLen;
    vProfile = (__m128i*)profile->profile64.score;
    vGapO = _mm_set1_epi64x_rpl(open);
    vGapE = _mm_set1_epi64x_rpl(gap);
    NEG_LIMIT = (-open < matrix->min ? INT64_MIN + open : INT64_MIN - matrix->min) + 1;
    POS_LIMIT = INT64_MAX - matrix->max - 1;
    score = NEG_LIMIT;
    vNegLimit = _mm_set1_epi64x_rpl(NEG_LIMIT);
    vPosLimit = _mm_set1_epi64x_rpl(POS_LIMIT);
    vSaturationCheckMin = vPosLimit;
    vSaturationCheckMax = vNegLimit;

    /* 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_NW | 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);
    pvE      = parasail_memalign___m128i(16, segLen);
    boundary = parasail_memalign_int64_t(16, s2Len+1);

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

    /* initialize H and E */
    {
        int32_t index = 0;
        for (i=0; i<segLen; ++i) {
            int32_t segNum = 0;
            __m128i_64_t h;
            __m128i_64_t e;
            for (segNum=0; segNum<segWidth; ++segNum) {
                int64_t tmp = -open-gap*(segNum*segLen+i);
                h.v[segNum] = tmp < INT64_MIN ? INT64_MIN : tmp;
                tmp = tmp - open;
                e.v[segNum] = tmp < INT64_MIN ? INT64_MIN : tmp;
            }
            _mm_store_si128(&pvHStore[index], h.m);
            _mm_store_si128(&pvE[index], e.m);
            ++index;
        }
    }

    /* initialize uppder boundary */
    {
        boundary[0] = 0;
        for (i=1; i<=s2Len; ++i) {
            int64_t tmp = -open-gap*(i-1);
            boundary[i] = tmp < INT64_MIN ? INT64_MIN : tmp;
        }
    }

    /* outer loop over database sequence */
    for (j=0; j<s2Len; ++j) {
        __m128i vE;
        /* Initialize F value to -inf.  Any errors to vH values will be
         * corrected in the Lazy_F loop.  */
        __m128i vF = vNegLimit;

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

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

        /* Swap the 2 H buffers. */
        __m128i* pv = pvHLoad;
        pvHLoad = pvHStore;
        pvHStore = pv;

        /* insert upper boundary condition */
        vH = _mm_insert_epi64_rpl(vH, boundary[j], 0);

        /* 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);
            /* Save vH values. */
            _mm_store_si128(pvHStore + i, vH);
            vSaturationCheckMax = _mm_max_epi64_rpl(vSaturationCheckMax, vH);
            vSaturationCheckMin = _mm_min_epi64_rpl(vSaturationCheckMin, vH);
            vSaturationCheckMin = _mm_min_epi64_rpl(vSaturationCheckMin, vE);
            vSaturationCheckMin = _mm_min_epi64_rpl(vSaturationCheckMin, vF);
#ifdef PARASAIL_TABLE
            arr_store_si128(result->tables->score_table, vH, i, segLen, j, s2Len);
#endif

            /* 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) {
            int64_t tmp = boundary[j+1]-open;
            int64_t tmp2 = tmp < INT64_MIN ? INT64_MIN : tmp;
            vF = _mm_slli_si128(vF, 8);
            vF = _mm_insert_epi64_rpl(vF, tmp2, 0);
            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);
                vSaturationCheckMin = _mm_min_epi64_rpl(vSaturationCheckMin, vH);
                vSaturationCheckMax = _mm_max_epi64_rpl(vSaturationCheckMax, vH);
#ifdef PARASAIL_TABLE
                arr_store_si128(result->tables->score_table, vH, i, segLen, j, s2Len);
#endif
                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
    }

#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

    /* extract last value from the last column */
    {
        __m128i vH = _mm_load_si128(pvHStore + offset);
        for (k=0; k<position; ++k) {
            vH = _mm_slli_si128 (vH, 8);
        }
        score = (int64_t) _mm_extract_epi64_rpl (vH, 1);
    }

    if (_mm_movemask_epi8(_mm_or_si128(
            _mm_cmplt_epi64_rpl(vSaturationCheckMin, vNegLimit),
            _mm_cmpgt_epi64_rpl(vSaturationCheckMax, vPosLimit)))) {
        result->flag |= PARASAIL_FLAG_SATURATED;
        score = 0;
        end_query = 0;
        end_ref = 0;
    }

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

    parasail_free(boundary);
    parasail_free(pvE);
    parasail_free(pvHLoad);
    parasail_free(pvHStore);

    return result;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rsi, 0x40(%rsp)
testq %rdi, %rdi
je 0x45a99b
movq 0x60(%rdi), %rax
movq %rax, 0x60(%rsp)
testq %rax, %rax
je 0x45a9a2
movq 0x10(%rdi), %rax
movq %rax, 0x38(%rsp)
testq %rax, %rax
je 0x45a9a9
movl 0x8(%rdi), %edi
testl %edi, %edi
jle 0x45a9b0
cmpq $0x0, 0x40(%rsp)
je 0x45a9b7
movl %edx, %r13d
testl %edx, %edx
jle 0x45a9be
movl %ecx, %r9d
testl %ecx, %ecx
js 0x45a9c5
testl %r8d, %r8d
js 0x45a9cc
movl %r8d, 0x1c(%rsp)
leal -0x1(%rdi), %eax
incq %rdi
movq %rdi, %rbp
shrq %rbp
movl %eax, 0x18(%rsp)
xorl %edx, %edx
divl %ebp
movl %eax, %r12d
movl %edx, %r14d
movl %r9d, %ecx
negl %r9d
movq 0x38(%rsp), %rdx
movslq 0x20(%rdx), %rax
movq %rcx, 0x48(%rsp)
btsq $0x3f, %rcx
movabsq $-0x8000000000000000, %rbx # imm = 0x8000000000000000
subq %rax, %rbx
movl %r9d, 0x8(%rsp)
cmpl %r9d, %eax
cmovgq %rcx, %rbx
movslq 0x1c(%rdx), %rax
movq %rax, 0x58(%rsp)
andl $0x7ffffffe, %edi       # imm = 0x7FFFFFFE
movl %r13d, %esi
callq 0x20ac53
testq %rax, %rax
je 0x45a9d1
movq %rax, %r15
movl %r14d, 0x14(%rsp)
movq %rbx, 0x28(%rsp)
orl $0x2840801, 0xc(%rax)   # imm = 0x2840801
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2f600c
movq %rax, %r14
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2f600c
movq %rax, %rbx
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2f600c
movq %r13, %rcx
movq %rax, %r13
movq %rcx, 0x20(%rsp)
leal 0x1(%rcx), %esi
movl $0x10, %edi
movq %rsi, 0x50(%rsp)
callq 0x20a636
testq %r14, %r14
sete %cl
testq %rbx, %rbx
sete %dl
orb %cl, %dl
testq %r13, %r13
sete %cl
testq %rax, %rax
sete %sil
orb %cl, %sil
orb %dl, %sil
jne 0x45a9d1
movq %r15, 0x30(%rsp)
movq 0x20(%rsp), %rcx
decl %ecx
movl %ecx, 0x4(%rsp)
movq 0x48(%rsp), %rdx
movq %rdx, %xmm0
pshufd $0x44, %xmm0, %xmm4     # xmm4 = xmm0[0,1,0,1]
movl 0x1c(%rsp), %esi
movd %esi, %xmm0
pshufd $0x44, %xmm0, %xmm5     # xmm5 = xmm0[0,1,0,1]
movq 0x28(%rsp), %rcx
incq %rcx
movabsq $-0x8000000000000000, %rdi # imm = 0x8000000000000000
subq 0x58(%rsp), %rdi
addq $-0x2, %rdi
movq %rcx, %xmm0
pshufd $0x44, %xmm0, %xmm6     # xmm6 = xmm0[0,1,0,1]
movq %rdi, %xmm2
pshufd $0x44, %xmm2, %xmm3     # xmm3 = xmm2[0,1,0,1]
movl %esi, %edi
movslq 0x8(%rsp), %r8
movq %rdx, %rcx
negq %rcx
movq %rbp, %rsi
imulq %rdi, %rsi
negq %rsi
movq %rsi, %r9
subq %rdx, %r9
movq %rbp, 0x8(%rsp)
movq %rbp, %rdx
shlq $0x4, %rdx
xorl %r10d, %r10d
movq %r8, %r11
leaq (%rcx,%r11), %rbp
leaq (%rsi,%r11), %r15
movq %r15, %xmm0
movq %r11, %xmm1
punpcklqdq %xmm0, %xmm1    # xmm1 = xmm1[0],xmm0[0]
leaq (%r9,%r11), %r15
movq %r15, %xmm0
movq %rbp, %xmm7
punpcklqdq %xmm0, %xmm7    # xmm7 = xmm7[0],xmm0[0]
movdqa %xmm1, (%r14,%r10)
movdqa %xmm7, (%r13,%r10)
subq %rdi, %r11
addq $0x10, %r10
cmpq %r10, %rdx
jne 0x45a5b0
movq $0x0, (%rax)
movl 0x20(%rsp), %esi
movq 0x50(%rsp), %r11
andl $-0x2, %r11d
leaq -0x1(%rsi), %rcx
movq %rcx, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movq %rdi, %rcx
negq %rcx
addq %rdi, %rdi
xorl %r9d, %r9d
pmovsxbq 0x1d2a77(%rip), %xmm1   # 0x62d09f
movdqa 0x1d1660(%rip), %xmm7   # 0x62bc90
pxor %xmm7, %xmm0
pcmpeqd %xmm8, %xmm8
movq %r9, %xmm9
movdqa %xmm9, %xmm10
pxor %xmm7, %xmm10
pcmpgtq %xmm0, %xmm10
movd %xmm10, %r10d
notl %r10d
testb $0x1, %r10b
je 0x45a661
movq %r8, 0x8(%rax,%r9,8)
pshufd $0x44, %xmm9, %xmm9     # xmm9 = xmm9[0,1,0,1]
por %xmm1, %xmm9
pxor %xmm7, %xmm9
pcmpgtq %xmm0, %xmm9
pxor %xmm8, %xmm9
pextrb $0x8, %xmm9, %r10d
testb $0x1, %r10b
je 0x45a692
leaq (%rcx,%r8), %r10
movq %r10, 0x10(%rax,%r9,8)
addq $0x2, %r9
subq %rdi, %r8
cmpq %r9, %r11
jne 0x45a639
movq 0x8(%rsp), %rcx
leal -0x1(%rcx), %r8d
movl 0x14(%rsp), %edi
xorl %r9d, %r9d
shlq $0x4, %r8
movslq %ecx, %r10
movq %rdi, %r11
shlq $0x4, %r11
movdqa %xmm6, %xmm7
movq %r14, %r15
movq %rbx, %r14
pshufd $0x44, (%r15,%r8), %xmm1 # xmm1 = mem[0,1,0,1]
movq 0x38(%rsp), %rcx
movq 0x10(%rcx), %rcx
movq 0x40(%rsp), %rbx
movzbl (%rbx,%r9), %ebx
movslq (%rcx,%rbx,4), %rbx
imulq %r10, %rbx
shlq $0x4, %rbx
addq 0x60(%rsp), %rbx
pinsrq $0x0, (%rax,%r9,8), %xmm1
xorl %ecx, %ecx
movdqa %xmm6, %xmm8
paddq (%rbx,%rcx), %xmm1
movdqa %xmm7, %xmm11
movdqa (%r13,%rcx), %xmm9
movdqa %xmm1, %xmm0
pcmpgtq %xmm9, %xmm0
movdqa %xmm9, %xmm7
blendvpd %xmm0, %xmm1, %xmm7
movapd %xmm7, %xmm0
pcmpgtq %xmm8, %xmm0
movdqa %xmm8, %xmm10
blendvpd %xmm0, %xmm7, %xmm10
movdqa %xmm11, %xmm0
pcmpgtq %xmm10, %xmm0
movapd %xmm10, %xmm7
blendvpd %xmm0, %xmm11, %xmm7
movdqa %xmm10, %xmm0
pcmpgtq %xmm3, %xmm0
movapd %xmm10, %xmm1
blendvpd %xmm0, %xmm3, %xmm1
movdqa %xmm9, %xmm0
pcmpgtq %xmm1, %xmm0
movdqa %xmm9, %xmm11
blendvpd %xmm0, %xmm1, %xmm11
movdqa %xmm8, %xmm3
movdqa %xmm8, %xmm12
movdqa %xmm8, %xmm0
pcmpgtq %xmm11, %xmm0
blendvpd %xmm0, %xmm11, %xmm3
movaps %xmm10, (%r14,%rcx)
psubq %xmm4, %xmm10
psubq %xmm5, %xmm9
movdqa %xmm9, %xmm0
pcmpgtq %xmm10, %xmm0
psubq %xmm5, %xmm12
movdqa %xmm12, %xmm1
pcmpgtq %xmm10, %xmm1
movdqa %xmm10, %xmm11
blendvpd %xmm0, %xmm9, %xmm11
movdqa %xmm10, %xmm8
movdqa %xmm1, %xmm0
blendvpd %xmm0, %xmm12, %xmm8
movapd %xmm11, (%r13,%rcx)
movdqa (%r15,%rcx), %xmm1
addq $0x10, %rcx
cmpq %rcx, %rdx
jne 0x45a700
movb $0x1, %cl
movq 0x8(%rax,%r9,8), %rbx
subq 0x48(%rsp), %rbx
pshufd $0x44, %xmm8, %xmm8     # xmm8 = xmm8[0,1,0,1]
pinsrq $0x0, %rbx, %xmm8
xorl %ebx, %ebx
movapd %xmm3, %xmm1
movdqa (%r14,%rbx), %xmm3
movdqa %xmm3, %xmm0
pcmpgtq %xmm8, %xmm0
movdqa %xmm8, %xmm9
blendvpd %xmm0, %xmm3, %xmm9
movapd %xmm7, %xmm10
movapd %xmm9, (%r14,%rbx)
movapd %xmm9, %xmm0
pcmpgtq %xmm1, %xmm0
movapd %xmm9, %xmm3
blendvpd %xmm0, %xmm1, %xmm3
movapd %xmm7, %xmm0
pcmpgtq %xmm9, %xmm0
movapd %xmm9, %xmm7
blendvpd %xmm0, %xmm10, %xmm7
psubq %xmm4, %xmm9
psubq %xmm5, %xmm8
movdqa %xmm8, %xmm0
pcmpgtq %xmm9, %xmm0
movmskpd %xmm0, %ebp
testl %ebp, %ebp
je 0x45a894
addq $0x10, %rbx
cmpq %rbx, %rdx
jne 0x45a80d
testb $0x1, %cl
movl $0x0, %ecx
jne 0x45a7f4
movdqa (%r14,%r11), %xmm0
testl %r12d, %r12d
jle 0x45a8a6
movq 0x30(%rsp), %rbp
jmp 0x45a8b5
movq 0x30(%rsp), %rbp
pslldq $0x8, %xmm0             # xmm0 = zero,zero,zero,zero,zero,zero,zero,zero,xmm0[0,1,2,3,4,5,6,7]
testl %r12d, %r12d
js 0x45a8ab
movq 0x10(%rbp), %rcx
movq (%rcx), %rcx
pextrd $0x2, %xmm0, (%rcx,%r9,4)
incq %r9
movq %r15, %rbx
cmpq %rsi, %r9
jne 0x45a6c0
movq 0x8(%rsp), %rsi
shlq $0x2, %rsi
xorl %ecx, %ecx
movdqa (%r14,%rcx,4), %xmm0
movq 0x10(%rbp), %rdx
movq 0x8(%rdx), %rdx
movd %xmm0, (%rdx,%rcx)
addq %rcx, %rdx
pextrd $0x2, %xmm0, (%rsi,%rdx)
addq $0x4, %rcx
cmpq %rcx, %rsi
jne 0x45a8de
shlq $0x4, %rdi
movdqa (%r14,%rdi), %xmm0
testl %r12d, %r12d
movq 0x28(%rsp), %rcx
jle 0x45a91e
movl 0x4(%rsp), %esi
jmp 0x45a92c
movl 0x4(%rsp), %esi
pslldq $0x8, %xmm0             # xmm0 = zero,zero,zero,zero,zero,zero,zero,zero,xmm0[0,1,2,3,4,5,6,7]
testl %r12d, %r12d
js 0x45a922
movq %rcx, %xmm1
pshufd $0x44, %xmm1, %xmm1     # xmm1 = xmm1[0,1,0,1]
pcmpgtq %xmm1, %xmm3
pcmpeqd %xmm1, %xmm1
pxor %xmm3, %xmm1
pshufd $0x44, %xmm2, %xmm2     # xmm2 = xmm2[0,1,0,1]
pcmpgtq %xmm2, %xmm7
por %xmm1, %xmm7
movmskpd %xmm7, %ecx
testl %ecx, %ecx
je 0x45a965
orb $0x40, 0xc(%rbp)
xorl %ecx, %ecx
xorl %esi, %esi
xorl %edx, %edx
jmp 0x45a970
pextrq $0x1, %xmm0, %rcx
movl 0x18(%rsp), %edx
movl %ecx, (%rbp)
movl %edx, 0x4(%rbp)
movl %esi, 0x8(%rbp)
movq %rax, %rdi
callq 0x20a60d
movq %r13, %rdi
callq 0x20a60d
movq %r15, %rdi
callq 0x20a60d
movq %r14, %rdi
callq 0x20a60d
jmp 0x45a9d3
callq 0x1d3ad1
jmp 0x45a9d1
callq 0x1d3aab
jmp 0x45a9d1
callq 0x1d3a85
jmp 0x45a9d1
callq 0x1d3a5f
jmp 0x45a9d1
callq 0x1d3a39
jmp 0x45a9d1
callq 0x1d3a13
jmp 0x45a9d1
callq 0x1d39ed
jmp 0x45a9d1
callq 0x1d39c7
xorl %ebp, %ebp
movq %rbp, %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)