// File: /workspace/github_cpp_makefile_star2_O2/xocoder[P]m_kcptun/vendor/kcp/ikcp.c
// Function: ikcp_flush
void ikcp_flush(ikcpcb *kcp)
{
	IUINT32 current = kcp->current;
	char *buffer = kcp->buffer;
	char *ptr = buffer;
	int count, size, i;
	IUINT32 resent, cwnd;
	IUINT32 rtomin;
	struct IQUEUEHEAD *p;
	int change = 0;
	int lost = 0;
	IKCPSEG seg;

	// 'ikcp_update' haven't been called. 
	if (kcp->updated == 0) return;

	seg.conv = kcp->conv;
	seg.cmd = IKCP_CMD_ACK;
	seg.frg = 0;
	seg.wnd = ikcp_wnd_unused(kcp);
	seg.una = kcp->rcv_nxt;
	seg.len = 0;
	seg.sn = 0;
	seg.ts = 0;

	// flush acknowledges
	count = kcp->ackcount;
	for (i = 0; i < count; i++) {
		size = (int)(ptr - buffer);
		if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
			ikcp_output(kcp, buffer, size);
			ptr = buffer;
		}
		ikcp_ack_get(kcp, i, &seg.sn, &seg.ts);
		ptr = ikcp_encode_seg(ptr, &seg);
	}

	kcp->ackcount = 0;

	// probe window size (if remote window size equals zero)
	if (kcp->rmt_wnd == 0) {
		if (kcp->probe_wait == 0) {
			kcp->probe_wait = IKCP_PROBE_INIT;
			kcp->ts_probe = kcp->current + kcp->probe_wait;
		}	
		else {
			if (_itimediff(kcp->current, kcp->ts_probe) >= 0) {
				if (kcp->probe_wait < IKCP_PROBE_INIT) 
					kcp->probe_wait = IKCP_PROBE_INIT;
				kcp->probe_wait += kcp->probe_wait / 2;
				if (kcp->probe_wait > IKCP_PROBE_LIMIT)
					kcp->probe_wait = IKCP_PROBE_LIMIT;
				kcp->ts_probe = kcp->current + kcp->probe_wait;
				kcp->probe |= IKCP_ASK_SEND;
			}
		}
	}	else {
		kcp->ts_probe = 0;
		kcp->probe_wait = 0;
	}

	// flush window probing commands
	if (kcp->probe & IKCP_ASK_SEND) {
		seg.cmd = IKCP_CMD_WASK;
		size = (int)(ptr - buffer);
		if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
			ikcp_output(kcp, buffer, size);
			ptr = buffer;
		}
		ptr = ikcp_encode_seg(ptr, &seg);
	}

	// flush window probing commands
	if (kcp->probe & IKCP_ASK_TELL) {
		seg.cmd = IKCP_CMD_WINS;
		size = (int)(ptr - buffer);
		if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) {
			ikcp_output(kcp, buffer, size);
			ptr = buffer;
		}
		ptr = ikcp_encode_seg(ptr, &seg);
	}

	kcp->probe = 0;

	// calculate window size
	cwnd = _imin_(kcp->snd_wnd, kcp->rmt_wnd);
	if (kcp->nocwnd == 0) cwnd = _imin_(kcp->cwnd, cwnd);

	// move data from snd_queue to snd_buf
	while (_itimediff(kcp->snd_nxt, kcp->snd_una + cwnd) < 0) {
		IKCPSEG *newseg;
		if (iqueue_is_empty(&kcp->snd_queue)) break;

		newseg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node);

		iqueue_del(&newseg->node);
		iqueue_add_tail(&newseg->node, &kcp->snd_buf);
		kcp->nsnd_que--;
		kcp->nsnd_buf++;

		newseg->conv = kcp->conv;
		newseg->cmd = IKCP_CMD_PUSH;
		newseg->wnd = seg.wnd;
		newseg->ts = current;
		newseg->sn = kcp->snd_nxt++;
		newseg->una = kcp->rcv_nxt;
		newseg->resendts = current;
		newseg->rto = kcp->rx_rto;
		newseg->fastack = 0;
		newseg->xmit = 0;
	}

	// calculate resent
	resent = (kcp->fastresend > 0)? (IUINT32)kcp->fastresend : 0xffffffff;
	rtomin = (kcp->nodelay == 0)? (kcp->rx_rto >> 3) : 0;

	// flush data segments
	for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = p->next) {
		IKCPSEG *segment = iqueue_entry(p, IKCPSEG, node);
		int needsend = 0;
		if (segment->xmit == 0) {
			needsend = 1;
			segment->xmit++;
			segment->rto = kcp->rx_rto;
			segment->resendts = current + segment->rto + rtomin;
		}
		else if (_itimediff(current, segment->resendts) >= 0) {
			needsend = 1;
			segment->xmit++;
			kcp->xmit++;
			if (kcp->nodelay == 0) {
				segment->rto += kcp->rx_rto;
			}	else {
				segment->rto += kcp->rx_rto / 2;
			}
			segment->resendts = current + segment->rto;
			lost = 1;
		}
		else if (segment->fastack >= resent) {
			needsend = 1;
			segment->xmit++;
			segment->fastack = 0;
			segment->resendts = current + segment->rto;
			change++;
		}

		if (needsend) {
			int size, need;
			segment->ts = current;
			segment->wnd = seg.wnd;
			segment->una = kcp->rcv_nxt;

			size = (int)(ptr - buffer);
			need = IKCP_OVERHEAD + segment->len;

			if (size + need > (int)kcp->mtu) {
				ikcp_output(kcp, buffer, size);
				ptr = buffer;
			}

			ptr = ikcp_encode_seg(ptr, segment);

			if (segment->len > 0) {
				memcpy(ptr, segment->data, segment->len);
				ptr += segment->len;
			}

			if (segment->xmit >= kcp->dead_link) {
				kcp->state = -1;
			}
		}
	}

	// flash remain segments
	size = (int)(ptr - buffer);
	if (size > 0) {
		ikcp_output(kcp, buffer, size);
	}

	// update ssthresh
	if (change) {
		IUINT32 inflight = kcp->snd_nxt - kcp->snd_una;
		kcp->ssthresh = inflight / 2;
		if (kcp->ssthresh < IKCP_THRESH_MIN)
			kcp->ssthresh = IKCP_THRESH_MIN;
		kcp->cwnd = kcp->ssthresh + resent;
		kcp->incr = kcp->cwnd * kcp->mss;
	}

	if (lost) {
		kcp->ssthresh = cwnd / 2;
		if (kcp->ssthresh < IKCP_THRESH_MIN)
			kcp->ssthresh = IKCP_THRESH_MIN;
		kcp->cwnd = 1;
		kcp->incr = kcp->mss;
	}

	if (kcp->cwnd < 1) {
		kcp->cwnd = 1;
		kcp->incr = kcp->mss;
	}
}

// Assembly:
cmpl $0x0, 0x70(%rdi)
je 0x398f
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rdi, %rbx
movl 0x4c(%rdi), %eax
movl %eax, -0x34(%rbp)
movq 0xe0(%rdi), %rsi
movl (%rdi), %edi
movl 0x3c(%rbx), %r10d
xorl %r12d, %r12d
subl 0x64(%rbx), %r10d
cmovbl %r12d, %r10d
movl 0xd0(%rbx), %r14d
testl %r14d, %r14d
cmovlel %r12d, %r14d
movl 0x18(%rbx), %r8d
xorl %r13d, %r13d
xorl %r9d, %r9d
movq %rsi, %r15
movq %rsi, -0x40(%rbp)
movl %r10d, -0x30(%rbp)
cmpq %r12, %r14
je 0x35b3
movl %r15d, %edx
subl %esi, %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
jle 0x357a
movl %edi, %r15d
movq %rbx, %rdi
movl %r8d, %r13d
callq 0x39a3
movl %r13d, %r8d
movl %r15d, %edi
movl -0x30(%rbp), %r10d
movq -0x40(%rbp), %rsi
movq %rsi, %r15
movq 0xc8(%rbx), %rax
movl (%rax,%r12,8), %r9d
movl 0x4(%rax,%r12,8), %r13d
movl %edi, (%r15)
movw $0x52, 0x4(%r15)
movw %r10w, 0x6(%r15)
movl %r13d, 0x8(%r15)
movl %r9d, 0xc(%r15)
movl %r8d, 0x10(%r15)
andl $0x0, 0x14(%r15)
addq $0x18, %r15
incq %r12
jmp 0x3549
andl $0x0, 0xd0(%rbx)
cmpl $0x0, 0x40(%rbx)
je 0x3935
andq $0x0, 0x74(%rbx)
movl -0x34(%rbp), %r14d
movl 0x48(%rbx), %eax
testb $0x1, %al
je 0x362d
movl %r15d, %edx
subl %esi, %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
jle 0x3606
movl %edi, -0x2c(%rbp)
movq %rbx, %rdi
movl %r8d, %r12d
movl %r9d, %r15d
callq 0x39a3
movl %r15d, %r9d
movl %r12d, %r8d
movl -0x2c(%rbp), %edi
movl -0x30(%rbp), %r10d
movq -0x40(%rbp), %rsi
movq %rsi, %r15
movl %edi, (%r15)
movw $0x53, 0x4(%r15)
movw %r10w, 0x6(%r15)
movl %r13d, 0x8(%r15)
movl %r9d, 0xc(%r15)
movl %r8d, 0x10(%r15)
andl $0x0, 0x14(%r15)
addq $0x18, %r15
movl 0x48(%rbx), %eax
testb $0x2, %al
je 0x3687
movl %r15d, %edx
subl %esi, %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
jle 0x3663
movl %edi, -0x2c(%rbp)
movq %rbx, %rdi
movl %r8d, %r12d
movl %r9d, %r15d
callq 0x39a3
movl %r15d, %r9d
movl %r12d, %r8d
movl -0x2c(%rbp), %edi
movl -0x30(%rbp), %r10d
movq -0x40(%rbp), %rsi
movq %rsi, %r15
movl %edi, (%r15)
movw $0x54, 0x4(%r15)
movw %r10w, 0x6(%r15)
movl %r13d, 0x8(%r15)
movl %r9d, 0xc(%r15)
movl %r8d, 0x10(%r15)
andl $0x0, 0x14(%r15)
addq $0x18, %r15
andl $0x0, 0x48(%rbx)
movl 0x38(%rbx), %eax
movl 0x40(%rbx), %r11d
cmpl %r11d, %eax
cmovbl %eax, %r11d
cmpl $0x0, 0xec(%rbx)
jne 0x36ac
movl 0x44(%rbx), %eax
cmpl %r11d, %eax
cmovbl %eax, %r11d
leaq 0x88(%rbx), %rax
movl 0x14(%rbx), %edx
leaq 0xa8(%rbx), %r12
movl 0x10(%rbx), %ecx
addl %r11d, %ecx
negl %ecx
xorps %xmm0, %xmm0
movl %ecx, %edi
addl %edx, %edi
jns 0x3741
movq (%rax), %r9
cmpq %r9, %rax
je 0x3741
movq (%r9), %rdi
movq 0x8(%r9), %r8
movq %r8, 0x8(%rdi)
movq %rdi, (%r8)
movups %xmm0, (%r9)
movq 0xb0(%rbx), %rdi
movq %rdi, 0x8(%r9)
movq %r12, (%r9)
movq %r9, (%rdi)
movq %r9, 0xb0(%rbx)
decl 0x68(%rbx)
incl 0x60(%rbx)
movl (%rbx), %edi
movl %edi, 0x10(%r9)
movl $0x51, 0x14(%r9)
movl %r10d, 0x1c(%r9)
movl %r14d, 0x20(%r9)
leal 0x1(%rdx), %edi
movl %edi, 0x14(%rbx)
movl %edx, 0x24(%r9)
movl 0x18(%rbx), %edx
movl %edx, 0x28(%r9)
movl %r14d, 0x30(%r9)
movl 0x30(%rbx), %edx
movl %edx, 0x34(%r9)
andq $0x0, 0x38(%r9)
movl %edi, %edx
jmp 0x36c8
movl %r11d, -0x50(%rbp)
movl 0xe8(%rbx), %eax
testl %eax, %eax
pushq $-0x1
popq %rdi
cmovgl %eax, %edi
movl $0x0, -0x44(%rbp)
cmpl $0x0, 0x6c(%rbx)
movl $0x0, %eax
jne 0x376b
movl 0x30(%rbx), %eax
sarl $0x3, %eax
addl %r14d, %eax
movl %eax, -0x4c(%rbp)
movl $0x0, -0x48(%rbp)
movq %r12, %r13
movl %edi, -0x2c(%rbp)
movq (%r13), %r13
cmpq %r12, %r13
je 0x38c9
movl 0x3c(%r13), %eax
testl %eax, %eax
je 0x37c0
cmpl 0x30(%r13), %r14d
jns 0x37df
cmpl %edi, 0x38(%r13)
jb 0x377e
movl %r14d, %edi
leaq 0x3c(%r13), %r14
incl %eax
movl %eax, 0x3c(%r13)
andl $0x0, 0x38(%r13)
movl 0x34(%r13), %eax
addl %edi, %eax
movl %eax, 0x30(%r13)
incl -0x44(%rbp)
jmp 0x3817
movl %r14d, %edi
leaq 0x3c(%r13), %r14
movl $0x1, 0x3c(%r13)
movl 0x30(%rbx), %eax
movl %eax, 0x34(%r13)
addl -0x4c(%rbp), %eax
movl %eax, 0x30(%r13)
jmp 0x3817
incl %eax
movl %eax, 0x3c(%r13)
incl 0x58(%rbx)
movl %r14d, %edi
leaq 0x3c(%r13), %r14
movl 0x30(%rbx), %ecx
movl %ecx, %eax
cltd
pushq $0x2
popq %r8
idivl %r8d
cmpl $0x0, 0x6c(%rbx)
cmovel %ecx, %eax
addl 0x34(%r13), %eax
movl %eax, 0x34(%r13)
addl %edi, %eax
movl %eax, 0x30(%r13)
pushq $0x1
popq %rax
movl %eax, -0x48(%rbp)
movl %edi, 0x20(%r13)
movl %r10d, 0x1c(%r13)
movl 0x18(%rbx), %eax
movl %eax, 0x28(%r13)
movl %r15d, %edx
subl %esi, %edx
movl 0x2c(%r13), %eax
addl %edx, %eax
addl $0x18, %eax
cmpl 0x4(%rbx), %eax
jle 0x3848
movq %rbx, %rdi
callq 0x39a3
movq -0x40(%rbp), %rsi
movq %rsi, %r15
movl 0x10(%r13), %eax
movl %eax, (%r15)
movb 0x14(%r13), %al
movb %al, 0x4(%r15)
movb 0x18(%r13), %al
movb %al, 0x5(%r15)
movzwl 0x1c(%r13), %eax
movw %ax, 0x6(%r15)
movl 0x20(%r13), %eax
movl %eax, 0x8(%r15)
movl 0x24(%r13), %eax
movl %eax, 0xc(%r15)
movl 0x28(%r13), %eax
movl %eax, 0x10(%r15)
movl 0x2c(%r13), %edx
movl %edx, 0x14(%r15)
addq $0x18, %r15
testq %rdx, %rdx
je 0x38a9
leaq 0x40(%r13), %rsi
movq %r15, %rdi
callq 0x2220
movq -0x40(%rbp), %rsi
movl 0x2c(%r13), %eax
addq %rax, %r15
movl -0x30(%rbp), %r10d
movl -0x2c(%rbp), %edi
movl (%r14), %eax
cmpl 0x7c(%rbx), %eax
movl -0x34(%rbp), %r14d
jb 0x377e
orl $-0x1, 0xc(%rbx)
jmp 0x377e
subl %esi, %r15d
testl %r15d, %r15d
jle 0x38df
movq %rbx, %rdi
movl %r15d, %edx
callq 0x39a3
movl -0x2c(%rbp), %edi
cmpl $0x0, -0x44(%rbp)
movl -0x50(%rbp), %edx
je 0x390d
movl 0x14(%rbx), %eax
subl 0x10(%rbx), %eax
movl %eax, %ecx
shrl %ecx
cmpl $0x4, %eax
pushq $0x2
popq %rax
cmovbl %eax, %ecx
movl %ecx, 0x24(%rbx)
addl %edi, %ecx
movl %ecx, 0x44(%rbx)
imull 0x8(%rbx), %ecx
movl %ecx, 0x80(%rbx)
cmpl $0x0, -0x48(%rbp)
je 0x397b
movl %edx, %eax
shrl %eax
cmpl $0x4, %edx
pushq $0x2
popq %rcx
cmovbl %ecx, %eax
movl %eax, 0x24(%rbx)
movl $0x1, 0x44(%rbx)
movl 0x8(%rbx), %eax
movl %eax, 0x80(%rbx)
jmp 0x3981
movl 0x78(%rbx), %ecx
testl %ecx, %ecx
movl -0x34(%rbp), %r14d
je 0x3990
movl 0x4c(%rbx), %eax
cmpl 0x74(%rbx), %eax
js 0x35cd
cmpl $0x1b59, %ecx           # imm = 0x1B59
movl $0x1b58, %edx           # imm = 0x1B58
cmovael %ecx, %edx
movl %edx, %ecx
shrl %ecx
addl %edx, %ecx
movl $0x1d4c0, %edx          # imm = 0x1D4C0
cmpl %edx, %ecx
cmovael %edx, %ecx
movl %ecx, 0x78(%rbx)
addl %eax, %ecx
movl %ecx, 0x74(%rbx)
orb $0x1, 0x48(%rbx)
jmp 0x35cd
cmpl $0x0, 0x44(%rbx)
je 0x3923
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x1b58, %eax           # imm = 0x1B58
movl %eax, 0x78(%rbx)
addl 0x4c(%rbx), %eax
movl %eax, 0x74(%rbx)
jmp 0x35cd