// File: /workspace/github_c_makefile_star2_O1/TeaInside[P]teavpn/src/teavpn/server/tcp.c
// Function: teavpn_tcp_server
__attribute__((force_align_arg_pointer)) uint8_t teavpn_tcp_server(server_config *config)
{
	fd_set rd_set;
	int  fd_ret, max_fd;
	ssize_t nwrite, nread;
	int16_t bufchan_index;
	pthread_t accept_worker;
	struct sockaddr_in server_addr;
	struct teavpn_tcp_queue _queues[QUEUE_AMOUNT];
	struct buffer_channel _bufchan[BUFCHAN_ALLOC];
	struct connection_entry _connections[CONNECTION_ALLOC];

	/**
	 * To store config file buffer (parsing).
	 *
	 * Avoid to use heap as long as it
	 * is still eligible to use stack.
	 *
	 * (heap is slower than stack)
	 */
	char config_buffer[4096];

	/** 
	 * Assign internal stack allocation to global vars
	 * in order to make other threads can access them.
	 */
	queues = _queues;
	bufchan = _bufchan;
	connections = _connections;

	/**
	 * Initialize TeaVPN server (vars, socket, iface, etc.)
	 */
	if (teavpn_tcp_server_init(config_buffer, config)) {
		return 1;
	}

	thread_amount = config->threads;

	/**
	 * Prepare worker threads.
	 * (Threads which transmit data to client).
	 *
	 * Use stack allocation as long as possible.
	 */
	struct worker_thread _workers[thread_amount];
	workers = _workers;

	if (thread_amount < 3) {
		debug_log(0, "Minimal threads amount is 3, but %d given", thread_amount);
		goto close_server;
	}


	/**
	 * Create the worker threads.
	 */
	for (register uint8_t i = 0; i < config->threads; ++i) {
		workers[i].busy = false;
		workers[i].num = i;
		pthread_cond_init(&(workers[i].cond), NULL);
		pthread_mutex_init(&(workers[i].mutex), NULL);
		pthread_create(
			&(workers[i].thread),
			NULL,
			(void * (*)(void *))teavpn_tcp_worker_thread,
			(void *)&(workers[i])
		);
		pthread_detach(workers[i].thread);

		#define thread_name (bufchan[0].buffer)
		sprintf(thread_name, "teavpn-worker-%d", i);
		pthread_setname_np(workers[i].thread, thread_name);
		#undef thread_name
	}
	memset(bufchan[0].buffer, 0, sizeof("teavpn-worker-xxx"));

	/**
	 * Prepare server bind address data.
	 */
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(config->bind_port);
	server_addr.sin_addr.s_addr = inet_addr(config->bind_addr);

	/**
	 * Bind socket to address.
	 */
	if (bind(net_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
		debug_log(0, "Bind socket failed");
		perror("Bind failed");
		goto close_server;
	}

	/**
	 * Listen
	 */
	if (listen(net_fd, 3) < 0) {
		debug_log(0, "Listen socket failed");
		perror("Listen failed");
		goto close_server;
	}

	/**
	 * Ignore SIGPIPE
	 */
	signal(SIGPIPE, SIG_IGN);

	/**
	 * Create accept worker thread.
	 * (Thread which accepts new connection).
	 */
	pthread_create(
		&accept_worker,
		NULL,
		(void * (*)(void *))teavpn_tcp_accept_worker_thread,
		(void *)config
	);
	pthread_setname_np(accept_worker, "accept-worker");
	pthread_detach(accept_worker);

	debug_log(0, "Listening on %s:%d...", config->bind_addr, config->bind_port);

	/**
	 * TeaVPN server event loop.
	 */
	while (true) {

		/**
		 * Calculate maximum value between tap_fd, net_fd and m_pie_fd[0].
		 */
		max_fd = (((tap_fd > net_fd) && (tap_fd > m_pipe_fd[0])) ? tap_fd :
				(net_fd > m_pipe_fd[0]) ? net_fd : m_pipe_fd[0]);

		/**
		 * Set rd_set to zero.
		 *
		 * This is a compulsory step in using
		 * select(2) inside of an event loop.
		 */
		FD_ZERO(&rd_set);

		/**
		 * Add file descriptors to rd_set.
		 */
		FD_SET(net_fd, &rd_set);
		FD_SET(tap_fd, &rd_set);
		FD_SET(m_pipe_fd[0], &rd_set);


		/**
		 * Add all connected clients file descriptor to rd_set.
		 */
		for (register uint16_t i = 0; i < CONNECTION_ALLOC; i++) {
			if (connections[i].connected) {

				/**
				 * Recalculate max fd to make sure that max_fd
				 * has the maximum value from the entire involved
				 * file descriptors.
				 */
				if (connections[i].fd > max_fd) {
					max_fd = connections[i].fd;
				}

				/**
				 * Add file descriptors to rd_set.
				 */
				FD_SET(connections[i].fd, &rd_set);
			}
		}


		/**
		 * Get buffer channel index.
		 */
		do {
			bufchan_index = get_bufchan_index();
		} while (bufchan_index == -1);


		/**
		 * Block main process until there is one or more ready fd.
		 * Read `man 2 select_tut` for details.
		 */
		fd_ret = select(max_fd + 1, &rd_set, NULL, NULL, NULL);

		/**
		 * Got interrupt signal.
		 */
		if ((fd_ret < 0) && (errno == EINTR)) {
			debug_log(2, "select(2) got interrupt signal");
			continue;
		}

		/**
		 * Got an error.
		 */
		if (fd_ret < 0) {
			debug_log(0, "select(2) got an error");
			perror("select()");
			continue;
		}

		/**
		 * Create a macro to manage buffer channel as other data type.
		 *
		 * Don't make a new variable as long as we can use the available
		 * resources in safely way.
		 */
		#define packet ((teavpn_packet *)(bufchan[bufchan_index].buffer))


		/**
		 * Read data from server TUN/TAP.
		 */
		if (FD_ISSET(tap_fd, &rd_set)) {
			/**
			 * Read from TUN/TAP.
			 */
			nread = read(tap_fd, packet->data.data, TEAVPN_TAP_READ_SIZE);
			if (nread < 0) {
				debug_log(0, "Error read from tap_fd");
				perror("Error read from tap_fd");
				goto next_1;
			}

			packet->info.type = TEAVPN_PACKET_DATA;
			packet->info.len = TEAVPN_PACK(nread);
			for (register uint16_t i = 0; i < CONNECTION_ALLOC; i++) {
				if (connections[i].connected) {
					/**
					 * Insert write queue.
					 *
					 * Send bufchan_index to connection i.
					 */
					bufchan[bufchan_index].ref_count++;
					// printf("i = %d;  r = %d\n", bufchan_index, bufchan[bufchan_index].ref_count);
					enqueue_packet(i, bufchan_index);
					thread_job_broadcast();
				}
			}
		}


		next_1:
		/**
		 * Traverse clients fd and read data from clients.
		 */
		for (register uint16_t i = 0; i < CONNECTION_ALLOC; i++) {
			if (connections[i].connected) {
				if (FD_ISSET(connections[i].fd, &rd_set)) {

					/**
					 * Get buffer channel index.
					 */
					do {
						bufchan_index = get_bufchan_index();
					} while (bufchan_index == -1);

					nread = read(connections[i].fd, packet, TEAVPN_PACKET_BUFFER);

					/**
					 * Connection closed by client.
					 */
					if (nread == 0) {
						FD_CLR(connections[i].fd, &rd_set);
						close(connections[i].fd);
						debug_log(1, "(%s:%d) connection closed",
							inet_ntoa(connections[i].addr.sin_addr),
							ntohs(connections[i].addr.sin_port)
						);
						connection_zero(i);
						continue;
					}

					/**
					 * Error read from client fd.
					 */
					if (nread < 0) {
						char *remote_addr = inet_ntoa(connections[i].addr.sin_addr);
						uint16_t remote_port = ntohs(connections[i].addr.sin_port);

						debug_log(0, "Error read from (%s:%d)", remote_addr, remote_port);
						perror("Error read from connection fd");

						/**
						 * Increment the error counter.
						 */
						connections[i].error++;

						/**
						 * Force disconnect client if it has
						 * reached the max number of errors.
						 */
						if (connections[i].error > MAX_CLIENT_ERR) {
							debug_log(0,
								"Client %s:%d has been disconnected because it has reached the max number of errors",
								remote_port,
								remote_port
							);
							FD_CLR(connections[i].fd, &rd_set);
							close(connections[i].fd);
							connection_zero(i);
						}

						continue;
					}


					/**
					 * Write to TUN/TAP server.
					 */
					if (packet->info.type == TEAVPN_PACKET_DATA) {

						while (nread < (packet->info.len)) {
							register ssize_t tmp_nread;
							debug_log(3, "Read extra %ld/%ld bytes", nread, packet->info.len);
							tmp_nread = read(
								connections[i].fd,
								&(((char *)packet)[nread]),
								packet->info.len - nread
							);

							if (tmp_nread < 0) {
								connections[i].error++;
								perror("Error read extra");
							} else {
								nread += tmp_nread;
							}
						}

						connections[i].seq++;
						debug_log(3, "[%ld] Read from client %s:%d (server_seq: %ld) (client_seq: %ld) (seq %s)",
							connections[i].seq,
							inet_ntoa(connections[i].addr.sin_addr),
							ntohs(connections[i].addr.sin_port),
							connections[i].seq,
							packet->info.seq,
							(connections[i].seq == packet->info.seq) ? "match" : "invalid"
						);

						nwrite = write(tap_fd, &(packet->data.data), nread - TEAVPN_PACK(0));
						if (nwrite < 0) {
							connections[i].error++;
							perror("Error write to tap_fd");
							continue;
						}

						debug_log(3, "Write to tap_fd %ld bytes", nwrite);

					} else {
						connections[i].error++;
					}
				}
			}
		}


		/**
		 * Deal with new connection.
		 */
		if (FD_ISSET(m_pipe_fd[0], &rd_set)) {
			uint8_t sig_x;

			nread = read(m_pipe_fd[0], &sig_x, sizeof(sig_x));
			if (nread < 0) {
				debug_log(0, "Error read from m_pipe_fd[0]");
				perror("Error read from m_pipe_fd[0]");
			}
		}

		if (FD_ISSET(net_fd, &rd_set)) {
			pthread_cond_signal(&accept_worker_cond);
		}

		/**
		 * Since macro doesn't have scope limit, we have to undef here
		 * so that it doesn't distrub the outer scope of variable usage.
		 */
		#undef packet
	}

	close_server:
	close(m_pipe_fd[0]);
	close(m_pipe_fd[1]);
	close(net_fd);
	close(tap_fd);
	return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
andq $-0x10, %rsp
subq $0x1a1a0, %rsp          # imm = 0x1A1A0
movq %rsp, %rbx
movq %rdi, %r14
movq %fs:0x28, %rax
movq %rax, 0x1a190(%rbx)
leaq 0x19c20(%rbx), %rax
movq %rax, 0x6d30(%rip)      # 0xb368
leaq 0x17a0(%rbx), %rax
movq %rax, 0x6d2a(%rip)      # 0xb370
leaq 0x1020(%rbx), %rax
movq %rax, 0x6d24(%rip)      # 0xb378
xorl %eax, %eax
movw $0x0, 0x17a0(%rbx,%rax)
addq $0x1030, %rax           # imm = 0x1030
cmpq $0x18480, %rax          # imm = 0x18480
jne 0x4656
movl $0x12, %eax
movb $0x0, 0x19c0e(%rbx,%rax)
movq $-0x1, 0x19c16(%rbx,%rax)
movl $0xffffffff, 0x19c1e(%rbx,%rax) # imm = 0xFFFFFFFF
addq $0x18, %rax
cmpq $0x492, %rax            # imm = 0x492
jne 0x4673
xorl %r15d, %r15d
movzwl %r15w, %r15d
movl %r15d, %edi
callq 0x5e10
incl %r15d
cmpw $0x18, %r15w
jne 0x46a1
cmpq $0x0, 0x8(%r14)
je 0x46d2
leaq 0x20(%rbx), %rdi
movq %r14, %rsi
callq 0x2b90
testb %al, %al
je 0x4835
movb 0x3c(%r14), %al
leaq 0x6d47(%rip), %rcx      # 0xb424
movb %al, (%rcx)
cmpq $0x0, 0x18(%r14)
je 0x483e
leaq 0x6ca7(%rip), %rdi      # 0xb398
callq 0x21b0
testl %eax, %eax
js 0x49bf
leaq 0x6d1f(%rip), %rax      # 0xb424
cmpb $0x2, (%rax)
jb 0x4718
leaq 0x310e(%rip), %rdi      # 0x781f
xorl %eax, %eax
callq 0x605c
movq 0x20(%r14), %rdi
movl $0x1, %esi
callq 0x6178
movl %eax, 0x6c68(%rip)      # 0xb394
movq 0x20(%r14), %rsi
testl %eax, %eax
js 0x484e
leaq 0x312a(%rip), %rdi      # 0x7869
xorl %eax, %eax
callq 0x605c
movq 0x20(%r14), %rdi
callq 0x2a80
movq %rax, %r12
movq 0x28(%r14), %rdi
callq 0x2a80
movq %rax, %r13
movq 0x30(%r14), %rdi
callq 0x2a80
movq %rax, %r15
movzwl 0x38(%r14), %ecx
leaq 0x31e2(%rip), %rsi      # 0x7958
leaq 0x1a0a0(%rbx), %rdi
movq %r12, %rdx
xorl %eax, %eax
callq 0x2390
leaq 0x31fc(%rip), %rsi      # 0x798a
leaq 0x1a120(%rbx), %rdi
movq %r12, %rdx
movq %r13, %rcx
movq %r15, %r8
xorl %eax, %eax
callq 0x2390
movq %r12, %rdi
callq 0x2030
movq %r13, %rdi
callq 0x2030
movq %r15, %rdi
callq 0x2030
leaq 0x31ef(%rip), %rdi      # 0x79b3
leaq 0x1a0a0(%rbx), %r15
movq %r15, %rsi
xorl %eax, %eax
callq 0x605c
movq %r15, %rdi
callq 0x2140
testl %eax, %eax
jne 0x4809
leaq 0x31cb(%rip), %rdi      # 0x79b3
leaq 0x1a120(%rbx), %r15
movq %r15, %rsi
xorl %eax, %eax
callq 0x605c
movq %r15, %rdi
callq 0x2140
testl %eax, %eax
je 0x4899
leaq 0x3a48(%rip), %rdi      # 0x8258
xorl %eax, %eax
callq 0x605c
movl 0x6b7b(%rip), %edi      # 0xb398
callq 0x21a0
movl 0x6b74(%rip), %edi      # 0xb39c
callq 0x21a0
movl 0x6b61(%rip), %edi      # 0xb394
jmp 0x486d
leaq 0x2f56(%rip), %rdi      # 0x7792
jmp 0x4845
leaq 0x39ae(%rip), %rdi      # 0x81f3
xorl %eax, %eax
callq 0x605c
jmp 0x4872
leaq 0x39d7(%rip), %rdi      # 0x822c
xorl %eax, %eax
callq 0x605c
movl 0x6b36(%rip), %edi      # 0xb398
callq 0x21a0
movl 0x6b2f(%rip), %edi      # 0xb39c
callq 0x21a0
movq %fs:0x28, %rax
cmpq 0x1a190(%rbx), %rax
jne 0x5185
movb $0x1, %al
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x6b84(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x48b3
leaq 0x2fe8(%rip), %rdi      # 0x7894
xorl %eax, %eax
callq 0x605c
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x2410
movl %eax, 0x6ac6(%rip)      # 0xb390
testl %eax, %eax
js 0x5152
leaq 0x6b4b(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x48ec
leaq 0x2fdd(%rip), %rdi      # 0x78c2
xorl %eax, %eax
callq 0x605c
leaq 0x6b31(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x4906
leaq 0x3988(%rip), %rdi      # 0x8287
xorl %eax, %eax
callq 0x605c
movl 0x6a84(%rip), %edi      # 0xb390
leaq 0x1a0a0(%rbx), %rcx
movl $0x1, (%rcx)
movl $0x1, %esi
movl $0x2, %edx
movl $0x4, %r8d
callq 0x20b0
testl %eax, %eax
js 0x515c
leaq 0x6ae7(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x4950
leaq 0x3977(%rip), %rdi      # 0x82c0
xorl %eax, %eax
callq 0x605c
movq %rsp, %r15
movzbl 0x3d(%r14), %esi
movb %sil, 0x6a21(%rip)      # 0xb380
movq %rsp, %rax
imull $0x68, %esi, %ecx
addl $0xf, %ecx
andl $-0x10, %ecx
subq %rcx, %rax
movq %rax, %rsp
movq %rax, 0x6a10(%rip)      # 0xb388
cmpl $0x3, %esi
jae 0x49c9
leaq 0x310c(%rip), %rdi      # 0x7a90
xorl %eax, %eax
callq 0x605c
movl 0x6a07(%rip), %edi      # 0xb398
callq 0x21a0
movl 0x6a00(%rip), %edi      # 0xb39c
callq 0x21a0
movl 0x69e9(%rip), %edi      # 0xb390
callq 0x21a0
movl 0x69e2(%rip), %edi      # 0xb394
callq 0x21a0
movq %r15, %rsp
jmp 0x4872
callq 0x27f3
jmp 0x4872
movq %r15, 0x8(%rbx)
cmpb $0x0, 0x3d(%r14)
je 0x4a93
leaq 0x30db(%rip), %r12      # 0x7aba
xorl %r15d, %r15d
xorl %r13d, %r13d
movq 0x699c(%rip), %rax      # 0xb388
leaq (%rax,%r15), %rdi
addq $0x38, %rdi
movb $0x0, -0x38(%rdi)
movb %r13b, -0x37(%rdi)
xorl %esi, %esi
callq 0x22a0
movq 0x697e(%rip), %rax      # 0xb388
leaq (%rax,%r15), %rdi
addq $0x10, %rdi
xorl %esi, %esi
callq 0x23d0
movq 0x6968(%rip), %rcx      # 0xb388
leaq (%rcx,%r15), %rdi
addq $0x8, %rdi
addq %r15, %rcx
xorl %esi, %esi
leaq 0x756(%rip), %rdx       # 0x518a
callq 0x2310
movq 0x6948(%rip), %rax      # 0xb388
movq 0x8(%rax,%r15), %rdi
callq 0x22e0
movq 0x691f(%rip), %rdi      # 0xb370
addq $0x10, %rdi
movq %r12, %rsi
movl %r13d, %edx
xorl %eax, %eax
callq 0x2390
movq 0x691f(%rip), %rax      # 0xb388
movq 0x8(%rax,%r15), %rdi
movq 0x68fb(%rip), %rsi      # 0xb370
addq $0x10, %rsi
callq 0x2170
incq %r13
movzbl 0x3d(%r14), %eax
addq $0x68, %r15
cmpq %rax, %r13
jb 0x49e5
movq 0x68d6(%rip), %rax      # 0xb370
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
movw $0x0, 0x20(%rax)
leaq 0x1a120(%rbx), %r15
movaps %xmm0, (%r15)
movw $0x2, (%r15)
movzwl 0x3a(%r14), %eax
rolw $0x8, %ax
movw %ax, 0x2(%r15)
movq (%r14), %rdi
callq 0x2210
movl %eax, 0x4(%r15)
movl 0x68b8(%rip), %edi      # 0xb390
movq %r15, %rsi
movl $0x10, %edx
callq 0x2300
testl %eax, %eax
js 0x516d
movl 0x689d(%rip), %edi      # 0xb390
movl $0x3, %esi
callq 0x22f0
testl %eax, %eax
movq 0x8(%rbx), %r15
js 0x517b
movl $0x1, %esi
movl $0xd, %edi
callq 0x2230
leaq 0xa58(%rip), %rdx       # 0x5577
leaq 0x18(%rbx), %r15
movq %r15, %rdi
xorl %esi, %esi
movq %r14, %rcx
callq 0x2310
movq (%r15), %rdi
leaq 0x2fd3(%rip), %rsi      # 0x7b0d
callq 0x2170
movq (%r15), %rdi
callq 0x22e0
movq (%r14), %rsi
movzwl 0x3a(%r14), %edx
leaq 0x2fc5(%rip), %rdi      # 0x7b1b
xorl %eax, %eax
callq 0x605c
leaq 0x30ed(%rip), %r13      # 0x7c51
movl 0x682a(%rip), %edx      # 0xb394
movl 0x6820(%rip), %ecx      # 0xb390
movl 0x6822(%rip), %eax      # 0xb398
xorps %xmm0, %xmm0
movaps %xmm0, 0x1a0a0(%rbx)
movaps %xmm0, 0x1a0b0(%rbx)
movaps %xmm0, 0x1a0c0(%rbx)
movaps %xmm0, 0x1a0d0(%rbx)
movaps %xmm0, 0x1a0e0(%rbx)
movaps %xmm0, 0x1a0f0(%rbx)
movaps %xmm0, 0x1a100(%rbx)
movaps %xmm0, 0x1a110(%rbx)
cmpl %eax, %ecx
movl %eax, %esi
cmovgl %ecx, %esi
cmpl %eax, %edx
movl %esi, %r12d
cmovgl %edx, %r12d
cmpl %ecx, %edx
cmovlel %esi, %r12d
leal 0x3f(%rcx), %esi
testl %ecx, %ecx
cmovnsl %ecx, %esi
movl %esi, %edi
andl $-0x40, %edi
subl %edi, %ecx
movl $0x1, %edi
shlq %cl, %rdi
sarl $0x6, %esi
movslq %esi, %rcx
orq %rdi, 0x1a0a0(%rbx,%rcx,8)
leal 0x3f(%rdx), %esi
testl %edx, %edx
cmovnsl %edx, %esi
movl %esi, %ecx
andl $-0x40, %ecx
subl %ecx, %edx
movl $0x1, %edi
movl %edx, %ecx
shlq %cl, %rdi
sarl $0x6, %esi
movslq %esi, %rcx
orq %rdi, 0x1a0a0(%rbx,%rcx,8)
leal 0x3f(%rax), %edx
testl %eax, %eax
cmovnsl %eax, %edx
movl %edx, %ecx
andl $-0x40, %ecx
subl %ecx, %eax
movl $0x1, %esi
movl %eax, %ecx
shlq %cl, %rsi
sarl $0x6, %edx
movslq %edx, %rax
orq %rsi, 0x1a0a0(%rbx,%rax,8)
movl $0x4, %eax
movq 0x6732(%rip), %rdx      # 0xb378
cmpb $0x1, (%rdx,%rax)
jne 0x4c7c
movl -0x4(%rdx,%rax), %ecx
cmpl %r12d, %ecx
cmovgl %ecx, %r12d
leal 0x3f(%rcx), %esi
testl %ecx, %ecx
cmovnsl %ecx, %esi
movl %esi, %edi
andl $-0x40, %edi
subl %edi, %ecx
movl $0x1, %edi
shlq %cl, %rdi
sarl $0x6, %esi
movslq %esi, %rcx
orq %rdi, 0x1a0a0(%rbx,%rcx,8)
addq $0x50, %rax
cmpq $0x784, %rax            # imm = 0x784
jne 0x4c46
callq 0x5e60
cmpw $-0x1, %ax
je 0x4c88
movl %eax, %r14d
incl %r12d
movl %r12d, %edi
leaq 0x1a0a0(%rbx), %rsi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x2290
testl %eax, %eax
js 0x510a
movl 0x66d7(%rip), %edi      # 0xb394
leal 0x3f(%rdi), %eax
testl %edi, %edi
cmovnsl %edi, %eax
sarl $0x6, %eax
cltq
movq 0x1a0a0(%rbx,%rax,8), %rax
btq %rdi, %rax
jae 0x4de8
movq 0x668d(%rip), %rax      # 0xb370
movswq %r14w, %rcx
imulq $0x1030, %rcx, %r15     # imm = 0x1030
leaq (%rax,%r15), %rsi
addq $0x20, %rsi
movl $0xbb8, %edx            # imm = 0xBB8
callq 0x21d0
testq %rax, %rax
js 0x5137
movq 0x6660(%rip), %rcx      # 0xb370
movl $0x2, 0x10(%rcx,%r15)
addl $0x10, %eax
movw %ax, 0x14(%rcx,%r15)
xorl %r12d, %r12d
movq 0x664c(%rip), %rax      # 0xb378
leaq (%r12,%r12,4), %rcx
shlq $0x4, %rcx
cmpb $0x1, 0x4(%rax,%rcx)
jne 0x4ddb
movq 0x662a(%rip), %rax      # 0xb370
incw (%rax,%r15)
movq 0x6616(%rip), %rax      # 0xb368
cmpb $0x1, (%rax)
jne 0x4d9f
movq $-0x1, %rcx
cmpq $0x2e, %rcx
je 0x4d89
leaq 0x18(%rax), %rdx
incq %rcx
cmpb $0x0, 0x18(%rax)
movq %rdx, %rax
jne 0x4d5e
movw $0x1, (%rdx)
movw %r12w, 0x10(%rdx)
movw %r14w, 0x12(%rdx)
cmpq $0x2f, %rcx
jb 0x4dae
movq %r13, %rdi
xorl %eax, %eax
callq 0x605c
movq 0x65ce(%rip), %rax      # 0xb368
cmpb $0x0, (%rax)
jne 0x4d57
movw $0x1, (%rax)
movw %r12w, 0x10(%rax)
movw %r14w, 0x12(%rax)
movzbl 0x65cb(%rip), %eax      # 0xb380
testq %rax, %rax
je 0x4ddb
movq 0x65c7(%rip), %rdi      # 0xb388
addq $0x38, %rdi
cmpb $0x0, -0x38(%rdi)
je 0x4dd6
addq $0x68, %rdi
decq %rax
jne 0x4dc5
jmp 0x4ddb
callq 0x21f0
incq %r12
cmpq $0x18, %r12
jne 0x4d25
xorl %r14d, %r14d
movq 0x6586(%rip), %rax      # 0xb378
leaq (%r14,%r14,4), %r13
shlq $0x4, %r13
cmpb $0x1, 0x4(%rax,%r13)
jne 0x508b
addq %r13, %rax
movl (%rax), %eax
leal 0x3f(%rax), %ecx
testl %eax, %eax
cmovnsl %eax, %ecx
sarl $0x6, %ecx
movslq %ecx, %rcx
movq 0x1a0a0(%rbx,%rcx,8), %rcx
btq %rax, %rcx
jae 0x508b
callq 0x5e60
cmpw $-0x1, %ax
je 0x4e2b
movq 0x653b(%rip), %rcx      # 0xb378
movl (%rcx,%r13), %edi
movq 0x6528(%rip), %rcx      # 0xb370
movswq %ax, %rax
imulq $0x1030, %rax, %r15     # imm = 0x1030
leaq (%rcx,%r15), %rsi
addq $0x10, %rsi
movl $0xfa0, %edx            # imm = 0xFA0
callq 0x21d0
testq %rax, %rax
je 0x4f00
js 0x5072
movq %rax, %r12
movq 0x64f2(%rip), %rax      # 0xb370
cmpl $0x2, 0x10(%rax,%r15)
jne 0x4f8d
movq 0x64df(%rip), %rax      # 0xb370
movzwl 0x14(%rax,%r15), %eax
cmpq %rax, %r12
jge 0x4f9e
leaq 0x657d(%rip), %rcx      # 0xb424
cmpb $0x3, (%rcx)
jb 0x4ec0
movzwl %ax, %edx
leaq 0x2845(%rip), %rdi      # 0x76fb
movq %r12, %rsi
xorl %eax, %eax
callq 0x605c
movq 0x64b1(%rip), %rax      # 0xb378
movl (%rax,%r13), %edi
movq 0x649e(%rip), %rax      # 0xb370
leaq (%rax,%r15), %rcx
leaq (%r12,%rcx), %rsi
addq $0x10, %rsi
movzwl 0x14(%rax,%r15), %edx
subq %r12, %rdx
callq 0x21d0
testq %rax, %rax
js 0x4ef6
addq %rax, %r12
jmp 0x4e8a
movq %r14, %rdi
callq 0x25f3
jmp 0x4e8a
movq 0x6471(%rip), %rax      # 0xb378
movl (%rax,%r13), %ecx
movq $-0x2, %rax
rolq %cl, %rax
leal 0x3f(%rcx), %edx
testl %ecx, %ecx
cmovnsl %ecx, %edx
sarl $0x6, %edx
movslq %edx, %rdx
andq %rax, 0x1a0a0(%rbx,%rdx,8)
movl %ecx, %edi
callq 0x21a0
leaq 0x64eb(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x4f7f
movq 0x6433(%rip), %rax      # 0xb378
movq %r14, %rcx
shlq $0x4, %rcx
leaq (%rcx,%rcx,4), %r15
movl 0x44(%rax,%r15), %edi
callq 0x20d0
movq 0x6417(%rip), %rcx      # 0xb378
movzwl 0x42(%rcx,%r15), %ecx
rolw $0x8, %cx
movzwl %cx, %edx
leaq 0x2bbc(%rip), %rdi      # 0x7b31
movq %rax, %rsi
xorl %eax, %eax
callq 0x605c
movzwl %r14w, %edi
callq 0x5e10
jmp 0x508b
movq 0x63e4(%rip), %rax      # 0xb378
incb 0x5(%rax,%r13)
jmp 0x508b
movq 0x63d3(%rip), %rax      # 0xb378
incq 0x8(%rax,%r13)
leaq 0x6473(%rip), %rcx      # 0xb424
cmpb $0x3, (%rcx)
jb 0x502d
movq %r14, %rcx
shlq $0x4, %rcx
leaq (%rcx,%rcx,4), %r13
movq 0x8(%rax,%r13), %rcx
movq %rcx, 0x8(%rbx)
movl 0x44(%rax,%r13), %edi
callq 0x20d0
movq 0x639d(%rip), %rdx      # 0xb378
movzwl 0x42(%rdx,%r13), %ecx
rolw $0x8, %cx
movzwl %cx, %ecx
movq 0x8(%rdx,%r13), %r8
movq 0x637c(%rip), %rdx      # 0xb370
movq 0x18(%rdx,%r15), %r9
cmpq %r9, %r8
leaq 0x254e(%rip), %r10      # 0x7551
leaq 0x2541(%rip), %rdx      # 0x754b
cmoveq %rdx, %r10
subq $0x8, %rsp
leaq 0x2bbb(%rip), %rdi      # 0x7bd4
movq 0x8(%rbx), %rsi
movq %rax, %rdx
xorl %eax, %eax
pushq %r10
callq 0x605c
addq $0x10, %rsp
movl 0x6361(%rip), %edi      # 0xb394
movq 0x6336(%rip), %rax      # 0xb370
leaq (%rax,%r15), %rsi
addq $0x20, %rsi
addq $-0x10, %r12
movq %r12, %rdx
callq 0x20c0
testq %rax, %rax
js 0x5083
leaq 0x63ca(%rip), %rcx      # 0xb424
cmpb $0x3, (%rcx)
jb 0x508b
leaq 0x2712(%rip), %rdi      # 0x7778
movq %rax, %rsi
xorl %eax, %eax
callq 0x605c
jmp 0x508b
movq %r14, %rdi
leaq 0x1a0a0(%rbx), %rsi
callq 0x2643
jmp 0x508b
movq %r14, %rdi
callq 0x261b
incq %r14
cmpq $0x18, %r14
jne 0x4deb
movl 0x62fa(%rip), %edi      # 0xb398
leal 0x3f(%rdi), %eax
testl %edi, %edi
cmovnsl %edi, %eax
sarl $0x6, %eax
cltq
movq 0x1a0a0(%rbx,%rax,8), %rax
btq %rdi, %rax
leaq 0x2b93(%rip), %r13      # 0x7c51
jae 0x50d3
movl $0x1, %edx
leaq 0x17(%rbx), %rsi
callq 0x21d0
testq %rax, %rax
js 0x5141
movl 0x62b7(%rip), %eax      # 0xb390
leal 0x3f(%rax), %ecx
testl %eax, %eax
cmovnsl %eax, %ecx
sarl $0x6, %ecx
movslq %ecx, %rcx
movq 0x1a0a0(%rbx,%rcx,8), %rcx
btq %rax, %rcx
jae 0x4b64
leaq 0x62a0(%rip), %rdi      # 0xb3a0
callq 0x21f0
jmp 0x4b64
callq 0x2050
cmpl $0x4, (%rax)
jne 0x5148
leaq 0x6309(%rip), %rax      # 0xb424
cmpb $0x2, (%rax)
jb 0x4b64
leaq 0x2523(%rip), %rdi      # 0x764e
xorl %eax, %eax
callq 0x605c
jmp 0x4b64
callq 0x25c6
jmp 0x4de8
callq 0x2709
jmp 0x50d3
callq 0x2736
jmp 0x4b64
callq 0x27ab
jmp 0x4872
leaq 0x1a0a0(%rbx), %rdi
callq 0x2573
jmp 0x4872
callq 0x2784
movq 0x8(%rbx), %r15
jmp 0x498b
callq 0x275d
jmp 0x498b
callq 0x2110