// File: /workspace/github_c_makefile_star2_O1/nh13[P]ksw/src/parasail/src/nw_striped_sse41_128_32.c
// Function: parasail_nw_rowcol_striped_profile_sse41_128_32
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;
    int32_t* restrict boundary = NULL;
    __m128i vGapO;
    __m128i vGapE;
    int32_t NEG_LIMIT = 0;
    int32_t POS_LIMIT = 0;
    int32_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->profile32.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 = 4; /* number of values in vector unit */
    segLen = (s1Len + segWidth - 1) / segWidth;
    offset = (s1Len - 1) % segLen;
    position = (segWidth - 1) - (s1Len - 1) / segLen;
    vProfile = (__m128i*)profile->profile32.score;
    vGapO = _mm_set1_epi32(open);
    vGapE = _mm_set1_epi32(gap);
    NEG_LIMIT = (-open < matrix->min ? INT32_MIN + open : INT32_MIN - matrix->min) + 1;
    POS_LIMIT = INT32_MAX - matrix->max - 1;
    score = NEG_LIMIT;
    vNegLimit = _mm_set1_epi32(NEG_LIMIT);
    vPosLimit = _mm_set1_epi32(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_32 | PARASAIL_FLAG_LANES_4;
#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_int32_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_32_t h;
            __m128i_32_t e;
            for (segNum=0; segNum<segWidth; ++segNum) {
                int64_t tmp = -open-gap*(segNum*segLen+i);
                h.v[segNum] = tmp < INT32_MIN ? INT32_MIN : tmp;
                tmp = tmp - open;
                e.v[segNum] = tmp < INT32_MIN ? INT32_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 < INT32_MIN ? INT32_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], 4);

        /* 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_epi32(vH, boundary[j], 0);

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

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

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

            /* Update vF value. */
            vF = _mm_sub_epi32(vF, vGapE);
            vF = _mm_max_epi32(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;
            int32_t tmp2 = tmp < INT32_MIN ? INT32_MIN : tmp;
            vF = _mm_slli_si128(vF, 4);
            vF = _mm_insert_epi32(vF, tmp2, 0);
            for (i=0; i<segLen; ++i) {
                vH = _mm_load_si128(pvHStore + i);
                vH = _mm_max_epi32(vH,vF);
                _mm_store_si128(pvHStore + i, vH);
                vSaturationCheckMin = _mm_min_epi32(vSaturationCheckMin, vH);
                vSaturationCheckMax = _mm_max_epi32(vSaturationCheckMax, vH);
#ifdef PARASAIL_TABLE
                arr_store_si128(result->tables->score_table, vH, i, segLen, j, s2Len);
#endif
                vH = _mm_sub_epi32(vH, vGapO);
                vF = _mm_sub_epi32(vF, vGapE);
                if (! _mm_movemask_epi8(_mm_cmpgt_epi32(vF, vH))) goto end;
                /*vF = _mm_max_epi32(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, 4);
            }
            result->rowcols->score_row[j] = (int32_t) _mm_extract_epi32 (vH, 3);
        }
#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, 4);
        }
        score = (int32_t) _mm_extract_epi32 (vH, 3);
    }

    if (_mm_movemask_epi8(_mm_or_si128(
            _mm_cmplt_epi32(vSaturationCheckMin, vNegLimit),
            _mm_cmpgt_epi32(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 $0x98, %rsp
movq %rsi, 0x58(%rsp)
testq %rdi, %rdi
je 0x4371ed
movq 0x48(%rdi), %rax
movq %rax, 0x68(%rsp)
testq %rax, %rax
je 0x4371f4
movq 0x10(%rdi), %rax
movq %rax, 0x50(%rsp)
testq %rax, %rax
je 0x4371fb
movl 0x8(%rdi), %edi
testl %edi, %edi
jle 0x437202
cmpq $0x0, 0x58(%rsp)
je 0x437209
movl %edx, %r14d
testl %edx, %edx
jle 0x437210
movl %ecx, %r15d
testl %ecx, %ecx
js 0x437217
testl %r8d, %r8d
js 0x43721e
movl %r8d, 0x20(%rsp)
leal -0x1(%rdi), %r13d
addq $0x3, %rdi
movq %rdi, %r12
shrq $0x2, %r12
movl %r13d, %eax
cltd
idivl %r12d
movl %eax, 0xc(%rsp)
movl %edx, %ebp
movl %r15d, %ebx
negl %ebx
movq 0x50(%rsp), %rdx
movl 0x20(%rdx), %eax
movl $0x80000000, %esi       # imm = 0x80000000
movl %r15d, %ecx
orl %esi, %ecx
subl %eax, %esi
cmpl %ebx, %eax
cmovgl %ecx, %esi
movl %esi, 0x30(%rsp)
movl $0x7ffffffe, %eax       # imm = 0x7FFFFFFE
subl 0x1c(%rdx), %eax
movl %eax, 0x8(%rsp)
andl $0x7ffffffc, %edi       # imm = 0x7FFFFFFC
movl %r14d, %esi
callq 0x209630
testq %rax, %rax
je 0x437223
movl %r13d, 0x44(%rsp)
movl %ebp, 0x28(%rsp)
movq %rax, 0x38(%rsp)
orl $0x4440801, 0xc(%rax)   # imm = 0x4440801
movl $0x10, %edi
movq %r12, %rsi
callq 0x2ea474
movq %r14, 0x10(%rsp)
movq %rax, %r14
movl $0x10, %edi
movq %r12, %rsi
callq 0x2ea474
movq %rax, %rbp
movl $0x10, %edi
movq %r12, %rsi
callq 0x2ea474
movq %rax, %r13
movq 0x10(%rsp), %rax
leal 0x1(%rax), %esi
movl $0x10, %edi
movq %rsi, 0x60(%rsp)
callq 0x2094d5
testq %r14, %r14
sete %cl
testq %rbp, %rbp
sete %dl
orb %cl, %dl
testq %r13, %r13
sete %cl
testq %rax, %rax
sete %sil
orb %cl, %sil
orb %dl, %sil
jne 0x437223
movq 0x10(%rsp), %rcx
decl %ecx
movl %ecx, 0x18(%rsp)
movl $0x3, %ecx
subl 0xc(%rsp), %ecx
movl %ecx, 0x1c(%rsp)
movd %r15d, %xmm0
pshufd $0x0, %xmm0, %xmm2      # xmm2 = xmm0[0,0,0,0]
movl 0x20(%rsp), %edx
movd %edx, %xmm0
pshufd $0x0, %xmm0, %xmm3      # xmm3 = xmm0[0,0,0,0]
movl 0x30(%rsp), %ecx
incl %ecx
movd %ecx, %xmm0
pshufd $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
movd 0x8(%rsp), %xmm1
pshufd $0x0, %xmm1, %xmm1      # xmm1 = xmm1[0,0,0,0]
movl %r15d, %ecx
movl %r12d, %esi
movq %r12, 0x48(%rsp)
imull %r12d, %edx
xorl %edi, %edi
movq $-0x80000000, %r8       # imm = 0x80000000
movl %ebx, %r9d
movl %r9d, %r10d
xorl %r11d, %r11d
movslq %r10d, %r10
movl %r10d, 0x80(%rsp,%r11,4)
movq %r10, %r12
subq %rcx, %r12
cmpq $-0x7fffffff, %r12      # imm = 0x80000001
cmovlq %r8, %r12
movl %r12d, 0x70(%rsp,%r11,4)
incq %r11
subl %edx, %r10d
cmpq $0x4, %r11
jne 0x436e67
movq %rdi, %r10
shlq $0x4, %r10
movaps 0x80(%rsp), %xmm4
movaps %xmm4, (%r14,%r10)
movaps 0x70(%rsp), %xmm4
movaps %xmm4, (%r13,%r10)
incq %rdi
movl 0x20(%rsp), %r10d
subl %r10d, %r9d
cmpq %rsi, %rdi
jne 0x436e61
movl $0x0, (%rax)
movl $0x1, %ecx
movq 0x60(%rsp), %rdx
movl %ebx, (%rax,%rcx,4)
incq %rcx
subl %r10d, %ebx
cmpq %rcx, %rdx
jne 0x436ed3
movq 0x48(%rsp), %r10
leal -0x1(%r10), %edi
movl $0x1, %r8d
cmpl %r8d, %r10d
adcl $0x0, %r10d
movl 0x1c(%rsp), %ecx
cmpl $0x2, %ecx
movl $0x1, %edx
cmovgel %ecx, %edx
movl %edx, 0x8(%rsp)
movl 0x28(%rsp), %edx
movq 0x10(%rsp), %rcx
cmpl $0x2, %ecx
cmovgel %ecx, %r8d
movq %r8, 0x10(%rsp)
movq %r10, %rbx
shlq $0x4, %rbx
xorl %ecx, %ecx
shlq $0x4, %rdi
movq %rdi, 0x20(%rsp)
movq %rdx, 0x28(%rsp)
shlq $0x4, %rdx
movq %rdx, 0x30(%rsp)
movdqa %xmm0, %xmm4
movdqa %xmm1, %xmm5
movq %r14, %r12
movq %rbp, %r14
movq 0x50(%rsp), %rdx
movq 0x10(%rdx), %rdx
movq 0x58(%rsp), %rdi
movzbl (%rdi,%rcx), %r8d
movslq (%rdx,%r8,4), %r8
movq %rsi, %rdx
imulq %r8, %rdx
shlq $0x4, %rdx
addq 0x68(%rsp), %rdx
movq 0x20(%rsp), %rdi
pshufd $0x90, (%r12,%rdi), %xmm7 # xmm7 = mem[0,0,1,2]
pinsrd $0x0, (%rax,%rcx,4), %xmm7
xorl %ebp, %ebp
movdqa %xmm0, %xmm6
paddd (%rdx,%rbp), %xmm7
movdqa (%r13,%rbp), %xmm8
movdqa %xmm8, %xmm9
pmaxsd %xmm6, %xmm9
pmaxsd %xmm7, %xmm9
movdqa %xmm9, (%r14,%rbp)
pmaxsd %xmm9, %xmm4
pminsd %xmm8, %xmm5
pminsd %xmm6, %xmm5
pminsd %xmm9, %xmm5
psubd %xmm2, %xmm9
psubd %xmm3, %xmm8
pmaxsd %xmm9, %xmm8
movdqa %xmm8, (%r13,%rbp)
psubd %xmm3, %xmm6
pmaxsd %xmm9, %xmm6
movdqa (%r12,%rbp), %xmm7
addq $0x10, %rbp
cmpq %rbp, %rbx
jne 0x436f8d
leaq 0x10(%r14), %r8
xorl %edx, %edx
movl 0x4(%rax,%rcx,4), %r9d
subl %r15d, %r9d
pshufd $0x90, %xmm6, %xmm6     # xmm6 = xmm6[0,0,1,2]
pinsrd $0x0, %r9d, %xmm6
movdqa (%r14), %xmm7
pmaxsd %xmm6, %xmm7
movdqa %xmm7, (%r14)
pminsd %xmm7, %xmm5
pmaxsd %xmm7, %xmm4
psubd %xmm2, %xmm7
psubd %xmm3, %xmm6
movdqa %xmm6, %xmm8
pcmpgtd %xmm7, %xmm8
movmskps %xmm8, %r9d
testl %r9d, %r9d
je 0x43709a
movl $0x1, %r11d
movq %r8, %rbp
movq %r11, %r9
cmpq %r11, %r10
je 0x437091
movdqa (%rbp), %xmm7
pmaxsd %xmm6, %xmm7
movdqa %xmm7, (%rbp)
pminsd %xmm7, %xmm5
pmaxsd %xmm7, %xmm4
psubd %xmm2, %xmm7
psubd %xmm3, %xmm6
movdqa %xmm6, %xmm8
pcmpgtd %xmm7, %xmm8
movmskps %xmm8, %edi
leaq 0x1(%r9), %r11
addq $0x10, %rbp
testl %edi, %edi
jne 0x43704e
cmpq %rsi, %r9
setb %r9b
jmp 0x43709d
movb $0x1, %r9b
testb %r9b, %r9b
jne 0x4370b0
leal 0x1(%rdx), %edi
cmpl $0x3, %edx
movl %edi, %edx
jb 0x436ffd
movq 0x30(%rsp), %rdx
movdqa (%r14,%rdx), %xmm6
cmpl $0x2, 0xc(%rsp)
jg 0x4370d6
movl 0x8(%rsp), %edx
movq 0x38(%rsp), %r9
pslldq $0x4, %xmm6             # xmm6 = zero,zero,zero,zero,xmm6[0,1,2,3,4,5,6,7,8,9,10,11]
decl %edx
jne 0x4370cb
jmp 0x4370db
movq 0x38(%rsp), %r9
movq 0x10(%r9), %rdx
movq (%rdx), %rdx
pextrd $0x3, %xmm6, (%rdx,%rcx,4)
incq %rcx
movq %r12, %rbp
cmpq 0x10(%rsp), %rcx
jne 0x436f47
movq 0x48(%rsp), %r10
cmpl $0x1, %r10d
adcl $0x0, %r10d
leaq (,%rsi,4), %rcx
leaq (%rcx,%rcx,2), %rdx
leaq (,%rsi,8), %rsi
shlq $0x2, %r10
xorl %edi, %edi
movdqa (%r14,%rdi,4), %xmm2
movq 0x10(%r9), %r8
movq 0x8(%r8), %r8
movd %xmm2, (%r8,%rdi)
addq %rdi, %r8
pextrd $0x1, %xmm2, (%rcx,%r8)
pextrd $0x2, %xmm2, (%rsi,%r8)
pextrd $0x3, %xmm2, (%rdx,%r8)
addq $0x4, %rdi
cmpq %rdi, %r10
jne 0x437121
movq 0x28(%rsp), %rcx
shlq $0x4, %rcx
movdqa (%r14,%rcx), %xmm2
cmpl $0x2, 0xc(%rsp)
jg 0x43718d
movl 0x1c(%rsp), %edx
cmpl $0x2, %edx
movl $0x1, %ecx
cmovgel %edx, %ecx
movl 0x18(%rsp), %esi
pslldq $0x4, %xmm2             # xmm2 = zero,zero,zero,zero,xmm2[0,1,2,3,4,5,6,7,8,9,10,11]
decl %ecx
jne 0x437182
jmp 0x437191
movl 0x18(%rsp), %esi
pcmpgtd %xmm5, %xmm0
pcmpgtd %xmm1, %xmm4
por %xmm0, %xmm4
movmskps %xmm4, %ecx
testl %ecx, %ecx
je 0x4371b1
orb $0x40, 0xc(%r9)
xorl %ecx, %ecx
xorl %esi, %esi
xorl %edx, %edx
jmp 0x4371bb
pextrd $0x3, %xmm2, %ecx
movl 0x44(%rsp), %edx
movl %ecx, (%r9)
movl %edx, 0x4(%r9)
movl %esi, 0x8(%r9)
movq %rax, %rdi
callq 0x2094b5
movq %r13, %rdi
callq 0x2094b5
movq %r12, %rdi
callq 0x2094b5
movq %r14, %rdi
callq 0x2094b5
movq 0x38(%rsp), %rax
jmp 0x437225
callq 0x1d418b
jmp 0x437223
callq 0x1d4165
jmp 0x437223
callq 0x1d413f
jmp 0x437223
callq 0x1d4119
jmp 0x437223
callq 0x1d40f3
jmp 0x437223
callq 0x1d40cd
jmp 0x437223
callq 0x1d40a7
jmp 0x437223
callq 0x1d4081
xorl %eax, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop