// File: /workspace/github_c_makefile_star2_O1/nh13[P]ksw/src/parasail/src/nw_striped_sse2_128_32.c
// Function: parasail_nw_table_striped_profile_sse2_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_rpl(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_rpl(vH, vE);
            vH = _mm_max_epi32_rpl(vH, vF);
            /* Save vH values. */
            _mm_store_si128(pvHStore + i, vH);
            vSaturationCheckMax = _mm_max_epi32_rpl(vSaturationCheckMax, vH);
            vSaturationCheckMin = _mm_min_epi32_rpl(vSaturationCheckMin, vH);
            vSaturationCheckMin = _mm_min_epi32_rpl(vSaturationCheckMin, vE);
            vSaturationCheckMin = _mm_min_epi32_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_epi32(vH, vGapO);
            vE = _mm_sub_epi32(vE, vGapE);
            vE = _mm_max_epi32_rpl(vE, vH);
            _mm_store_si128(pvE + i, vE);

            /* Update vF value. */
            vF = _mm_sub_epi32(vF, vGapE);
            vF = _mm_max_epi32_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;
            int32_t tmp2 = tmp < INT32_MIN ? INT32_MIN : tmp;
            vF = _mm_slli_si128(vF, 4);
            vF = _mm_insert_epi32_rpl(vF, tmp2, 0);
            for (i=0; i<segLen; ++i) {
                vH = _mm_load_si128(pvHStore + i);
                vH = _mm_max_epi32_rpl(vH,vF);
                _mm_store_si128(pvHStore + i, vH);
                vSaturationCheckMin = _mm_min_epi32_rpl(vSaturationCheckMin, vH);
                vSaturationCheckMax = _mm_max_epi32_rpl(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_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, 4);
            }
            result->rowcols->score_row[j] = (int32_t) _mm_extract_epi32_rpl (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_rpl (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 $0xa8, %rsp
movl %ecx, 0xc(%rsp)
movq %rsi, 0x60(%rsp)
testq %rdi, %rdi
je 0x2ffe6f
movq 0x48(%rdi), %rax
movq %rax, 0x78(%rsp)
testq %rax, %rax
je 0x2ffe76
movq 0x10(%rdi), %rax
movq %rax, 0x58(%rsp)
testq %rax, %rax
je 0x2ffe7d
movl 0x8(%rdi), %edi
testl %edi, %edi
jle 0x2ffe84
cmpq $0x0, 0x60(%rsp)
je 0x2ffe8b
movl %edx, %r15d
testl %edx, %edx
jle 0x2ffe92
cmpl $0x0, 0xc(%rsp)
js 0x2ffe99
testl %r8d, %r8d
js 0x2ffea0
movl %r8d, 0x38(%rsp)
leal -0x1(%rdi), %r12d
addq $0x3, %rdi
movq %rdi, %rbp
shrq $0x2, %rbp
movl %r12d, %eax
cltd
idivl %ebp
movl %eax, %r13d
movl %edx, 0x4c(%rsp)
movl 0xc(%rsp), %ecx
movl %ecx, %esi
negl %esi
movq 0x58(%rsp), %rdx
movl 0x20(%rdx), %eax
movl $0x80000000, %r14d      # imm = 0x80000000
orl %r14d, %ecx
subl %eax, %r14d
movl %esi, 0x18(%rsp)
cmpl %esi, %eax
cmovgl %ecx, %r14d
movl $0x7ffffffe, %eax       # imm = 0x7FFFFFFE
subl 0x1c(%rdx), %eax
movl %eax, 0x30(%rsp)
andl $0x7ffffffc, %edi       # imm = 0x7FFFFFFC
movl %r15d, %esi
movq %r15, 0x10(%rsp)
callq 0x20959f
testq %rax, %rax
je 0x2ffea5
movq %rax, %rbx
movl %r13d, 0x24(%rsp)
movl %r12d, 0x48(%rsp)
orl $0x4420801, 0xc(%rax)   # imm = 0x4420801
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2ea474
movq %rax, %r12
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2ea474
movq %rax, %r15
movl $0x10, %edi
movq %rbp, %rsi
callq 0x2ea474
movq %rax, %r13
movq 0x10(%rsp), %rax
leal 0x1(%rax), %esi
movl $0x10, %edi
movq %rsi, 0x68(%rsp)
callq 0x2094d5
testq %r12, %r12
sete %dl
movq %r15, 0x70(%rsp)
testq %r15, %r15
sete %cl
orb %dl, %cl
movq %r13, 0x50(%rsp)
testq %r13, %r13
sete %sil
movq %rax, 0x28(%rsp)
testq %rax, %rax
sete %dl
orb %sil, %dl
orb %cl, %dl
jne 0x2ffea5
movq 0x10(%rsp), %rax
decl %eax
movl %eax, 0x20(%rsp)
movl $0x3, %eax
subl 0x24(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0xc(%rsp), %eax
movd %eax, %xmm0
pshufd $0x0, %xmm0, %xmm2      # xmm2 = xmm0[0,0,0,0]
movl 0x38(%rsp), %ecx
movd %ecx, %xmm0
pshufd $0x0, %xmm0, %xmm3      # xmm3 = xmm0[0,0,0,0]
incl %r14d
movd %r14d, %xmm0
movl %ecx, %r14d
pshufd $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
movd 0x30(%rsp), %xmm1
pshufd $0x0, %xmm1, %xmm1      # xmm1 = xmm1[0,0,0,0]
movl %eax, %eax
movl %ebp, %esi
imull %ebp, %ecx
xorl %edx, %edx
movq $-0x80000000, %r15      # imm = 0x80000000
movl 0x18(%rsp), %r8d
movq 0x50(%rsp), %r13
movq 0x28(%rsp), %rdi
movl %r8d, %r9d
xorl %r10d, %r10d
movslq %r9d, %r9
movl %r9d, 0x90(%rsp,%r10,4)
movq %r9, %r11
subq %rax, %r11
cmpq $-0x7fffffff, %r11      # imm = 0x80000001
cmovlq %r15, %r11
movl %r11d, 0x80(%rsp,%r10,4)
incq %r10
subl %ecx, %r9d
cmpq $0x4, %r10
jne 0x2ffa30
movq %rdx, %r9
shlq $0x4, %r9
movaps 0x90(%rsp), %xmm4
movaps %xmm4, (%r12,%r9)
movaps 0x80(%rsp), %xmm4
movaps %xmm4, (%r13,%r9)
incq %rdx
subl %r14d, %r8d
cmpq %rsi, %rdx
jne 0x2ffa2a
movl $0x0, (%rdi)
movl $0x1, %eax
movl 0x18(%rsp), %ecx
movq 0x68(%rsp), %rdx
movl %ecx, (%rdi,%rax,4)
incq %rax
subl %r14d, %ecx
cmpq %rax, %rdx
jne 0x2ffaa1
leal -0x1(%rbp), %eax
movq 0x10(%rsp), %rdx
movl %edx, %r8d
cmpl $0x1, %ebp
adcl $0x0, %ebp
cmpl $0x2, %edx
movl $0x1, %ecx
cmovgel %edx, %ecx
movq %rcx, 0x30(%rsp)
movq %rsi, %r10
imulq %r8, %r10
leaq (,%r10,4), %r11
shlq $0x2, %r8
shlq $0x3, %r10
leaq (%r11,%r11,2), %rcx
shlq $0x4, %rbp
xorl %r14d, %r14d
shlq $0x4, %rax
movq %rax, 0x38(%rsp)
xorl %r9d, %r9d
movdqa %xmm0, %xmm4
movdqa %xmm1, %xmm5
movq 0x70(%rsp), %rax
movq %r12, %r15
movq %rax, %r12
movq 0x58(%rsp), %rax
movq 0x10(%rax), %rdx
movq 0x60(%rsp), %rax
movq %r9, %rdi
movzbl (%rax,%r9), %r9d
movq %r15, %rax
movslq (%rdx,%r9,4), %rdx
movq %rsi, %r9
imulq %rdx, %r9
shlq $0x4, %r9
addq 0x78(%rsp), %r9
movq 0x38(%rsp), %rdx
pshufd $0x90, (%r15,%rdx), %xmm7 # xmm7 = mem[0,0,1,2]
movq %rdi, 0x10(%rsp)
movq 0x28(%rsp), %rdx
movss (%rdx,%rdi,4), %xmm6
movss %xmm6, %xmm7            # xmm7 = xmm6[0],xmm7[1,2,3]
movq %r14, %rdi
movq %r14, %rdx
xorl %r15d, %r15d
movdqa %xmm0, %xmm6
paddd (%r9,%r15), %xmm7
movdqa (%r13,%r15), %xmm8
movdqa %xmm7, %xmm9
pcmpgtd %xmm8, %xmm9
pand %xmm9, %xmm7
pandn %xmm8, %xmm9
por %xmm7, %xmm9
movdqa %xmm9, %xmm7
pcmpgtd %xmm6, %xmm7
pand %xmm7, %xmm9
pandn %xmm6, %xmm7
por %xmm9, %xmm7
movdqa %xmm7, (%r12,%r15)
movdqa %xmm4, %xmm9
pcmpgtd %xmm7, %xmm4
pand %xmm4, %xmm9
pandn %xmm7, %xmm4
por %xmm9, %xmm4
movdqa %xmm5, %xmm9
pcmpgtd %xmm7, %xmm9
movdqa %xmm7, %xmm10
pand %xmm9, %xmm10
pandn %xmm5, %xmm9
por %xmm10, %xmm9
movdqa %xmm9, %xmm10
pcmpgtd %xmm8, %xmm10
movdqa %xmm8, %xmm5
pand %xmm10, %xmm5
pandn %xmm9, %xmm10
por %xmm5, %xmm10
movdqa %xmm10, %xmm5
pcmpgtd %xmm6, %xmm5
movdqa %xmm6, %xmm9
pand %xmm5, %xmm9
pandn %xmm10, %xmm5
por %xmm9, %xmm5
movq 0x10(%rbx), %r14
movq (%r14), %r14
movd %xmm7, (%r14,%rdx)
addq %rdx, %r14
pshufd $0x55, %xmm7, %xmm9     # xmm9 = xmm7[1,1,1,1]
movd %xmm9, (%r11,%r14)
pshufd $0xee, %xmm7, %xmm9     # xmm9 = xmm7[2,3,2,3]
movd %xmm9, (%r10,%r14)
pshufd $0xff, %xmm7, %xmm9     # xmm9 = xmm7[3,3,3,3]
movd %xmm9, (%rcx,%r14)
psubd %xmm2, %xmm7
psubd %xmm3, %xmm8
movdqa %xmm8, %xmm9
pcmpgtd %xmm7, %xmm9
pand %xmm9, %xmm8
pandn %xmm7, %xmm9
por %xmm8, %xmm9
movdqa %xmm9, (%r13,%r15)
psubd %xmm3, %xmm6
movdqa %xmm6, %xmm8
pcmpgtd %xmm7, %xmm6
pand %xmm6, %xmm8
pandn %xmm7, %xmm6
por %xmm8, %xmm6
movdqa (%rax,%r15), %xmm7
addq $0x10, %r15
addq %r8, %rdx
cmpq %r15, %rbp
jne 0x2ffb6a
movq %rax, 0x18(%rsp)
xorl %r9d, %r9d
movq 0x28(%rsp), %rax
movq 0x10(%rsp), %rdx
movl 0x4(%rax,%rdx,4), %edx
subl 0xc(%rsp), %edx
movd %edx, %xmm7
pshufd $0x90, %xmm6, %xmm6     # xmm6 = xmm6[0,0,1,2]
movss %xmm7, %xmm6            # xmm6 = xmm7[0],xmm6[1,2,3]
movb $0x1, %dl
movl $0x1, %r15d
movq %rdi, %r14
xorl %r13d, %r13d
movdqa (%r12,%r13), %xmm8
movdqa %xmm8, %xmm7
pcmpgtd %xmm6, %xmm7
pand %xmm7, %xmm8
pandn %xmm6, %xmm7
por %xmm8, %xmm7
movdqa %xmm7, (%r12,%r13)
movdqa %xmm5, %xmm8
pcmpgtd %xmm7, %xmm8
movdqa %xmm7, %xmm9
pand %xmm8, %xmm9
pandn %xmm5, %xmm8
movdqa %xmm8, %xmm5
por %xmm9, %xmm5
movdqa %xmm4, %xmm8
pcmpgtd %xmm7, %xmm4
pand %xmm4, %xmm8
pandn %xmm7, %xmm4
por %xmm8, %xmm4
movq 0x10(%rbx), %rax
movq (%rax), %rax
movd %xmm7, (%rax,%r14)
addq %r14, %rax
pshufd $0x55, %xmm7, %xmm8     # xmm8 = xmm7[1,1,1,1]
movd %xmm8, (%r11,%rax)
pshufd $0xee, %xmm7, %xmm8     # xmm8 = xmm7[2,3,2,3]
movd %xmm8, (%r10,%rax)
pshufd $0xff, %xmm7, %xmm8     # xmm8 = xmm7[3,3,3,3]
movd %xmm8, (%rcx,%rax)
psubd %xmm2, %xmm7
psubd %xmm3, %xmm6
movdqa %xmm6, %xmm8
pcmpgtd %xmm7, %xmm8
movmskps %xmm8, %eax
testl %eax, %eax
je 0x2ffda4
cmpq %rsi, %r15
setb %dl
addq $0x10, %r13
addq %r8, %r14
incq %r15
cmpq %r13, %rbp
jne 0x2ffce0
testb $0x1, %dl
jne 0x2ffdba
leal 0x1(%r9), %eax
cmpl $0x3, %r9d
movl %eax, %r9d
jb 0x2ffcb3
movq 0x10(%rsp), %r9
incq %r9
movq %rdi, %r14
addq $0x4, %r14
movq 0x18(%rsp), %rax
cmpq 0x30(%rsp), %r9
movq 0x50(%rsp), %r13
movq 0x28(%rsp), %rdi
jne 0x2ffb0b
movl 0x4c(%rsp), %eax
shlq $0x4, %rax
movdqa (%r12,%rax), %xmm2
cmpl $0x2, 0x24(%rsp)
jg 0x2ffe16
movl 0x44(%rsp), %ecx
cmpl $0x2, %ecx
movl $0x1, %eax
cmovgel %ecx, %eax
movl 0x20(%rsp), %edx
pslldq $0x4, %xmm2             # xmm2 = zero,zero,zero,zero,xmm2[0,1,2,3,4,5,6,7,8,9,10,11]
decl %eax
jne 0x2ffe0b
jmp 0x2ffe1a
movl 0x20(%rsp), %edx
pcmpgtd %xmm5, %xmm0
pcmpgtd %xmm1, %xmm4
por %xmm0, %xmm4
movmskps %xmm4, %eax
testl %eax, %eax
je 0x2ffe39
orb $0x40, 0xc(%rbx)
xorl %eax, %eax
xorl %edx, %edx
xorl %ecx, %ecx
jmp 0x2ffe46
pshufd $0xff, %xmm2, %xmm0     # xmm0 = xmm2[3,3,3,3]
movd %xmm0, %eax
movl 0x48(%rsp), %ecx
movl %eax, (%rbx)
movl %ecx, 0x4(%rbx)
movl %edx, 0x8(%rbx)
callq 0x2094b5
movq %r13, %rdi
callq 0x2094b5
movq 0x18(%rsp), %rdi
callq 0x2094b5
movq %r12, %rdi
callq 0x2094b5
jmp 0x2ffea7
callq 0x1adef3
jmp 0x2ffea5
callq 0x1adecd
jmp 0x2ffea5
callq 0x1adea7
jmp 0x2ffea5
callq 0x1ade81
jmp 0x2ffea5
callq 0x1ade5b
jmp 0x2ffea5
callq 0x1ade35
jmp 0x2ffea5
callq 0x1ade0f
jmp 0x2ffea5
callq 0x1adde9
xorl %ebx, %ebx
movq %rbx, %rax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq