// File: /workspace/github_cpp_makefile_star2_O1/bakeunbin[P]inverse_mix_column_precalculated/invmc.cpp
// Function: main
int main (int argc, char * argv [])
{
	if (not check_aes_ni_support ())
	{
		std::cerr << "Cannot test without AES-NI." << std::endl;
		return 1;
	}

	std::random_device rd;
	std::mt19937 mt (rd ());
	std::uniform_int_distribution <uint32_t> dist (0, 255);
	
	// AES-ECB-128
	uint8_t key [BLOCK_SIZE], obj [AES_128_KEY_OBJ_SIZE];
	uint8_t input [VECTOR_SIZE];
	uint8_t fullni [VECTOR_SIZE], precalc [VECTOR_SIZE], gmul [VECTOR_SIZE];

	for (auto & k : key)
	{
		k = (uint8_t) dist (mt);
	}

	aesni_keygen (key, obj);
	
	for (auto & i : input)
	{
		i = (uint8_t) dist (mt);
	}

	auto fullni_t = decrypt_full_aesni (obj, fullni, input);
	auto precalc_t = decrypt_mixed_precalc (obj, precalc, input);
	auto gmul_t = decrypt_mixed_gmul (obj, gmul, input);

	std::cout << "Block size    : " << BLOCK_SIZE << std::endl;
	std::cout << "Block count   : " << BLOCK_COUNT << std::endl;
	std::cout << "Vector size   : " << VECTOR_SIZE << std::endl;
	std::cout << "AES-NI        : " << (fullni_t / 1000.0) << "μs" << std::endl;
	std::cout << "Soft Precalc  : " << (precalc_t / 1000.0) << "μs" << std::endl;
	std::cout << "Soft GMul     : " << (gmul_t / 1000.0) << "μs" << std::endl;

	if (memcmp (fullni, precalc, VECTOR_SIZE) or memcmp (fullni, gmul, VECTOR_SIZE))
	{
		std::cerr << "Test result invalid: results different from AES-NI." << std::endl;
		return 2;
	}

	return 0;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x827e8, %rsp          # imm = 0x827E8
callq 0x2330
testb %al, %al
je 0x1ef2
leaq 0x1458(%rsp), %rbx
movq %rbx, %rdi
callq 0x1f7a
movq %rbx, %rdi
callq 0x1130
movl %eax, %eax
movq %rax, 0xd0(%rsp)
movl $0x1, %ecx
movq %rax, %rdx
shrq $0x1e, %rdx
xorl %eax, %edx
imull $0x6c078965, %edx, %eax # imm = 0x6C078965
addl %ecx, %eax
movq %rax, 0xd0(%rsp,%rcx,8)
incq %rcx
cmpq $0x270, %rcx            # imm = 0x270
jne 0x1b0c
leaq 0xd0(%rsp), %rbx
movq $0x270, 0x1380(%rbx) # imm = 0x270
movabsq $0xff00000000, %rax     # imm = 0xFF00000000
leaq 0x8(%rsp), %r14
movq %rax, (%r14)
xorl %r15d, %r15d
movq %r14, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x20d8
movb %al, 0x10(%rsp,%r15)
incq %r15
cmpq $0x10, %r15
jne 0x1b59
leaq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x234a
xorl %r15d, %r15d
leaq 0xd0(%rsp), %rbx
leaq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x20d8
movb %al, 0x227e0(%rsp,%r15)
incq %r15
cmpq $0x20000, %r15          # imm = 0x20000
jne 0x1b94
leaq 0x20(%rsp), %rdi
leaq 0x27e0(%rsp), %rsi
leaq 0x227e0(%rsp), %rdx
callq 0x19bf
movq %rax, %r15
leaq 0x20(%rsp), %rbx
leaq 0x627e0(%rsp), %rsi
leaq 0x227e0(%rsp), %r12
movq %rbx, %rdi
movq %r12, %rdx
callq 0x1a18
movq %rax, %r14
leaq 0x427e0(%rsp), %rsi
movq %rbx, %rdi
movq %r12, %rdx
callq 0x1a71
movq %rax, %rbx
movq 0x33bd(%rip), %rdi      # 0x4fd0
leaq 0x1562(%rip), %rsi      # 0x317c
movl $0x10, %edx
callq 0x1120
movq 0x33a5(%rip), %rdi      # 0x4fd0
movl $0x10, %esi
callq 0x1170
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x10e0
movsbl %al, %esi
movq %r12, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1090
movq 0x336a(%rip), %rdi      # 0x4fd0
leaq 0x1520(%rip), %rsi      # 0x318d
movl $0x10, %edx
callq 0x1120
movq 0x3352(%rip), %rdi      # 0x4fd0
movl $0x2000, %esi           # imm = 0x2000
callq 0x1170
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x10e0
movsbl %al, %esi
movq %r12, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1090
movq 0x3317(%rip), %rdi      # 0x4fd0
leaq 0x14de(%rip), %rsi      # 0x319e
movl $0x10, %edx
callq 0x1120
movq 0x32ff(%rip), %rdi      # 0x4fd0
movl $0x20000, %esi          # imm = 0x20000
callq 0x1170
movq %rax, %r12
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x10e0
movsbl %al, %esi
movq %r12, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1090
movq 0x32c4(%rip), %rdi      # 0x4fd0
leaq 0x149c(%rip), %rsi      # 0x31af
movl $0x10, %edx
callq 0x1120
cvtsi2sd %r15, %xmm0
divsd 0x1326(%rip), %xmm0     # 0x3050
movq 0x329f(%rip), %rdi      # 0x4fd0
callq 0x1150
movq %rax, %r15
leaq 0x1480(%rip), %rsi      # 0x31c0
movl $0x3, %edx
movq %rax, %rdi
callq 0x1120
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x10e0
movsbl %al, %esi
movq %r15, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1090
movq 0x3255(%rip), %rdi      # 0x4fd0
leaq 0x1442(%rip), %rsi      # 0x31c4
movl $0x10, %edx
callq 0x1120
xorps %xmm0, %xmm0
cvtsi2sd %r14, %xmm0
divsd 0x12b4(%rip), %xmm0     # 0x3050
movq 0x322d(%rip), %rdi      # 0x4fd0
callq 0x1150
movq %rax, %r14
leaq 0x140e(%rip), %rsi      # 0x31c0
movl $0x3, %edx
movq %rax, %rdi
callq 0x1120
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x10e0
movsbl %al, %esi
movq %r14, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1090
movq 0x31e3(%rip), %rdi      # 0x4fd0
leaq 0x13e1(%rip), %rsi      # 0x31d5
movl $0x10, %edx
callq 0x1120
xorps %xmm0, %xmm0
cvtsi2sd %rbx, %xmm0
divsd 0x1242(%rip), %xmm0     # 0x3050
movq 0x31bb(%rip), %rdi      # 0x4fd0
callq 0x1150
movq %rax, %rbx
leaq 0x139c(%rip), %rsi      # 0x31c0
movl $0x3, %edx
movq %rax, %rdi
callq 0x1120
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x10e0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1090
leaq 0x27e0(%rsp), %rdi
leaq 0x627e0(%rsp), %rsi
movl $0x20000, %edx          # imm = 0x20000
callq 0x1110
testl %eax, %eax
jne 0x1e98
leaq 0x27e0(%rsp), %rdi
leaq 0x427e0(%rsp), %rsi
movl $0x20000, %edx          # imm = 0x20000
callq 0x1110
testl %eax, %eax
je 0x1f4a
movq 0x3151(%rip), %rbx      # 0x4ff0
leaq 0x1340(%rip), %rsi      # 0x31e6
movl $0x33, %edx
movq %rbx, %rdi
callq 0x1120
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x10e0
movsbl %al, %esi
movq 0x311f(%rip), %rdi      # 0x4ff0
callq 0x1030
movl $0x2, %ebx
movq %rax, %rdi
callq 0x1090
leaq 0x1458(%rsp), %rdi
callq 0x10d0
jmp 0x1f39
movq 0x30f7(%rip), %rbx      # 0x4ff0
leaq 0x1260(%rip), %rsi      # 0x3160
movl $0x1b, %edx
movq %rbx, %rdi
callq 0x1120
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x10e0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1090
movl $0x1, %ebx
movl %ebx, %eax
addq $0x827e8, %rsp          # imm = 0x827E8
popq %rbx
popq %r12
popq %r14
popq %r15
retq
xorl %ebx, %ebx
jmp 0x1ee3
jmp 0x1f72
jmp 0x1f5a
jmp 0x1f5a
jmp 0x1f5a
jmp 0x1f5a
jmp 0x1f5a
movq %rax, %rbx
leaq 0x1458(%rsp), %rdi
callq 0x10d0
movq %rbx, %rdi
callq 0x1180
movq %rax, %rdi
callq 0x20cd