// File: /workspace/github_cpp_makefile_star2_O1/xbai0624[P]dnn/src/ConstructLayer.cpp
// Function: ConstructLayer::UpdateWeightsAndBiasFC()
void ConstructLayer::UpdateWeightsAndBiasFC()
{
    //cout<<__func__<<" started..."<<endl;
    // after finishing one batch, update weights and bias, for FC layer
    size_t M = __imageDeltaFull.size(); // batch size
    if( M != __wGradient.size() ) {
        std::cout<<__func__<<" Error: update FC weights, batch size not match."<<std::endl;
        std::cout<<"           weight gradient batch size: "<<__wGradient.size()<<std::endl;
        std::cout<<"           delta image batch size: "<<__imageDeltaFull.size()<<std::endl;
        exit(0);
    }
    if( __wGradient[0].OutputImageFromKernel.size() != 1 || __bGradient[0].OutputImageFromKernel.size()!=1) 
    {
        std::cout<<__func__<<" Error: update FC weiths, more than 1 w gradient matrix found."
            <<std::endl;
        exit(0);
    }

    // gradient descent
    if(__weightMatrix.size() != __neuronDim.k) {
        std::cout<<__func__<<" Error: update FC layer weights, more than 1 weight matrix found."<<std::endl;
        std::cout<<"__weightMatrix size: "<<__weightMatrix.size()<<std::endl;
        std::cout<<"neuron dimension: "<<__neuronDim<<std::endl;
        exit(0);
    }
    Matrix dw((__weightMatrix[0]).Dimension(), 0); 
    for(size_t i=0;i<M;i++){ // sum x (batches)
        dw  = dw + __wGradient[i].OutputImageFromKernel[0];
        //cout<<__wGradient[i].OutputImageFromKernel[0]<<endl;
        //cout<<i<<" before sum"<<endl;
        //getchar();
    }

    if(__weights_optimizer == WeightsOptimizer::SGD)
    {
        // standard SGD 
        dw = dw * double(__learningRate/(double)M); // over batch 
    }
    else if(__weights_optimizer == WeightsOptimizer::Adam)
    {
        // Adam optimizer
        dw = dw * (1./ (double)M );

        //Matrix tmp = dw * __learningRate;
        //cout<<"Before adam: "<<endl<<dw<<endl;
        dw = AdamOptimizer(dw, 0);
        //cout<<"after adam: "<<endl<<dw<<endl;
        //getchar();
    }
    else
    {
        std::cout<<__func__<<" Error: unsupported optimization method."<<std::endl;
        exit(0);
    }
    //cout<<"learning rate: "<<double(__learningRate/(double)M)<<endl;

    // Get filter Matrix for masking Regularization item
    assert(__activeFlag.size() == 1);
    auto convertFilterToMatrix = [&](Filter2D & F) -> Matrix
    {
        auto dim = F.Dimension();
        Matrix M(dim, 0);
        for(size_t i=0;i<dim.first;i++)
        {
            for(size_t j=0;j<dim.second;j++)
            {
                if(F[i][j]) M[i][j] = 1;
            }
        }
        return M;
    };
    Matrix currentLayerFilter = convertFilterToMatrix(__activeFlag[0]);
    //cout<<currentLayerFilter.Dimension()<<endl;
    Matrix prevLayerFilter(1, dw.Dimension().second, 1);
    //cout<<"before: "<<endl<<prevLayerFilter<<endl;

    if(__prevLayer->GetType() == LayerType::input) // only fc layer need this, other layers won't affect
    {
        auto & prevLayerFilters = __prevLayer->GetActiveFlag();
        assert(prevLayerFilters.size() == 1);
        assert(prevLayerFilters[0].Dimension().first == (size_t)__prevLayer->GetNumberOfNeurons());

        Matrix filter = convertFilterToMatrix(prevLayerFilters[0]);
        prevLayerFilter = filter.Transpose();
        //cout<<"after: "<<endl<<prevLayerFilter<<endl;
    }

    // following is two flag matrix (dim[n,1] x dim[1, m], with bool elements) product
    // all the elements of the product will be either 0 or 1
    // this product can be used to mask out disabled elements in weight matrix regularization
    Matrix F = currentLayerFilter * prevLayerFilter;
    //cout<<F<<endl;
    //cout<<prevLayerFilter<<endl;
    //cout<<dw<<endl;
    //getchar();

    assert(F.Dimension() == (__weightMatrix[0]).Dimension());
    // Regularization
    //double f_regularization = 0.;
    if(__regularizationMethod == Regularization::L2) 
    {
        // obsolete
        //f_regularization = 1 - __learningRate * __regularizationParameter / M;
        //(__weightMatrix[0]) = (__weightMatrix[0]) * f_regularization - dw;

        // new
        // hadamard multiply with F to maks out all inactive elements
        Matrix regularization_M = (__weightMatrix[0]^F) *(__learningRate * __regularizationParameter/((double)M)); 
        Matrix total_correction_M = regularization_M + dw; // dw already include learning rate during generation
        __weightMatrix[0] = __weightMatrix[0] - total_correction_M;
    } 
    else if(__regularizationMethod == Regularization::L1) 
    {
        Matrix _t = (__weightMatrix[0]); // make a copy of weight matrix
        _t(&SGN); // get the sign for each element in weight matrix
        _t = _t^F; // hadamard operation to mask out all inactive elements
        _t = _t * (__learningRate*__regularizationParameter/(double)M); // L1 regularization part
        (__weightMatrix[0]) = (__weightMatrix[0]) -  _t; // apply L1 regularization to weight matrix
        (__weightMatrix[0]) = (__weightMatrix[0]) - dw; // apply gradient decsent part
    } 
    else 
    {
        std::cout<<__func__<<" Error: update FC weights, unsupported regularization."<<std::endl;
        exit(0);
    }

    //cout<<"reached hrere..."<<endl;

    if(!__use_batch_normalization || 
            (__type != LayerType::cnn && __type != LayerType::fullyConnected && __type != LayerType::output))
    {
        // for cnn, fc, output layers, if BN is not used, one need to update b paramter.
        // if BN is used, b parameter is discarded (combined into \beta parameter)
        // bias
        Matrix db(__biasVector[0].Dimension());
        for(size_t i=0;i<M;i++){
            db = db + __bGradient[i].OutputImageFromKernel[0];
        }
        db = db / (double)M;
        db = db * __learningRate;
        __biasVector[0] = __biasVector[0] - db;
    }
    //cout<<__func__<<" ended.."<<endl;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movq %rdi, %r13
movq 0x1e8(%rdi), %rbp
movq 0x1e0(%rdi), %rax
movq %rbp, 0x98(%rsp)
movq %rax, 0x90(%rsp)
subq %rax, %rbp
movabsq $-0x5555555555555555, %r12 # imm = 0xAAAAAAAAAAAAAAAB
movq 0x90(%rdi), %rax
movq 0x98(%rdi), %rcx
subq %rax, %rcx
cmpq %rcx, %rbp
jne 0xf4a5
movq 0x8(%rax), %rcx
subq (%rax), %rcx
cmpq $0x18, %rcx
jne 0xf47e
movq 0xa8(%r13), %rax
movq 0x8(%rax), %rcx
subq (%rax), %rcx
cmpq $0x18, %rcx
jne 0xf47e
movq 0x60(%r13), %rdi
movq 0x68(%r13), %rax
subq %rdi, %rax
sarq $0x3, %rax
imulq %r12, %rax
cmpq 0x3a8(%r13), %rax
jne 0xf536
sarq $0x3, %rbp
imulq %r12, %rbp
callq 0x1ac7c
leaq 0x48(%rsp), %rdi
xorpd %xmm0, %xmm0
movq %rax, %rsi
callq 0x1a9ec
movq 0x90(%rsp), %rax
cmpq %rax, 0x98(%rsp)
je 0xed26
cmpq $0x1, %rbp
movq %rbp, %rbx
adcq $0x0, %rbx
xorl %r12d, %r12d
leaq 0x30(%rsp), %r14
leaq 0x48(%rsp), %r15
movq 0x90(%r13), %rax
movq (%rax,%r12), %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x1aef8
movq %r15, %rdi
movq %r14, %rsi
callq 0x14f80
movq %r14, %rdi
callq 0x1acb6
addq $0x18, %r12
decq %rbx
jne 0xecf4
movl 0x440(%r13), %eax
movq %rbp, %xmm1
testl %eax, %eax
movdqa %xmm1, 0xa0(%rsp)
je 0xedc9
cmpl $0x1, %eax
jne 0xf600
movapd 0xa0(%rsp), %xmm0
unpcklps 0x182e4(%rip), %xmm0    # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x182ec(%rip), %xmm0    # 0x27050
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movsd 0x18808(%rip), %xmm0    # 0x27580
divsd %xmm1, %xmm0
leaq 0x30(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x1b7d0
leaq 0x48(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x14f80
leaq 0x30(%rsp), %rdi
callq 0x1acb6
leaq 0x30(%rsp), %rdi
leaq 0x48(%rsp), %rdx
movq %r13, %rsi
xorl %ecx, %ecx
callq 0x10a60
leaq 0x48(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x14f80
jmp 0xee10
movsd 0xc0(%r13), %xmm0
punpckldq 0x18266(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x1826e(%rip), %xmm1    # 0x27050
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
leaq 0x30(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x1b7d0
leaq 0x48(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x14f80
leaq 0x30(%rsp), %rdi
callq 0x1acb6
movq 0x108(%r13), %rbx
movq 0x110(%r13), %rax
subq %rbx, %rax
cmpq $0x18, %rax
jne 0xf5c2
movq (%rbx), %rax
movq 0x8(%rbx), %rcx
subq %rax, %rcx
je 0xee63
sarq $0x3, %rcx
movabsq $-0x3333333333333333, %r14 # imm = 0xCCCCCCCCCCCCCCCD
imulq %rcx, %r14
movq 0x10(%rax), %rcx
movl 0x18(%rax), %edx
subq (%rax), %rcx
leaq (%rdx,%rcx,8), %r15
jmp 0xee69
xorl %r14d, %r14d
xorl %r15d, %r15d
movq %rbp, 0x80(%rsp)
movq %r13, 0x88(%rsp)
leaq 0x30(%rsp), %rdi
xorpd %xmm0, %xmm0
movq %r14, %rsi
movq %r15, %rdx
callq 0x1a9ec
movq %r14, 0x60(%rsp)
testq %r14, %r14
je 0xef24
movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000
xorl %r12d, %r12d
leaq 0x3f(%rax), %r14
testq %r15, %r15
je 0xef1a
leaq (%r12,%r12,4), %r13
xorl %ebp, %ebp
movq (%rbx), %rax
leaq 0x3f(%rbp), %rcx
testq %rbp, %rbp
cmovnsq %rbp, %rcx
sarq $0x6, %rcx
shlq $0x3, %rcx
addq (%rax,%r13,8), %rcx
movq %rbp, %rax
andq %r14, %rax
xorl %edx, %edx
movabsq $-0x8000000000000000, %rsi # imm = 0x8000000000000000
cmpq %rsi, %rax
setbe %dl
movq -0x8(%rcx,%rdx,8), %rax
btq %rbp, %rax
jae 0xef12
leaq 0x30(%rsp), %rdi
movq %r12, %rsi
callq 0x1ae76
movq (%rax), %rax
movabsq $0x3ff0000000000000, %rcx # imm = 0x3FF0000000000000
movq %rcx, (%rax,%rbp,8)
incq %rbp
cmpq %rbp, %r15
jne 0xeeb7
incq %r12
cmpq 0x60(%rsp), %r12
jne 0xeeac
leaq 0x48(%rsp), %rdi
callq 0x1ac7c
leaq 0xb8(%rsp), %rdi
movsd 0x18642(%rip), %xmm0    # 0x27580
movl $0x1, %esi
callq 0x1a952
movq 0x88(%rsp), %r12
movq 0x3f0(%r12), %rdi
movq (%rdi), %rax
callq *0x250(%rax)
movq 0x80(%rsp), %r13
cmpl $0x3, %eax
jne 0xf0ff
movq 0x3f0(%r12), %rdi
movq (%rdi), %rax
callq *0x268(%rax)
movq %rax, %r14
movq (%rax), %rax
movq 0x8(%r14), %rcx
subq %rax, %rcx
cmpq $0x18, %rcx
jne 0xf641
movq 0x8(%rax), %rcx
subq (%rax), %rcx
je 0xefb7
sarq $0x3, %rcx
movabsq $-0x3333333333333333, %rbx # imm = 0xCCCCCCCCCCCCCCCD
imulq %rcx, %rbx
jmp 0xefb9
xorl %ebx, %ebx
movq 0x3f0(%r12), %rdi
movq (%rdi), %rax
callq *0x278(%rax)
cltq
cmpq %rax, %rbx
jne 0xf660
movq (%r14), %rbx
movq (%rbx), %rax
movq 0x8(%rbx), %rcx
subq %rax, %rcx
je 0xf006
sarq $0x3, %rcx
movabsq $-0x3333333333333333, %r13 # imm = 0xCCCCCCCCCCCCCCCD
imulq %rcx, %r13
movq 0x10(%rax), %rcx
movl 0x18(%rax), %edx
subq (%rax), %rcx
leaq (%rdx,%rcx,8), %r15
jmp 0xf00c
xorl %r13d, %r13d
xorl %r15d, %r15d
leaq 0x68(%rsp), %rdi
xorpd %xmm0, %xmm0
movq %r13, %rsi
movq %r15, %rdx
callq 0x1a9ec
testq %r13, %r13
je 0xf0ba
movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000
xorl %r12d, %r12d
leaq 0x3f(%rax), %r14
movq %r13, 0x60(%rsp)
testq %r15, %r15
je 0xf0ad
leaq (%r12,%r12,4), %r13
xorl %ebp, %ebp
movq (%rbx), %rax
leaq 0x3f(%rbp), %rcx
testq %rbp, %rbp
cmovnsq %rbp, %rcx
sarq $0x6, %rcx
shlq $0x3, %rcx
addq (%rax,%r13,8), %rcx
movq %rbp, %rax
andq %r14, %rax
xorl %edx, %edx
movabsq $-0x8000000000000000, %rsi # imm = 0x8000000000000000
cmpq %rsi, %rax
setbe %dl
movq -0x8(%rcx,%rdx,8), %rax
btq %rbp, %rax
jae 0xf0a5
leaq 0x68(%rsp), %rdi
movq %r12, %rsi
callq 0x1ae76
movq (%rax), %rax
movabsq $0x3ff0000000000000, %rcx # imm = 0x3FF0000000000000
movq %rcx, (%rax,%rbp,8)
incq %rbp
cmpq %rbp, %r15
jne 0xf04a
incq %r12
movq 0x60(%rsp), %r13
cmpq %r13, %r12
jne 0xf03f
leaq 0x18(%rsp), %rdi
leaq 0x68(%rsp), %rsi
callq 0x1c6d2
leaq 0xb8(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x14f80
movq 0x88(%rsp), %r12
movq 0x80(%rsp), %r13
leaq 0x18(%rsp), %rdi
callq 0x1acb6
leaq 0x68(%rsp), %rdi
callq 0x1acb6
leaq 0x68(%rsp), %rdi
leaq 0x30(%rsp), %rsi
leaq 0xb8(%rsp), %rdx
callq 0x1acc8
leaq 0x68(%rsp), %rdi
callq 0x1ac7c
movq %rax, %r14
movq %rdx, %r15
movq 0x60(%r12), %rdi
callq 0x1ac7c
movq %rdx, %rcx
movq %r14, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x1a680
testb %al, %al
je 0xf5e1
movl 0xc8(%r12), %eax
cmpl $0x1, %eax
je 0xf210
testl %eax, %eax
jne 0xf67f
movq 0x60(%r12), %rsi
movq %rsp, %rdi
leaq 0x68(%rsp), %rdx
callq 0x1b2b2
movsd 0xc0(%r12), %xmm0
mulsd 0xd0(%r12), %xmm0
movapd 0xa0(%rsp), %xmm1
unpcklps 0x17ea8(%rip), %xmm1    # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x17eb0(%rip), %xmm1    # 0x27050
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
leaq 0x18(%rsp), %rdi
movq %rsp, %rsi
callq 0x1b7d0
movq %rsp, %rdi
callq 0x1acb6
movq %rsp, %rdi
leaq 0x18(%rsp), %rsi
leaq 0x48(%rsp), %rdx
callq 0x1aef8
movq 0x60(%r12), %rsi
leaq 0xd0(%rsp), %rdi
movq %rsp, %rdx
callq 0x1b1b0
movq 0x60(%r12), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x14f80
leaq 0xd0(%rsp), %rdi
callq 0x1acb6
jmp 0xf2fb
movq 0x60(%r12), %rsi
leaq 0x18(%rsp), %rdi
callq 0x1aafe
leaq 0x1d8e(%rip), %rsi      # 0x10fb4
leaq 0x18(%rsp), %rdi
callq 0x1bfe6
movq %rsp, %rdi
leaq 0x18(%rsp), %rsi
leaq 0x68(%rsp), %rdx
callq 0x1b2b2
leaq 0x18(%rsp), %rdi
movq %rsp, %rsi
callq 0x14f80
movq %rsp, %rdi
callq 0x1acb6
movsd 0xc0(%r12), %xmm0
mulsd 0xd0(%r12), %xmm0
movapd 0xa0(%rsp), %xmm1
unpcklps 0x17dc5(%rip), %xmm1    # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x17dcd(%rip), %xmm1    # 0x27050
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
movq %rsp, %rdi
leaq 0x18(%rsp), %rsi
callq 0x1b7d0
leaq 0x18(%rsp), %rdi
movq %rsp, %rsi
callq 0x14f80
movq %rsp, %rdi
callq 0x1acb6
movq 0x60(%r12), %rsi
movq %rsp, %rdi
leaq 0x18(%rsp), %rdx
callq 0x1b1b0
movq 0x60(%r12), %rdi
movq %rsp, %rsi
callq 0x14f80
movq %rsp, %rdi
callq 0x1acb6
movq 0x60(%r12), %rsi
movq %rsp, %rdi
leaq 0x48(%rsp), %rdx
callq 0x1b1b0
movq 0x60(%r12), %rdi
movq %rsp, %rsi
callq 0x14f80
movq %rsp, %rdi
callq 0x1acb6
leaq 0x18(%rsp), %rdi
callq 0x1acb6
cmpb $0x1, 0x210(%r12)
jne 0xf330
movl 0xc(%r12), %eax
cmpl $0x4, %eax
ja 0xf330
movl $0x13, %ecx
btl %eax, %ecx
jb 0xf441
movq 0x78(%r12), %rdi
callq 0x1ac7c
leaq 0x18(%rsp), %rdi
movq %rax, %rsi
callq 0x1a8c0
movq 0x90(%rsp), %rax
cmpq %rax, 0x98(%rsp)
je 0xf39e
cmpq $0x1, %r13
adcq $0x0, %r13
xorl %ebx, %ebx
movq %rsp, %r14
leaq 0x18(%rsp), %r15
movq 0xa8(%r12), %rax
movq (%rax,%rbx), %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x1aef8
movq %r15, %rdi
movq %r14, %rsi
callq 0x14f80
movq %r14, %rdi
callq 0x1acb6
addq $0x18, %rbx
decq %r13
jne 0xf36b
movapd 0xa0(%rsp), %xmm1
unpcklps 0x17c92(%rip), %xmm1    # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x17c9a(%rip), %xmm1    # 0x27050
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
addsd %xmm1, %xmm0
movq %rsp, %rdi
leaq 0x18(%rsp), %rsi
callq 0x1b88c
leaq 0x18(%rsp), %rdi
movq %rsp, %rsi
callq 0x14f80
movq %rsp, %rdi
callq 0x1acb6
movsd 0xc0(%r12), %xmm0
movq %rsp, %rdi
leaq 0x18(%rsp), %rsi
callq 0x1b7d0
leaq 0x18(%rsp), %rdi
movq %rsp, %rsi
callq 0x14f80
movq %rsp, %rdi
callq 0x1acb6
movq 0x78(%r12), %rsi
movq %rsp, %rdi
leaq 0x18(%rsp), %rdx
callq 0x1b1b0
movq 0x78(%r12), %rdi
movq %rsp, %rsi
callq 0x14f80
movq %rsp, %rdi
callq 0x1acb6
leaq 0x18(%rsp), %rdi
callq 0x1acb6
leaq 0x68(%rsp), %rdi
callq 0x1acb6
leaq 0xb8(%rsp), %rdi
callq 0x1acb6
leaq 0x30(%rsp), %rdi
callq 0x1acb6
leaq 0x48(%rsp), %rdi
callq 0x1acb6
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x27b53(%rip), %rdi     # 0x36fd8
leaq 0x19678(%rip), %rsi     # 0x28b04
callq 0x4260
leaq 0x19700(%rip), %rsi     # 0x28b98
movq %rax, %rdi
callq 0x4260
jmp 0xf5b3
movq 0x27b2c(%rip), %r14     # 0x36fd8
leaq 0x19651(%rip), %rsi     # 0x28b04
movq %r14, %rdi
callq 0x4260
leaq 0x19659(%rip), %rsi     # 0x28b1b
movq %rax, %rdi
callq 0x4260
movq %rax, %rdi
callq 0x4100
leaq 0x19673(%rip), %rsi     # 0x28b4c
movq %r14, %rdi
callq 0x4260
movq 0x98(%r13), %rsi
subq 0x90(%r13), %rsi
sarq $0x3, %rsi
imulq %r12, %rsi
movq %rax, %rdi
callq 0x4090
movq %rax, %rdi
callq 0x4100
leaq 0x19666(%rip), %rsi     # 0x28b74
movq %r14, %rdi
callq 0x4260
movq 0x1e8(%r13), %rsi
subq 0x1e0(%r13), %rsi
sarq $0x3, %rsi
imulq %r12, %rsi
movq %rax, %rdi
callq 0x4090
jmp 0xf5b3
leaq 0x398(%r13), %r14
movq 0x27a94(%rip), %r15     # 0x36fd8
leaq 0x195b9(%rip), %rsi     # 0x28b04
movq %r15, %rdi
callq 0x4260
leaq 0x1967d(%rip), %rsi     # 0x28bd7
movq %rax, %rdi
callq 0x4260
movq %rax, %rdi
callq 0x4100
leaq 0x196a8(%rip), %rsi     # 0x28c19
movq %r15, %rdi
callq 0x4260
movq 0x68(%r13), %rsi
subq 0x60(%r13), %rsi
sarq $0x3, %rsi
imulq %r12, %rsi
movq %rax, %rdi
callq 0x4090
movq %rax, %rdi
callq 0x4100
leaq 0x1968f(%rip), %rsi     # 0x28c2f
movq %r15, %rdi
callq 0x4260
movq %rax, %rdi
movq %r14, %rsi
callq 0x1a3c1
movq %rax, %rdi
callq 0x4100
xorl %edi, %edi
callq 0x4290
leaq 0x18d9d(%rip), %rdi     # 0x28366
leaq 0x1817a(%rip), %rsi     # 0x2774a
leaq 0x19694(%rip), %rcx     # 0x28c6b
movl $0xd4a, %edx            # imm = 0xD4A
callq 0x4160
leaq 0x19721(%rip), %rdi     # 0x28d09
leaq 0x1815b(%rip), %rsi     # 0x2774a
leaq 0x19675(%rip), %rcx     # 0x28c6b
movl $0xd71, %edx            # imm = 0xD71
callq 0x4160
movq 0x279d1(%rip), %rdi     # 0x36fd8
leaq 0x194f6(%rip), %rsi     # 0x28b04
movl $0x16, %edx
callq 0x4280
movq 0x279b9(%rip), %rdi     # 0x36fd8
leaq 0x1961c(%rip), %rsi     # 0x28c42
movl $0x28, %edx
callq 0x4280
movq 0x279a1(%rip), %rdi     # 0x36fd8
callq 0x4100
jmp 0xf5bb
leaq 0x19651(%rip), %rdi     # 0x28c99
leaq 0x180fb(%rip), %rsi     # 0x2774a
leaq 0x19615(%rip), %rcx     # 0x28c6b
movl $0xd60, %edx            # imm = 0xD60
callq 0x4160
leaq 0x1964f(%rip), %rdi     # 0x28cb6
leaq 0x180dc(%rip), %rsi     # 0x2774a
leaq 0x195f6(%rip), %rcx     # 0x28c6b
movl $0xd61, %edx            # imm = 0xD61
callq 0x4160
movq 0x27952(%rip), %rdi     # 0x36fd8
leaq 0x19477(%rip), %rsi     # 0x28b04
movl $0x16, %edx
callq 0x4280
movq 0x2793a(%rip), %rdi     # 0x36fd8
leaq 0x19695(%rip), %rsi     # 0x28d3a
movl $0x36, %edx
callq 0x4280
movq 0x27922(%rip), %rdi     # 0x36fd8
callq 0x4100
jmp 0xf5bb
jmp 0xf749
jmp 0xf72d
jmp 0xf750
jmp 0xf732
jmp 0xf72d
jmp 0xf732
jmp 0xf72d
jmp 0xf732
jmp 0xf72d
movq %rax, %rbx
leaq 0xd0(%rsp), %rdi
callq 0x1acb6
jmp 0xf735
jmp 0xf732
jmp 0xf732
jmp 0xf72d
jmp 0xf72d
jmp 0xf72d
movq %rax, %rbx
movq %rsp, %rdi
jmp 0xf742
jmp 0xf750
jmp 0xf750
jmp 0xf720
jmp 0xf720
jmp 0xf720
jmp 0xf76c
jmp 0xf749
jmp 0xf76c
jmp 0xf76c
jmp 0xf749
jmp 0xf749
jmp 0xf732
jmp 0xf72d
jmp 0xf732
jmp 0xf72d
jmp 0xf732
jmp 0xf72d
jmp 0xf720
movq %rax, %rbx
jmp 0xf75d
jmp 0xf749
jmp 0xf750
jmp 0xf76c
jmp 0xf750
movq %rax, %rbx
jmp 0xf73d
movq %rax, %rbx
movq %rsp, %rdi
callq 0x1acb6
leaq 0x18(%rsp), %rdi
callq 0x1acb6
jmp 0xf753
movq %rax, %rbx
jmp 0xf779
jmp 0xf76c
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x1acb6
leaq 0xb8(%rsp), %rdi
callq 0x1acb6
jmp 0xf76f
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x1acb6
leaq 0x48(%rsp), %rdi
callq 0x1acb6
movq %rbx, %rdi
callq 0x43e0
nop