// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movl %edx, %r10d
movq %rdi, %rbx
movb 0x20(%rbp), %r15b
movq 0x10(%rbp), %r11
movb 0x18(%rbp), %dl
movl %esi, (%rdi)
movl %r10d, 0x4(%rdi)
movl %ecx, 0x8(%rdi)
movl 0x4(%r11), %eax
movl %eax, 0xc(%rdi)
movl %r8d, 0x10(%rdi)
movl %r9d, 0x14(%rdi)
movb %dl, 0x64(%rdi)
movb %r15b, 0x65(%rdi)
cltd
idivl %r9d
xorps %xmm0, %xmm0
movups %xmm0, 0x68(%rdi)
movq $0x0, 0x78(%rdi)
testl %edx, %edx
jne 0x37fc
movl %eax, %edi
movl %r8d, %eax
cltd
idivl %r9d
testl %edx, %edx
jne 0x380c
movl %edi, 0x18(%rbx)
movl %eax, 0x1c(%rbx)
movups (%r11), %xmm0
movups %xmm0, 0x20(%rbx)
movl 0xc(%r11), %eax
movl %eax, 0x48(%rbx)
imull 0x8(%r11), %eax
movl %eax, 0x44(%rbx)
imull 0x4(%r11), %eax
movl %eax, 0x40(%rbx)
movl %esi, 0x54(%rbx)
movl %esi, %eax
imull %esi, %eax
movl %eax, 0x50(%rbx)
imull %edi, %eax
movl %eax, 0x4c(%rbx)
movl (%r11), %eax
movl %eax, 0x30(%rbx)
movl %r8d, 0x34(%rbx)
addl %ecx, %ecx
subl %esi, %ecx
movl 0x8(%r11), %eax
addl %ecx, %eax
cltd
idivl %r10d
movl %eax, %r9d
incl %r9d
movl %r9d, 0x38(%rbx)
addl 0xc(%r11), %ecx
movl %ecx, %eax
cltd
idivl %r10d
incl %eax
movl %eax, 0x3c(%rbx)
movl %eax, 0x60(%rbx)
imull %r9d, %eax
movl %eax, 0x5c(%rbx)
imull %r8d, %eax
movl %eax, 0x58(%rbx)
movslq %r8d, %r14
shlq $0x2, %r14
movslq %edi, %rax
movslq %esi, %rdi
imulq %rdi, %rdi
imulq %r14, %rdi
imulq %rax, %rdi
callq 0x2240
movq %rax, 0x68(%rbx)
testb %r15b, %r15b
je 0x37f1
movq %r14, %rdi
callq 0x2240
movq %rax, 0x70(%rbx)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq 0x57ed(%rip), %rdi      # 0x8ff0
leaq 0x2af2(%rip), %rsi      # 0x62fc
jmp 0x381a
movq 0x57dd(%rip), %rdi      # 0x8ff0
leaq 0x2afc(%rip), %rsi      # 0x6316
callq 0x2180
movq %rax, %rdi
callq 0x20d0
movl $0x1, %edi
callq 0x2210
nop