// File: iibrahimli[P]adsa_project/src/../include/util.hpp
// Function: x_correlate_region(BMP_image const&, std::pair<int, int>, std::pair<int, int>, BMP_image const&, std::pair<int, int>, std::pair<int, int>, int, int, int, float*)
void x_correlate_region(const BMP_image& a, std::pair<int, int> a_start, std::pair<int, int> a_end,
                        const BMP_image& b, std::pair<int, int> b_start, std::pair<int, int> b_end,
                        int sh_start, int sh_end, int sh_begin, sim_t* act)
{
    // heights are different
    if(abs(a_start.second - a_end.second)+1 != abs(b_start.second - b_end.second)+1){
        throw std::runtime_error("The heights of correlated regions must match (got "
                                + std::to_string(abs(a_start.second-a_end.second)) + " and "
                                + std::to_string(abs(b_start.second-b_end.second)) + ")");
    }

    int height  = a_end.second - a_start.second + 1;
    int width_a = a_end.first - a_start.first + 1;
    int width_b = b_end.first - b_start.first + 1;

    // width of b exceeds width of a
    if(width_a < width_b){
        throw std::runtime_error("Width of b is greater than width of a. Swap the arguments maybe");
    }

    // activations initialized to 0
    for(int i=sh_start; i<sh_end; ++i) act[i - sh_begin] = 0;

    // outer loop with j for cache efficiency

    for(int shift=sh_start; shift<sh_end; ++shift){
        // b entering a
        if(shift <= 0){
            for(int j=a_start.second; j<a_start.second+height; ++j){
                for(int i=0; i<width_b+shift; ++i){
                    act[shift - sh_begin] += a.ploc(i, j) * b.ploc(i-shift, j);
                }
            }
        }
        // b fully inside a
        else if ((width_a - shift) >= width_b){
            for(int j=a_start.second; j<a_start.second+height; ++j){
                for(int i=0; i<width_b; ++i){
                    act[shift - sh_begin] += a.ploc(i+shift, j) * b.ploc(i, j);
                }
            }
        }
        // b leaving a
        else{
            for(int j=a_start.second; j<a_start.second+height; ++j){
                for(int i=0; i<width_a-shift; ++i){
                    act[shift - sh_begin] += a.ploc(i+shift, j) * b.ploc(i, j);
                }
            }
        }
    }
}

// Assembly:
subq $0x158, %rsp            # imm = 0x158
movq 0x178(%rsp), %rax
movl 0x170(%rsp), %eax
movl 0x168(%rsp), %eax
movl 0x160(%rsp), %eax
movq %rsi, 0x150(%rsp)
movq %rdx, 0x148(%rsp)
movq %r8, 0x140(%rsp)
movq %r9, 0x138(%rsp)
movq %rdi, 0x130(%rsp)
movq %rcx, 0x128(%rsp)
movl 0x154(%rsp), %eax
subl 0x14c(%rsp), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
addl $0x1, %eax
movl 0x144(%rsp), %ecx
subl 0x13c(%rsp), %ecx
movl %ecx, %edx
negl %edx
cmovnsl %edx, %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
je 0x3ed1
movb $0x1, 0x57(%rsp)
movl $0x10, %edi
callq 0x3150
movq %rax, 0x20(%rsp)
movl 0x154(%rsp), %esi
movl 0x14c(%rsp), %eax
subl %eax, %esi
movl %esi, %eax
negl %eax
cmovnsl %eax, %esi
leaq 0x88(%rsp), %rdi
callq 0x6e30
jmp 0x3d16
leaq 0xa6ca(%rip), %rsi      # 0xe3e7
leaq 0xa8(%rsp), %rdi
leaq 0x88(%rsp), %rdx
callq 0x70b0
jmp 0x3d34
leaq 0xa6df(%rip), %rdx      # 0xe41a
leaq 0xc8(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x6f70
jmp 0x3d52
movl 0x144(%rsp), %esi
movl 0x13c(%rsp), %eax
subl %eax, %esi
movl %esi, %eax
negl %eax
cmovnsl %eax, %esi
leaq 0x58(%rsp), %rdi
callq 0x6e30
jmp 0x3d75
leaq 0xe8(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
leaq 0x58(%rsp), %rdx
callq 0x6fc0
jmp 0x3d91
leaq 0xa293(%rip), %rdx      # 0xe02b
leaq 0x108(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x6f70
jmp 0x3daf
movq 0x20(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x33e0
jmp 0x3dc3
movq 0x20(%rsp), %rdi
movb $0x0, 0x57(%rsp)
movq 0x1021c(%rip), %rsi     # 0x13ff0
movq 0x101e5(%rip), %rdx     # 0x13fc0
callq 0x3440
jmp 0x4249
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
jmp 0x3eb9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
jmp 0x3eac
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
jmp 0x3e9f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
jmp 0x3e92
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
jmp 0x3e88
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
jmp 0x3e7b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x3190
leaq 0xe8(%rsp), %rdi
callq 0x3190
leaq 0x58(%rsp), %rdi
callq 0x3190
leaq 0xc8(%rsp), %rdi
callq 0x3190
leaq 0xa8(%rsp), %rdi
callq 0x3190
leaq 0x88(%rsp), %rdi
callq 0x3190
testb $0x1, 0x57(%rsp)
jne 0x3ec2
jmp 0x3ecc
movq 0x20(%rsp), %rdi
callq 0x31d0
jmp 0x423c
movl 0x14c(%rsp), %eax
subl 0x154(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x50(%rsp)
movl 0x148(%rsp), %eax
subl 0x150(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
movl 0x138(%rsp), %eax
subl 0x140(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
movl 0x4c(%rsp), %eax
cmpl 0x48(%rsp), %eax
jge 0x3f75
movl $0x10, %edi
callq 0x3150
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x18(%rsp)
leaq 0xa4ea(%rip), %rsi      # 0xe420
callq 0x30f0
jmp 0x3f3d
movq 0x18(%rsp), %rdi
movq 0x100a7(%rip), %rsi     # 0x13ff0
movq 0x10070(%rip), %rdx     # 0x13fc0
callq 0x3440
movq 0x18(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
callq 0x31d0
jmp 0x423c
movl 0x160(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0x44(%rsp), %eax
cmpl 0x168(%rsp), %eax
jge 0x3fb8
movq 0x178(%rsp), %rax
movl 0x44(%rsp), %ecx
subl 0x170(%rsp), %ecx
movslq %ecx, %rcx
xorps %xmm0, %xmm0
movss %xmm0, (%rax,%rcx,4)
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x3f80
movl 0x160(%rsp), %eax
movl %eax, 0x40(%rsp)
movl 0x40(%rsp), %eax
cmpl 0x168(%rsp), %eax
jge 0x4234
cmpl $0x0, 0x40(%rsp)
jg 0x409d
movl 0x154(%rsp), %eax
movl %eax, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
movl 0x154(%rsp), %ecx
addl 0x50(%rsp), %ecx
cmpl %ecx, %eax
jge 0x4098
movl $0x0, 0x38(%rsp)
movl 0x38(%rsp), %eax
movl 0x48(%rsp), %ecx
addl 0x40(%rsp), %ecx
cmpl %ecx, %eax
jge 0x4086
movq 0x130(%rsp), %rdi
movl 0x38(%rsp), %esi
movl 0x3c(%rsp), %edx
callq 0x7170
movq %rax, 0x10(%rsp)
movq 0x128(%rsp), %rdi
movl 0x38(%rsp), %esi
subl 0x40(%rsp), %esi
movl 0x3c(%rsp), %edx
callq 0x7170
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x7100
movq 0x178(%rsp), %rax
movl 0x40(%rsp), %ecx
subl 0x170(%rsp), %ecx
movslq %ecx, %rcx
addss (%rax,%rcx,4), %xmm0
movss %xmm0, (%rax,%rcx,4)
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0x4009
jmp 0x4088
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x3fea
jmp 0x4222
movl 0x4c(%rsp), %eax
subl 0x40(%rsp), %eax
cmpl 0x48(%rsp), %eax
jl 0x4167
movl 0x154(%rsp), %eax
movl %eax, 0x34(%rsp)
movl 0x34(%rsp), %eax
movl 0x154(%rsp), %ecx
addl 0x50(%rsp), %ecx
cmpl %ecx, %eax
jge 0x4162
movl $0x0, 0x30(%rsp)
movl 0x30(%rsp), %eax
cmpl 0x48(%rsp), %eax
jge 0x4150
movq 0x130(%rsp), %rdi
movl 0x30(%rsp), %esi
addl 0x40(%rsp), %esi
movl 0x34(%rsp), %edx
callq 0x7170
movq %rax, 0x8(%rsp)
movq 0x128(%rsp), %rdi
movl 0x30(%rsp), %esi
movl 0x34(%rsp), %edx
callq 0x7170
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x7100
movq 0x178(%rsp), %rax
movl 0x40(%rsp), %ecx
subl 0x170(%rsp), %ecx
movslq %ecx, %rcx
addss (%rax,%rcx,4), %xmm0
movss %xmm0, (%rax,%rcx,4)
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x40d9
jmp 0x4152
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0x40ba
jmp 0x4220
movl 0x154(%rsp), %eax
movl %eax, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
movl 0x154(%rsp), %ecx
addl 0x50(%rsp), %ecx
cmpl %ecx, %eax
jge 0x421e
movl $0x0, 0x28(%rsp)
movl 0x28(%rsp), %eax
movl 0x4c(%rsp), %ecx
subl 0x40(%rsp), %ecx
cmpl %ecx, %eax
jge 0x420c
movq 0x130(%rsp), %rdi
movl 0x28(%rsp), %esi
addl 0x40(%rsp), %esi
movl 0x2c(%rsp), %edx
callq 0x7170
movq %rax, (%rsp)
movq 0x128(%rsp), %rdi
movl 0x28(%rsp), %esi
movl 0x2c(%rsp), %edx
callq 0x7170
movq (%rsp), %rdi
movq %rax, %rsi
callq 0x7100
movq 0x178(%rsp), %rax
movl 0x40(%rsp), %ecx
subl 0x170(%rsp), %ecx
movslq %ecx, %rcx
addss (%rax,%rcx,4), %xmm0
movss %xmm0, (%rax,%rcx,4)
movl 0x28(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x28(%rsp)
jmp 0x4191
jmp 0x420e
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x4172
jmp 0x4220
jmp 0x4222
jmp 0x4224
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x3fc3
addq $0x158, %rsp            # imm = 0x158
retq
movq 0x80(%rsp), %rdi
callq 0x3460
nopl (%rax)