// File: /workspace/github_c_makefile_star2_O3/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 $0x48, %rsp
movl %ecx, (%rsp)
movq %rsi, 0x38(%rsp)
testq %rdi, %rdi
je 0x45c25b
movq 0x48(%rdi), %rax
movq %rax, 0x40(%rsp)
testq %rax, %rax
je 0x45c262
movq 0x10(%rdi), %rax
movq %rax, 0x30(%rsp)
testq %rax, %rax
je 0x45c269
movl 0x8(%rdi), %edi
testl %edi, %edi
jle 0x45c270
cmpq $0x0, 0x38(%rsp)
je 0x45c277
movl %edx, %r9d
testl %edx, %edx
jle 0x45c27e
cmpl $0x0, (%rsp)
js 0x45c285
testl %r8d, %r8d
js 0x45c28c
movq %r8, 0x18(%rsp)
leal -0x1(%rdi), %eax
addq $0x3, %rdi
movq %rdi, %rbp
shrq $0x2, %rbp
movl %eax, 0x14(%rsp)
xorl %edx, %edx
divl %ebp
movl %eax, 0x4(%rsp)
movl %edx, %ebx
movl (%rsp), %ecx
movl %ecx, %r15d
negl %r15d
movq 0x30(%rsp), %rdx
movl 0x20(%rdx), %eax
movl $0x80000000, %r12d      # imm = 0x80000000
orl %r12d, %ecx
subl %eax, %r12d
cmpl %r15d, %eax
cmovgl %ecx, %r12d
movl $0x7ffffffe, %r14d      # imm = 0x7FFFFFFE
subl 0x1c(%rdx), %r14d
andl $0x7ffffffc, %edi       # imm = 0x7FFFFFFC
movq %r9, 0x20(%rsp)
movl %r9d, %esi
callq 0x20ac53
testq %rax, %rax
je 0x45c291
movl %r14d, 0xc(%rsp)
movl %ebx, 0x10(%rsp)
movq %rax, 0x28(%rsp)
orl $0x4440801, 0xc(%rax)   # imm = 0x4440801
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 %rax, %r13
movq 0x20(%rsp), %rax
leal 0x1(%rax), %esi
movl $0x10, %edi
callq 0x20a62d
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 0x45c291
movq 0x20(%rsp), %rcx
movq %rcx, %r9
decl %ecx
movl %ecx, 0x8(%rsp)
movl $0x3, %edx
subl 0x4(%rsp), %edx
movd (%rsp), %xmm0
pshufd $0x0, %xmm0, %xmm3      # xmm3 = xmm0[0,0,0,0]
movd 0x18(%rsp), %xmm1
pshufd $0x0, %xmm1, %xmm4      # xmm4 = xmm1[0,0,0,0]
incl %r12d
movd %r12d, %xmm1
pshufd $0x0, %xmm1, %xmm1      # xmm1 = xmm1[0,0,0,0]
movd 0xc(%rsp), %xmm2
pshufd $0x0, %xmm2, %xmm2      # xmm2 = xmm2[0,0,0,0]
movd %r15d, %xmm5
pshufd $0x0, %xmm5, %xmm5      # xmm5 = xmm5[0,0,0,0]
pshufd $0x44, %xmm0, %xmm6     # xmm6 = xmm0[0,1,0,1]
movd %ebp, %xmm0
pshufd $0x44, %xmm0, %xmm7     # xmm7 = xmm0[0,1,0,1]
pmovsxbq 0x1d12aa(%rip), %xmm8   # 0x62d107
pmuldq %xmm7, %xmm8
pmuldq 0x1cd024(%rip), %xmm7   # 0x628e90
xorl %esi, %esi
pmovsxdq 0x1cfeb4(%rip), %xmm9   # 0x62bd2c
movq %r14, %rdi
movq %r13, %r8
movq %rsi, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movdqa %xmm8, %xmm10
paddq %xmm0, %xmm10
paddq %xmm7, %xmm0
shufps $0x88, %xmm10, %xmm0    # xmm0 = xmm0[0,2],xmm10[0,2]
pmulld %xmm4, %xmm0
movdqa %xmm5, %xmm10
psubd %xmm0, %xmm10
pmovsxdq %xmm10, %xmm11
pshufd $0xee, %xmm10, %xmm0    # xmm0 = xmm10[2,3,2,3]
pmovsxdq %xmm0, %xmm12
psubq %xmm6, %xmm12
psubq %xmm6, %xmm11
movdqa %xmm11, %xmm0
pcmpgtq %xmm9, %xmm0
movdqa %xmm9, %xmm13
blendvpd %xmm0, %xmm11, %xmm13
movdqa %xmm12, %xmm0
pcmpgtq %xmm9, %xmm0
movdqa %xmm9, %xmm11
blendvpd %xmm0, %xmm12, %xmm11
shufps $0x88, %xmm11, %xmm13   # xmm13 = xmm13[0,2],xmm11[0,2]
movdqa %xmm10, (%rdi)
movaps %xmm13, (%r8)
incq %rsi
addq $0x10, %r8
addq $0x10, %rdi
cmpq %rsi, %rbp
jne 0x45be7e
movl $0x0, (%rax)
movq %r9, %r12
movl %r12d, %esi
addl $0x3, %r12d
andl $-0x4, %r12d
leaq -0x1(%rsi), %rdi
movq %rdi, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movq 0x18(%rsp), %rcx
leal (%rcx,%rcx,2), %edi
negl %edi
leal (,%rcx,4), %r8d
leal (%rcx,%rcx), %r9d
negl %r9d
negl %ecx
xorl %r10d, %r10d
pmovsxbq 0x1d11aa(%rip), %xmm5   # 0x62d107
pmovsxbq 0x1d11a3(%rip), %xmm6   # 0x62d109
movdqa 0x1cfd22(%rip), %xmm7   # 0x62bc90
pxor %xmm7, %xmm0
pcmpeqd %xmm8, %xmm8
movq %r10, %xmm9
movdqa %xmm9, %xmm10
pxor %xmm7, %xmm10
pcmpgtq %xmm0, %xmm10
movd %xmm10, %r11d
notl %r11d
testb $0x1, %r11b
je 0x45bf9f
movl %r15d, 0x4(%rax,%r10,4)
pshufd $0x44, %xmm9, %xmm9     # xmm9 = xmm9[0,1,0,1]
movdqa %xmm9, %xmm10
por %xmm6, %xmm10
pxor %xmm7, %xmm10
pcmpgtq %xmm0, %xmm10
pxor %xmm8, %xmm10
pextrb $0x8, %xmm10, %r11d
testb $0x1, %r11b
je 0x45bfd5
leal (%rcx,%r15), %r11d
movl %r11d, 0x8(%rax,%r10,4)
por %xmm5, %xmm9
pxor %xmm7, %xmm9
pcmpgtq %xmm0, %xmm9
pxor %xmm8, %xmm9
pextrb $0x0, %xmm9, %r11d
testb $0x1, %r11b
je 0x45c000
leal (%r9,%r15), %r11d
movl %r11d, 0xc(%rax,%r10,4)
pextrb $0x8, %xmm9, %r11d
testb $0x1, %r11b
je 0x45c016
leal (%rdi,%r15), %r11d
movl %r11d, 0x10(%rax,%r10,4)
addq $0x4, %r10
subl %r8d, %r15d
cmpq %r10, %r12
jne 0x45bf77
leal -0x1(%rbp), %r8d
movl 0x10(%rsp), %edi
movl %ebp, %r9d
movq %r9, %r10
shlq $0x4, %r10
xorl %r11d, %r11d
shlq $0x4, %r8
movq %rdi, %r15
shlq $0x4, %r15
movdqa %xmm1, %xmm0
movdqa %xmm2, %xmm5
movq %r14, %r12
movq %rbx, %r14
movq 0x30(%rsp), %rcx
movq 0x10(%rcx), %rbx
movq 0x38(%rsp), %rcx
movzbl (%rcx,%r11), %ebp
movslq (%rbx,%rbp,4), %rbp
movq %r9, %rbx
imulq %rbp, %rbx
shlq $0x4, %rbx
addq 0x40(%rsp), %rbx
pshufd $0x90, (%r12,%r8), %xmm7 # xmm7 = mem[0,0,1,2]
pinsrd $0x0, (%rax,%r11,4), %xmm7
xorl %ebp, %ebp
movdqa %xmm1, %xmm6
paddd (%rbx,%rbp), %xmm7
movdqa (%r13,%rbp), %xmm8
movdqa %xmm8, %xmm9
pmaxsd %xmm6, %xmm9
pmaxsd %xmm7, %xmm9
movdqa %xmm9, (%r14,%rbp)
pmaxsd %xmm9, %xmm0
pminsd %xmm8, %xmm5
pminsd %xmm6, %xmm5
pminsd %xmm9, %xmm5
psubd %xmm3, %xmm9
psubd %xmm4, %xmm8
pmaxsd %xmm9, %xmm8
movdqa %xmm8, (%r13,%rbp)
psubd %xmm4, %xmm6
pmaxsd %xmm9, %xmm6
movdqa (%r12,%rbp), %xmm7
addq $0x10, %rbp
cmpq %rbp, %r10
jne 0x45c090
xorl %ebx, %ebx
movl 0x4(%rax,%r11,4), %ebp
subl (%rsp), %ebp
pshufd $0x90, %xmm6, %xmm6     # xmm6 = xmm6[0,0,1,2]
pinsrd $0x0, %ebp, %xmm6
xorl %ebp, %ebp
movdqa (%r14,%rbp), %xmm7
pmaxsd %xmm6, %xmm7
movdqa %xmm7, (%r14,%rbp)
pminsd %xmm7, %xmm5
pmaxsd %xmm7, %xmm0
psubd %xmm3, %xmm7
psubd %xmm4, %xmm6
movdqa %xmm6, %xmm8
pcmpgtd %xmm7, %xmm8
movmskps %xmm8, %ecx
testl %ecx, %ecx
je 0x45c156
addq $0x10, %rbp
cmpq %rbp, %r10
jne 0x45c111
incl %ebx
cmpl $0x4, %ebx
jne 0x45c0fc
movdqa (%r14,%r15), %xmm6
cmpl $0x2, 0x4(%rsp)
jg 0x45c170
xorl %ebx, %ebx
pslldq $0x4, %xmm6             # xmm6 = zero,zero,zero,zero,xmm6[0,1,2,3,4,5,6,7,8,9,10,11]
incl %ebx
cmpl %edx, %ebx
jl 0x45c165
movq 0x28(%rsp), %rcx
movq 0x10(%rcx), %rcx
movq (%rcx), %rcx
pextrd $0x3, %xmm6, (%rcx,%r11,4)
incq %r11
movq %r12, %rbx
cmpq %rsi, %r11
jne 0x45c04e
leaq (,%r9,4), %rsi
leaq (%rsi,%rsi,2), %r8
leaq (,%r9,8), %r9
xorl %r10d, %r10d
movq 0x28(%rsp), %rbx
movdqa (%r14,%r10,4), %xmm3
movq 0x10(%rbx), %rcx
movq 0x8(%rcx), %rcx
movd %xmm3, (%rcx,%r10)
addq %r10, %rcx
pextrd $0x1, %xmm3, (%rsi,%rcx)
pextrd $0x2, %xmm3, (%r9,%rcx)
pextrd $0x3, %xmm3, (%r8,%rcx)
addq $0x4, %r10
cmpq %r10, %rsi
jne 0x45c1af
shlq $0x4, %rdi
movdqa (%r14,%rdi), %xmm3
cmpl $0x2, 0x4(%rsp)
jg 0x45c204
xorl %esi, %esi
pslldq $0x4, %xmm3             # xmm3 = zero,zero,zero,zero,xmm3[0,1,2,3,4,5,6,7,8,9,10,11]
incl %esi
cmpl %edx, %esi
jl 0x45c1f9
pcmpgtd %xmm5, %xmm1
pcmpgtd %xmm2, %xmm0
por %xmm1, %xmm0
movmskps %xmm0, %ecx
testl %ecx, %ecx
movl 0x8(%rsp), %esi
je 0x45c227
orb $0x40, 0xc(%rbx)
xorl %edx, %edx
xorl %esi, %esi
xorl %ecx, %ecx
jmp 0x45c231
pextrd $0x3, %xmm3, %edx
movl 0x14(%rsp), %ecx
movl %edx, (%rbx)
movl %ecx, 0x4(%rbx)
movl %esi, 0x8(%rbx)
movq %rax, %rdi
callq 0x20a60d
movq %r13, %rdi
callq 0x20a60d
movq %r12, %rdi
callq 0x20a60d
movq %r14, %rdi
callq 0x20a60d
jmp 0x45c293
callq 0x1d417f
jmp 0x45c291
callq 0x1d4159
jmp 0x45c291
callq 0x1d4133
jmp 0x45c291
callq 0x1d410d
jmp 0x45c291
callq 0x1d40e7
jmp 0x45c291
callq 0x1d40c1
jmp 0x45c291
callq 0x1d409b
jmp 0x45c291
callq 0x1d4075
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)