// File: hey-yahei[P]ConvNet/src/Convolution.cpp
// Function: Convolution::Convolution(int, int, int, int, int, int*, bool, bool)
Convolution::Convolution(int kernel, int stride, int pad, int out_channels, int groups, int ishape[], bool with_relu, bool with_bias)
		: kernel(kernel), stride(stride), pad(pad), in_channels(ishape[1]), 
	      out_channels(out_channels), groups(groups), with_relu(with_relu), with_bias(with_bias){
	if (in_channels % groups != 0) {
		cerr << "in_channels % groups != 0" << endl;
		exit(1);
	}
	if (out_channels % groups != 0) {
		cerr << "out_channels % groups != 0" << endl;
		exit(1);
	}

	ic_per_gp = in_channels / groups;
	oc_per_gp = out_channels / groups;

	memcpy(in_shape, ishape, sizeof(int) * 4);
	in_w = ishape[3];
	in_hw = ishape[2] * in_w;
	in_chw = ishape[1] * in_hw;

	wt_w = kernel;
	wt_hw = kernel * wt_w;
	wt_chw = ic_per_gp * wt_hw;

	out_shape[0] = ishape[0];		// batch size
	out_shape[1] = out_channels;	// out_channels
	out_shape[2] = (ishape[2] + 2 * pad - kernel) / stride + 1;   // out_height
	out_shape[3] = (ishape[3] + 2 * pad - kernel) / stride + 1;   // out_width
	out_w = out_shape[3];
	out_hw = out_shape[2] * out_w;
	out_chw = out_shape[1] * out_hw;

	weight_data = (float*)malloc(sizeof(float) * out_channels * ic_per_gp * kernel * kernel);
	if (with_bias)
		bias_data = (float*)malloc(sizeof(float) * out_channels);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movl %ecx, -0x34(%rbp)
movl %edx, %eax
movl -0x34(%rbp), %edx
movl %eax, -0x30(%rbp)
movl %esi, %eax
movl -0x30(%rbp), %esi
movl %eax, -0x2c(%rbp)
movq %rdi, %r10
movl -0x2c(%rbp), %edi
movb 0x20(%rbp), %al
movb 0x18(%rbp), %cl
movq 0x10(%rbp), %r11
movq %r10, -0x8(%rbp)
movl %edi, -0xc(%rbp)
movl %esi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movl %r8d, -0x18(%rbp)
movl %r9d, -0x1c(%rbp)
andb $0x1, %cl
movb %cl, -0x1d(%rbp)
andb $0x1, %al
movb %al, -0x1e(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movl -0xc(%rbp), %ecx
movl %ecx, (%rax)
movl -0x10(%rbp), %ecx
movl %ecx, 0x4(%rax)
movl -0x14(%rbp), %ecx
movl %ecx, 0x8(%rax)
movq 0x10(%rbp), %rcx
movl 0x4(%rcx), %ecx
movl %ecx, 0xc(%rax)
movl -0x18(%rbp), %ecx
movl %ecx, 0x10(%rax)
movl -0x1c(%rbp), %ecx
movl %ecx, 0x14(%rax)
movb -0x1d(%rbp), %cl
andb $0x1, %cl
movb %cl, 0x64(%rax)
movb -0x1e(%rbp), %cl
andb $0x1, %cl
movb %cl, 0x65(%rax)
movq $0x0, 0x68(%rax)
movq $0x0, 0x70(%rax)
movq $0x0, 0x78(%rax)
movl 0xc(%rax), %eax
cltd
idivl -0x1c(%rbp)
cmpl $0x0, %edx
je 0x661c
movq 0xb9f9(%rip), %rdi      # 0x11ff0
leaq 0x5cfe(%rip), %rsi      # 0xc2fc
callq 0x21c0
movq %rax, %rdi
movq 0xb9b3(%rip), %rsi      # 0x11fc0
callq 0x2200
movl $0x1, %edi
callq 0x2290
movl -0x18(%rbp), %eax
cltd
idivl -0x1c(%rbp)
cmpl $0x0, %edx
je 0x6654
movq 0xb9c1(%rip), %rdi      # 0x11ff0
leaq 0x5ce0(%rip), %rsi      # 0xc316
callq 0x21c0
movq %rax, %rdi
movq 0xb97b(%rip), %rsi      # 0x11fc0
callq 0x2200
movl $0x1, %edi
callq 0x2290
movq -0x28(%rbp), %rax
movl 0xc(%rax), %eax
cltd
idivl -0x1c(%rbp)
movl %eax, %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x18(%rax)
movl -0x18(%rbp), %eax
cltd
idivl -0x1c(%rbp)
movl %eax, %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x1c(%rax)
movq 0x10(%rbp), %rcx
movq (%rcx), %rdx
movq %rdx, 0x20(%rax)
movq 0x8(%rcx), %rcx
movq %rcx, 0x28(%rax)
movq 0x10(%rbp), %rcx
movl 0xc(%rcx), %ecx
movl %ecx, 0x48(%rax)
movq 0x10(%rbp), %rcx
movl 0x8(%rcx), %ecx
imull 0x48(%rax), %ecx
movl %ecx, 0x44(%rax)
movq 0x10(%rbp), %rcx
movl 0x4(%rcx), %ecx
imull 0x44(%rax), %ecx
movl %ecx, 0x40(%rax)
movl -0xc(%rbp), %ecx
movl %ecx, 0x54(%rax)
movl -0xc(%rbp), %ecx
imull 0x54(%rax), %ecx
movl %ecx, 0x50(%rax)
movl 0x18(%rax), %ecx
imull 0x50(%rax), %ecx
movl %ecx, 0x4c(%rax)
movq 0x10(%rbp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x30(%rax)
movl -0x18(%rbp), %ecx
movl %ecx, 0x34(%rax)
movq 0x10(%rbp), %rax
movl 0x8(%rax), %eax
movl -0x14(%rbp), %ecx
shll %ecx
addl %ecx, %eax
subl -0xc(%rbp), %eax
cltd
idivl -0x10(%rbp)
movl %eax, %ecx
movq -0x28(%rbp), %rax
addl $0x1, %ecx
movl %ecx, 0x38(%rax)
movq 0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl -0x14(%rbp), %ecx
shll %ecx
addl %ecx, %eax
subl -0xc(%rbp), %eax
cltd
idivl -0x10(%rbp)
movl %eax, %ecx
movq -0x28(%rbp), %rax
addl $0x1, %ecx
movl %ecx, 0x3c(%rax)
movl 0x3c(%rax), %ecx
movl %ecx, 0x60(%rax)
movl 0x38(%rax), %ecx
imull 0x60(%rax), %ecx
movl %ecx, 0x5c(%rax)
movl 0x34(%rax), %ecx
imull 0x5c(%rax), %ecx
movl %ecx, 0x58(%rax)
movslq -0x18(%rbp), %rdi
shlq $0x2, %rdi
movslq 0x18(%rax), %rax
imulq %rax, %rdi
movslq -0xc(%rbp), %rax
imulq %rax, %rdi
movslq -0xc(%rbp), %rax
imulq %rax, %rdi
callq 0x22e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x68(%rax)
testb $0x1, -0x1e(%rbp)
je 0x6784
movslq -0x18(%rbp), %rdi
shlq $0x2, %rdi
callq 0x22e0
movq %rax, %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x70(%rax)
addq $0x40, %rsp
popq %rbp
retq
nopw (%rax,%rax)