// File: /workspace/github_cpp_makefile_star2_O2/cgvwzq[P]aes_bf/src/aes-brute-force.cpp
// Function: main
int main (int argc, char*argv[]) 
{
	uint8_t payload[16] = {0};
	uint8_t key[16] = {0};
	uint8_t iv[16] = {0};
	uint8_t plain_mask[16] = {0};
	uint8_t plain[16] = {0};
	uint8_t next_block[16] = {0};
	uint8_t cipher_mask[16] = {0};
	uint8_t cipher[16] = {0};

	const char *payload_str = "4D346731_435F6330_306B3133_5F465457"; // payload

	const char *key_str = "FD621FE5_A2B40253_9DFA147C_A9272778"; //  fixed on Linux 

	#ifndef PADDING
		const char *iv_str = "20202020_20202020_20202020_20202020"; // fixed on Chrome
		const char *plain_mask_str = "A0A0A0A0_A0A0A0A0_A0A0A0A0_A0A0A0A0A0"; // bit mask for valid chars
		const char *plain_str = "20202020_20202020_20202020_20202020"; // valid ascii chars
	#else
		const char *iv_str = "7B007D00_2A007B00_2D002D00_3A002800";
		const char *plain_mask_str = "A0A0A0A0_A0A0A0A0_A0A0A0A0_A0A0A0A0FF"; // bit mask for valid chars + padding
		const char *plain_str = "20202020_20202020_20202020_20202001"; // valid ascii chars + padding
	#endif

	const char *cipher_mask_str = "FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF"; // try all chars
	const char *cipher_str = "00000000_00000000_00000000_00000000"; 
	const char *next_block_str = "00000000_00000000_00000000_00000000"; 

	char buf[8][1024] = {0};

	memcpy (buf[0], payload_str, MIN(strlen (payload_str), 1024));
	memcpy (buf[1], key_str, MIN(strlen (key_str), 1024));
	memcpy (buf[2], iv_str, MIN(strlen (iv_str), 1024));
	memcpy (buf[3], plain_mask_str, MIN(strlen (plain_mask_str), 1024));
	memcpy (buf[4], plain_str, MIN(strlen (plain_str), 1024));
	memcpy (buf[5], next_block_str, MIN(strlen (next_block_str), 1024));
	memcpy (buf[6], cipher_mask_str, MIN(strlen (cipher_mask_str), 1024));
	memcpy (buf[7], cipher_str, MIN(strlen (cipher_str), 1024));

	if (0 != aes128_self_test())
	{
		std::cerr << "ERROR: AES-NI self test failed" << std::endl;
		exit(-1);
    }

    unsigned int len;
    len = user_hexstr_to_bytes (payload, 16, buf[0], strlen (buf[0]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (key, 16, buf[1], strlen (buf[1]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (iv, 16, buf[2], strlen (buf[2]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (plain_mask, 16, buf[3], strlen (buf[3]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (plain, 16, buf[4], strlen (buf[4]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (next_block, 16, buf[5], strlen (buf[5]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (cipher_mask, 16, buf[6], strlen (buf[6]) + 1);
	assert (16 == len);
    len = user_hexstr_to_bytes (cipher, 16, buf[7], strlen (buf[7]) + 1);
	assert (16 == len);

	__m128i key_schedule[20] = {0};
	aes128_load_key (key, key_schedule);
	#ifndef PADDING
		aes128_dec (key_schedule, payload, next_block); 
	#endif

	unsigned int n_threads = std::thread::hardware_concurrency ();
	//if (0 == n_threads)
	if (true) // debug
	{
		n_threads = 1;
	}

	std::cout << "[+] INFO: " << n_threads << " concurrent threads supported in hardware." << std::endl << std::endl;
	std::cout << "[+] Search parameters:\t" << std::endl << std::endl;
	std::cout << "\t- n_threads:\t" << n_threads << std::endl;
	println_128 ("\t- payload:\t", payload);
	println_128 ("\t- key:\t\t", key);
	println_128 ("\t- iv:\t\t", iv);
    println_128 ("\t- plain_mask:\t", plain_mask);
    println_128 ("\t- plain:\t", plain);
	#ifndef PADDING
		// start from valid ciphertext
		aes_brute_force::initial_ciphertext (cipher, next_block);
	#endif
    println_128 ("\t- cipher:\t", cipher);
    println_128 ("\t- next_block:\t", next_block);
	std::cout << std::endl;

	std::cout << "[+] Dividing work in jobs..." << std::endl << std::endl;
	voffset_t v;
	aes_brute_force::mask_to_offsets (cipher_mask, next_block, &v);
	uint8_t jobs_cipher_mask[16];
	memcpy (jobs_cipher_mask, cipher_mask, 16);

	if (1 == v.n_offsets)
	{
		n_threads = 1;
		std::cout << "[+] INFO: n_threads set to 1 because n_offsets=1" << std::endl;
	}
	if (1 != n_threads)
	{
		jobs_cipher_mask[v.offsets[0]] = 0; //fix this key byte at the job level.
	}
	std::vector<std::thread *> threads (n_threads);
	std::vector<aes_brute_force *> jobs (n_threads);
	aes_brute_force::reset ();

	int n_ciphers_per_thread = (n_threads == 1) ? 0 : ((v.n_valid_chars + n_threads - 1) / n_threads);
	unsigned int nbits = 0;
	for (unsigned int i=v.n_valid_chars; i; i = i >> 1, nbits++);

	unsigned int jobs_cnt = 0;
	for (unsigned int thread_i=0; thread_i < n_threads; thread_i++)
	{
		cipher[v.offsets[0]] = v.valid_chars[0][jobs_cnt++];
		jobs.at(thread_i) = new aes_brute_force (jobs_cipher_mask, cipher, key, iv, plain_mask, plain, next_block);
		printf ("\tthread_%d: %d jobs ", thread_i, n_ciphers_per_thread);
		print_128 ("(mask : ", jobs_cipher_mask, ")\n");
		for (int i=0; i < n_ciphers_per_thread-1; i++)
		{
			cipher[v.offsets[0]] = v.valid_chars[0][jobs_cnt++];
			jobs.at(thread_i)->push(cipher);
		}
	}
	// TODO: calculate entropy from given masks
	std::cout  << std::endl << "\tlaunching " << (v.n_offsets * nbits) << " bits search" << std::endl;
	std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
	for (unsigned int thread_i=0; thread_i < n_threads; thread_i++)
	{
		threads.at(thread_i) = new std::thread(&aes_brute_force::compute, jobs.at(thread_i));
	}

	bool found = false;
	uint64_t loop_cnt = 0;
	int winner = -1;
	for (unsigned int thread_i=0; thread_i < n_threads; thread_i++)
	{
		threads.at(thread_i)->join();
		if (jobs.at(thread_i)->found)
		{
			found = true;
			winner = thread_i;
			memcpy (cipher, jobs.at(thread_i)->valid_cipher, 16);

		}
		loop_cnt += jobs.at(thread_i)->loop_cnt;
	}
	std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
	std::cout << std::endl;
	if (found)
	{
		std::cout << "[+] Thread " << winner << " claims to have found a valid ciphertext" << std::endl;
        println_128 ("[+] CIPHER FOUND: ", cipher);
    }
	else
	{
        std::cout << "[!] No valid cipher could be found." << std::endl;
    }
	std::cout << std::endl << "[+] Performances:" << std::endl;
    std::cout << "\t" << std::dec << loop_cnt << " AES128 operations done in ";
    std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
    std::cout << time_span.count() << "s" << std::endl;

	if (!loop_cnt)
	{
		return 1;
	}

    uint64_t ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t2-t1).count();
    unsigned int aes_op_duration_ns = ns / loop_cnt;

    std::cout << "\t" << aes_op_duration_ns << " ns per AES128 operation" <<std::endl;
    uint64_t ciphers_per_sec = loop_cnt / time_span.count();
	if (ciphers_per_sec > 1000000)
	{
		std::cout << "\t" << std::fixed << std::setprecision(2) << ciphers_per_sec/1000000.0 << " million ciphers per second" << std::endl;
	}
	else
	{
		std::cout << "\t" << ciphers_per_sec << " cipers per second" << std::endl;
	}
	if (found)
	{
		uint8_t dec[16] = {0};
		char txt[17] = {0}; 
		__m128i key_schedule[20] = {0};
		aes128_load_key (key, key_schedule);
		aes128_dec (key_schedule, cipher, dec); 
		for (unsigned int i=0; i < 16; i++) {
			dec[i] ^= iv[i]; // IV
		}
		memcpy (txt, dec, 16);
		println_128 ("[+] Ciphertext: ", cipher);
		println_128 ("[+] Plaintext: ", dec);
		printf("\tascii: %s (length=%zu)\n", txt, strlen(txt));
		#ifndef PADDING
			char txt2[17] = {0};
			println_128 ("[+] Next block: ", next_block);
			for (unsigned int i=0; i < 16; i++) {
				next_block[i] ^= cipher[i]; 
			}
			memcpy (txt2, next_block, 16);
			println_128 ("[+] Next block XOR cipher: ", next_block);
			printf("\tascii: %s (length=%zu)\n", txt2, strlen(txt2));
		#endif
	}

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x3288, %rsp           # imm = 0x3288
vxorps %xmm0, %xmm0, %xmm0
leaq 0x12a3(%rsp), %rbx
vmovaps %xmm0, 0xd0(%rsp)
vmovaps %xmm0, 0x50(%rsp)
vmovaps %xmm0, 0x40(%rsp)
vmovaps %xmm0, 0xa0(%rsp)
vmovaps %xmm0, 0x90(%rsp)
vmovaps %xmm0, 0x80(%rsp)
vmovaps %xmm0, 0xc0(%rsp)
vmovaps %xmm0, 0x10(%rsp)
movl $0x1fdd, %edx           # imm = 0x1FDD
movq %rbx, %rdi
xorl %esi, %esi
callq 0x20a0
vmovups 0x1af2(%rip), %ymm0     # 0x4085
vmovups 0x1b0e(%rip), %ymm2     # 0x40a9
vmovups 0x1b2a(%rip), %ymm1     # 0x40cd
movabsq $0x4646304130413041, %rax # imm = 0x4646304130413041
vmovups %ymm0, -0x23(%rbx)
movl $0x37353435, -0x4(%rbx) # imm = 0x37353435
vmovups %ymm2, 0x3dd(%rbx)
movl $0x38373732, 0x3fc(%rbx) # imm = 0x38373732
vmovups %ymm1, 0x7dd(%rbx)
vmovups 0x1b16(%rip), %ymm2     # 0x40f1
vmovups 0x1b34(%rip), %ymm1     # 0x4117
movl $0x30303832, 0x7fc(%rbx) # imm = 0x30303832
movq %rax, 0xbfa(%rbx)
movl $0x30303030, %eax       # imm = 0x30303030
vmovups %ymm2, 0xbdd(%rbx)
vmovups %ymm1, 0xfdd(%rbx)
vmovups 0x1b4e(%rip), %ymm2     # 0x415f
vmovups 0x1b22(%rip), %ymm1     # 0x413b
movl $0x31303032, 0xffc(%rbx) # imm = 0x31303032
movl %eax, 0x13fc(%rbx)
vmovups %ymm2, 0x13dd(%rbx)
vmovups %ymm1, 0x17dd(%rbx)
movl $0x46464646, 0x17fc(%rbx) # imm = 0x46464646
movl %eax, 0x1bfc(%rbx)
vmovups %ymm2, 0x1bdd(%rbx)
leaq 0x250(%rsp), %rbx
leaq 0x19e0(%rip), %rdi      # 0x4040
movq %rbx, %rsi
vzeroupper
callq 0x3087
vmovdqa (%rbx), %xmm0
vpxor 0x1999(%rip), %xmm0, %xmm0 # 0x4010
vaesenc 0x10(%rbx), %xmm0, %xmm0
vaesenc 0x20(%rbx), %xmm0, %xmm0
vaesenc 0x30(%rbx), %xmm0, %xmm0
vaesenc 0x40(%rbx), %xmm0, %xmm0
vaesenc 0x50(%rbx), %xmm0, %xmm0
vaesenc 0x60(%rbx), %xmm0, %xmm0
vaesenc 0x70(%rbx), %xmm0, %xmm0
vaesenc 0x80(%rbx), %xmm0, %xmm0
vaesenc 0x90(%rbx), %xmm0, %xmm0
vaesenclast 0xa0(%rbx), %xmm0, %xmm0
vmovdqa %xmm0, 0x110(%rsp)
leaq 0x60(%rsp), %r14
leaq 0x194f(%rip), %rsi      # 0x4020
movq %rbx, %rdi
movq %r14, %rdx
callq 0x334d
vmovdqa 0x110(%rsp), %xmm0
vmovdqa (%r14), %xmm1
vpxor 0x191e(%rip), %xmm1, %xmm1 # 0x4010
vpternlogq $0xf6, 0x1923(%rip), %xmm0, %xmm1 # 0x4020
vptest %xmm1, %xmm1
jne 0x2f23
leaq 0x1280(%rsp), %rbx
movq %rbx, %rdi
callq 0x2060
leaq 0x1(%rax), %rcx
leaq 0xd0(%rsp), %rdi
pushq $0x10
popq %rsi
movq %rbx, %rdx
callq 0x24ea
cmpl $0x10, %eax
jne 0x2f46
leaq 0x1680(%rsp), %rbx
movq %rbx, %rdi
callq 0x2060
leaq 0x1(%rax), %rcx
leaq 0x50(%rsp), %rdi
pushq $0x10
popq %rsi
movq %rbx, %rdx
callq 0x24ea
cmpl $0x10, %eax
jne 0x2f65
leaq 0x1a80(%rsp), %rbx
movq %rbx, %rdi
callq 0x2060
leaq 0x1(%rax), %rcx
leaq 0x40(%rsp), %rdi
pushq $0x10
popq %rsi
movq %rbx, %rdx
callq 0x24ea
cmpl $0x10, %eax
jne 0x2f84
leaq 0x1e80(%rsp), %rbx
movq %rbx, %rdi
callq 0x2060
leaq 0x1(%rax), %rcx
leaq 0xa0(%rsp), %rdi
pushq $0x10
popq %rsi
movq %rbx, %rdx
callq 0x24ea
cmpl $0x10, %eax
jne 0x2fa3
leaq 0x2280(%rsp), %rbx
movq %rbx, %rdi
callq 0x2060
leaq 0x1(%rax), %rcx
leaq 0x90(%rsp), %rdi
pushq $0x10
popq %rsi
movq %rbx, %rdx
callq 0x24ea
cmpl $0x10, %eax
jne 0x2fc2
leaq 0x2680(%rsp), %rbx
movq %rbx, %rdi
callq 0x2060
leaq 0x1(%rax), %rcx
leaq 0x80(%rsp), %rdi
pushq $0x10
popq %rsi
movq %rbx, %rdx
callq 0x24ea
cmpl $0x10, %eax
jne 0x2fe1
leaq 0x2a80(%rsp), %rbx
movq %rbx, %rdi
callq 0x2060
leaq 0x1(%rax), %rcx
leaq 0xc0(%rsp), %rdi
pushq $0x10
popq %rsi
movq %rbx, %rdx
callq 0x24ea
cmpl $0x10, %eax
jne 0x3000
leaq 0x2e80(%rsp), %rbx
movq %rbx, %rdi
callq 0x2060
leaq 0x1(%rax), %rcx
leaq 0x10(%rsp), %rdi
pushq $0x10
popq %rsi
movq %rbx, %rdx
callq 0x24ea
cmpl $0x10, %eax
jne 0x301f
callq 0x2160
movq 0x4745(%rip), %rbx      # 0x6fd0
leaq 0x1949(%rip), %rsi      # 0x41db
movq %rbx, %rdi
callq 0x2120
pushq $0x1
popq %r14
movq %rax, %rdi
movq %r14, %rsi
callq 0x20c0
leaq 0x1936(%rip), %rsi      # 0x41e6
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
movq %rax, %rdi
callq 0x2080
leaq 0x1942(%rip), %rsi      # 0x4211
movq %rbx, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
movq %rax, %rdi
callq 0x2080
leaq 0x193b(%rip), %rsi      # 0x4229
movq %rbx, %rdi
callq 0x2120
movq %rax, %rdi
movq %r14, %rsi
callq 0x20c0
movq %rax, %rdi
callq 0x2080
leaq 0x1928(%rip), %rdi      # 0x4238
leaq 0xd0(%rsp), %rsi
callq 0x32e8
leaq 0x1921(%rip), %rdi      # 0x4245
leaq 0x50(%rsp), %rsi
callq 0x32e8
leaq 0x191a(%rip), %rdi      # 0x424f
leaq 0x40(%rsp), %rsi
callq 0x32e8
leaq 0x1912(%rip), %rdi      # 0x4258
leaq 0xa0(%rsp), %rsi
callq 0x32e8
leaq 0x190e(%rip), %rdi      # 0x4268
leaq 0x90(%rsp), %rsi
callq 0x32e8
leaq 0x1905(%rip), %rdi      # 0x4273
leaq 0x10(%rsp), %rsi
callq 0x32e8
leaq 0x80(%rsp), %r15
leaq 0x18f8(%rip), %rdi      # 0x427f
movq %r15, %rsi
callq 0x32e8
movq %rbx, %rdi
callq 0x2080
leaq 0x18f1(%rip), %rsi      # 0x428f
movq %rbx, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
movq %rax, %rdi
callq 0x2080
leaq 0xc0(%rsp), %rbx
leaq 0x250(%rsp), %r14
movq %r15, %rsi
movq %rbx, %rdi
movq %r14, %rdx
callq 0x3430
vmovapd (%rbx), %xmm0
cmpb $0x1, 0x10(%r14)
vmovapd %xmm0, 0xe0(%rsp)
jne 0x2a03
movq 0x45e1(%rip), %rdi      # 0x6fd0
leaq 0x18b6(%rip), %rsi      # 0x42ac
callq 0x2120
movq %rax, %rdi
callq 0x2080
leaq 0x60(%rsp), %rdi
pushq $0x1
popq %rbx
leaq 0x110(%rsp), %rdx
movq %rbx, %rsi
callq 0x34c6
leaq 0x28(%rsp), %rdi
leaq 0x110(%rsp), %rdx
movq %rbx, %rsi
callq 0x351a
pushq $-0x1
popq %rax
movq %rax, 0x8(%rsp)
movzbl 0x1261(%rsp), %eax
xorl %r12d, %r12d
movb $0x0, 0x46d0(%rip)      # 0x711a
testl %eax, %eax
je 0x2a55
shrl %eax
incl %r12d
jmp 0x2a4a
pushq $0x11
popq %rbx
leaq 0xe0(%rsp), %r13
leaq 0x188b(%rip), %r14      # 0x42f2
leaq 0x19bf(%rip), %r15      # 0x442d
cmpq $0x12, %rbx
je 0x2b05
movb 0x250(%rsp,%rbx), %al
movzbl 0x250(%rsp), %ecx
movb %al, 0x10(%rsp,%rcx)
movl $0x10c8, %edi           # imm = 0x10C8
callq 0x2130
movq %rax, %rbp
movq %rax, %rdi
leaq 0x10(%rsp), %rdx
leaq 0x80(%rsp), %rax
movq %r13, %rsi
leaq 0x50(%rsp), %rcx
leaq 0x40(%rsp), %r8
leaq 0xa0(%rsp), %r9
pushq %rax
leaq 0x98(%rsp), %rax
pushq %rax
callq 0x356e
popq %rax
popq %rcx
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
callq 0x363e
movq %rbp, (%rax)
leaq 0x17f9(%rip), %rdi      # 0x42dd
xorl %esi, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x2030
movq %r14, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x32f1
incq %rbx
jmp 0x2a6e
movq 0x44c4(%rip), %rdi      # 0x6fd0
callq 0x2080
leaq 0x17e3(%rip), %rsi      # 0x42fb
movq %rax, %rdi
callq 0x2120
movzbl 0x260(%rsp), %ecx
imull %ecx, %r12d
movq %rax, %rdi
movq %r12, %rsi
callq 0x20c0
leaq 0x17c9(%rip), %rsi      # 0x4307
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
callq 0x2150
movq %rax, %r14
pushq $0x8
popq %rdi
callq 0x2130
leaq 0xafb(%rip), %rcx       # 0x3660
movq %rax, %r15
movq %rcx, 0x110(%rsp)
andq $0x0, 0x118(%rsp)
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
callq 0x363e
leaq 0x110(%rsp), %rsi
movq %r15, %rdi
movq %rax, %rdx
callq 0x375c
leaq 0x60(%rsp), %rdi
xorl %esi, %esi
callq 0x37dc
movq %r15, (%rax)
leaq 0x60(%rsp), %rdi
xorl %esi, %esi
callq 0x37dc
movq (%rax), %rdi
callq 0x21c0
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
callq 0x363e
movq (%rax), %rax
movb 0x8(%rax), %bpl
cmpb $0x1, %bpl
jne 0x2bfa
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
movq $0x0, 0x8(%rsp)
callq 0x363e
movq (%rax), %rax
vmovupd 0x1030(%rax), %xmm0
vmovapd %xmm0, 0x10(%rsp)
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
callq 0x363e
movq (%rax), %rax
movq (%rax), %r15
callq 0x2150
movq %rax, %r12
movq 0x43b5(%rip), %rdi      # 0x6fd0
callq 0x2080
testb %bpl, %bpl
je 0x2c6f
movq 0x43a4(%rip), %rdi      # 0x6fd0
leaq 0x16e1(%rip), %rsi      # 0x4314
callq 0x2120
movq 0x8(%rsp), %rsi
movq %rax, %rdi
callq 0x21d0
leaq 0x16d4(%rip), %rsi      # 0x4320
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
leaq 0x16e6(%rip), %rdi      # 0x4349
leaq 0x10(%rsp), %rsi
callq 0x32e8
jmp 0x2c8a
movq 0x435a(%rip), %rdi      # 0x6fd0
leaq 0x16df(%rip), %rsi      # 0x435c
callq 0x2120
movq %rax, %rdi
callq 0x2080
movq 0x433f(%rip), %rdi      # 0x6fd0
callq 0x2080
leaq 0x16e3(%rip), %rsi      # 0x4380
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
movq 0x431c(%rip), %rdi      # 0x6fd0
leaq 0x159b(%rip), %rsi      # 0x4256
callq 0x2120
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movl 0x18(%rax,%rcx), %edx
andl $-0x4b, %edx
orl $0x2, %edx
movl %edx, 0x18(%rax,%rcx)
movq %rax, %rdi
movq %r15, %rsi
callq 0x20c0
leaq 0x16ab(%rip), %rsi      # 0x4392
movq %rax, %rdi
callq 0x2120
subq %r14, %r12
vcvtsi2sd %r12, %xmm1, %xmm0
vmulsd 0x1351(%rip), %xmm0, %xmm0 # 0x4050
movq 0x42ca(%rip), %rdi      # 0x6fd0
vmovsd %xmm0, 0x8(%rsp)
callq 0x2190
leaq 0x1739(%rip), %rsi      # 0x4451
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
testq %r15, %r15
je 0x2dde
movq 0x4298(%rip), %rdi      # 0x6fd0
leaq 0x1517(%rip), %rsi      # 0x4256
callq 0x2120
movq %rax, %rdi
movq %r12, %rax
xorl %edx, %edx
divq %r15
movl %eax, %esi
callq 0x20c0
leaq 0x1651(%rip), %rsi      # 0x43ae
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
vcvtusi2sd %r15, %xmm1, %xmm0
vdivsd 0x8(%rsp), %xmm0, %xmm0
vcvttsd2usi %xmm0, %rbx
cmpq $0xf4241, %rbx          # imm = 0xF4241
jb 0x2de6
movq 0x4241(%rip), %rdi      # 0x6fd0
leaq 0x14c0(%rip), %rsi      # 0x4256
callq 0x2120
movq (%rax), %rcx
movl $0xfffffefb, %esi       # imm = 0xFFFFFEFB
vcvtusi2sd %rbx, %xmm1, %xmm0
vmulsd 0x12a7(%rip), %xmm0, %xmm0 # 0x4058
movq -0x18(%rcx), %rdx
andl 0x18(%rax,%rdx), %esi
orl $0x4, %esi
movl %esi, 0x18(%rax,%rdx)
movq -0x18(%rcx), %rcx
movq $0x2, 0x8(%rax,%rcx)
movq %rax, %rdi
callq 0x2190
leaq 0x15eb(%rip), %rsi      # 0x43c7
jmp 0x2e0b
pushq $0x1
popq %rbx
jmp 0x2efb
movq 0x41e3(%rip), %rdi      # 0x6fd0
leaq 0x1462(%rip), %rsi      # 0x4256
callq 0x2120
movq %rax, %rdi
movq %rbx, %rsi
callq 0x20c0
leaq 0x15d8(%rip), %rsi      # 0x43e3
movq %rax, %rdi
callq 0x2120
movq %rax, %rdi
callq 0x2080
xorl %ebx, %ebx
testb %bpl, %bpl
je 0x2efb
vxorpd %xmm0, %xmm0, %xmm0
leaq 0xb0(%rsp), %rbx
leaq 0x110(%rsp), %r14
movb $0x0, 0x100(%rsp)
vmovapd %xmm0, (%rbx)
vxorpd %xmm0, %xmm0, %xmm0
vmovupd %zmm0, 0x100(%r14)
vmovupd %zmm0, 0xc0(%r14)
vmovupd %zmm0, 0x80(%r14)
vmovupd %zmm0, 0x40(%r14)
vmovupd %zmm0, (%r14)
leaq 0x50(%rsp), %rdi
movq %r14, %rsi
vzeroupper
callq 0x3087
leaq 0x10(%rsp), %rsi
movq %r14, %rdi
movq %rbx, %rdx
callq 0x334d
xorl %eax, %eax
cmpq $0x10, %rax
je 0x2ea4
movb 0x40(%rsp,%rax), %cl
xorb %cl, 0xb0(%rsp,%rax)
incq %rax
jmp 0x2e8e
leaq 0xb0(%rsp), %rbx
leaq 0xf0(%rsp), %r14
vmovapd (%rbx), %xmm0
vmovapd %xmm0, (%r14)
leaq 0x1532(%rip), %rdi      # 0x43f6
leaq 0x10(%rsp), %rsi
callq 0x32e8
leaq 0x1532(%rip), %rdi      # 0x4407
movq %rbx, %rsi
callq 0x32e8
movq %r14, %rdi
callq 0x2060
leaq 0x152b(%rip), %rdi      # 0x4417
movq %rax, %rdx
xorl %ebx, %ebx
movq %r14, %rsi
xorl %eax, %eax
callq 0x2030
leaq 0x28(%rsp), %rdi
callq 0x3cc2
leaq 0x60(%rsp), %rdi
callq 0x3be2
movl %ebx, %eax
addq $0x3288, %rsp           # imm = 0x3288
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x40c6(%rip), %rdi      # 0x6ff0
leaq 0x1252(%rip), %rsi      # 0x4183
callq 0x2120
movq %rax, %rdi
callq 0x2080
pushq $-0x1
popq %rdi
callq 0x2140
leaq 0x1255(%rip), %rdi      # 0x41a2
leaq 0x1258(%rip), %rsi      # 0x41ac
leaq 0x1269(%rip), %rcx      # 0x41c4
movl $0x1b0, %edx            # imm = 0x1B0
callq 0x20b0
leaq 0x1236(%rip), %rdi      # 0x41a2
leaq 0x1239(%rip), %rsi      # 0x41ac
leaq 0x124a(%rip), %rcx      # 0x41c4
movl $0x1b2, %edx            # imm = 0x1B2
callq 0x20b0
leaq 0x1217(%rip), %rdi      # 0x41a2
leaq 0x121a(%rip), %rsi      # 0x41ac
leaq 0x122b(%rip), %rcx      # 0x41c4
movl $0x1b4, %edx            # imm = 0x1B4
callq 0x20b0
leaq 0x11f8(%rip), %rdi      # 0x41a2
leaq 0x11fb(%rip), %rsi      # 0x41ac
leaq 0x120c(%rip), %rcx      # 0x41c4
movl $0x1b6, %edx            # imm = 0x1B6
callq 0x20b0
leaq 0x11d9(%rip), %rdi      # 0x41a2
leaq 0x11dc(%rip), %rsi      # 0x41ac
leaq 0x11ed(%rip), %rcx      # 0x41c4
movl $0x1b8, %edx            # imm = 0x1B8
callq 0x20b0
leaq 0x11ba(%rip), %rdi      # 0x41a2
leaq 0x11bd(%rip), %rsi      # 0x41ac
leaq 0x11ce(%rip), %rcx      # 0x41c4
movl $0x1ba, %edx            # imm = 0x1BA
callq 0x20b0
leaq 0x119b(%rip), %rdi      # 0x41a2
leaq 0x119e(%rip), %rsi      # 0x41ac
leaq 0x11af(%rip), %rcx      # 0x41c4
movl $0x1bc, %edx            # imm = 0x1BC
callq 0x20b0
leaq 0x117c(%rip), %rdi      # 0x41a2
leaq 0x117f(%rip), %rsi      # 0x41ac
leaq 0x1190(%rip), %rcx      # 0x41c4
movl $0x1be, %edx            # imm = 0x1BE
callq 0x20b0
jmp 0x3068
jmp 0x3068
movq %rax, %rbx
jmp 0x3075
movq %rax, %rbx
movq %r15, %rdi
jmp 0x3061
jmp 0x3068
jmp 0x3068
jmp 0x3068
jmp 0x3068
jmp 0x3068
jmp 0x3068
movq %rax, %rbx
movq %rbp, %rdi
callq 0x2110
jmp 0x306b
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x3cc2
leaq 0x60(%rsp), %rdi
callq 0x3be2
movq %rbx, %rdi
callq 0x21e0