// File: /workspace/github_cpp_makefile_star2_O1/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 0x3c53
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, -0x30(%rbp)
movq 0xe0(%rdi), %rsi
movl (%rdi), %r8d
movl 0x18(%rdi), %edi
movl 0x3c(%rbx), %eax
xorl %r12d, %r12d
subl 0x64(%rbx), %eax
cmovbl %r12d, %eax
movl %eax, -0x34(%rbp)
movslq 0xd0(%rbx), %rcx
movl $0x0, %r13d
movq %rsi, %r15
testq %rcx, %rcx
movq %rsi, -0x40(%rbp)
jle 0x37fa
xorl %r14d, %r14d
movq %rsi, %r15
movl %r15d, %edx
subl %esi, %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
jle 0x37b8
movl %edi, %r15d
movq %rbx, %rdi
movl %r8d, %r12d
movq %rcx, %r13
callq 0x3c67
movq %r13, %rcx
movl %r12d, %r8d
movl %r15d, %edi
movq -0x40(%rbp), %rsi
movq %rsi, %r15
movq 0xc8(%rbx), %rax
movl (%rax,%r14,8), %r13d
movl 0x4(%rax,%r14,8), %r12d
movl %r8d, (%r15)
movw $0x52, 0x4(%r15)
movl -0x34(%rbp), %eax
movw %ax, 0x6(%r15)
movl %r12d, 0x8(%r15)
movl %r13d, 0xc(%r15)
movl %edi, 0x10(%r15)
movl $0x0, 0x14(%r15)
addq $0x18, %r15
incq %r14
cmpq %r14, %rcx
jne 0x378a
movl $0x0, 0xd0(%rbx)
cmpl $0x0, 0x40(%rbx)
je 0x3b75
movq $0x0, 0x74(%rbx)
testb $0x1, 0x48(%rbx)
jne 0x3822
movl -0x30(%rbp), %r14d
jmp 0x3878
movl %r15d, %edx
subl %esi, %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
movl -0x30(%rbp), %r14d
jle 0x384e
movl %edi, -0x2c(%rbp)
movq %rbx, %rdi
movl %r8d, %r15d
callq 0x3c67
movl %r15d, %r8d
movl -0x2c(%rbp), %edi
movq -0x40(%rbp), %rsi
movq %rsi, %r15
movl %r8d, (%r15)
movw $0x53, 0x4(%r15)
movl -0x34(%rbp), %eax
movw %ax, 0x6(%r15)
movl %r12d, 0x8(%r15)
movl %r13d, 0xc(%r15)
movl %edi, 0x10(%r15)
movl $0x0, 0x14(%r15)
addq $0x18, %r15
testb $0x2, 0x48(%rbx)
je 0x38d0
movl %r15d, %edx
subl %esi, %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
jle 0x38a6
movl %edi, -0x2c(%rbp)
movq %rbx, %rdi
movl %r8d, %r15d
callq 0x3c67
movl %r15d, %r8d
movl -0x2c(%rbp), %edi
movq -0x40(%rbp), %rsi
movq %rsi, %r15
movl %r8d, (%r15)
movw $0x54, 0x4(%r15)
movl -0x34(%rbp), %eax
movw %ax, 0x6(%r15)
movl %r12d, 0x8(%r15)
movl %r13d, 0xc(%r15)
movl %edi, 0x10(%r15)
movl $0x0, 0x14(%r15)
addq $0x18, %r15
movl $0x0, 0x48(%rbx)
movl 0x38(%rbx), %eax
movl 0x40(%rbx), %r11d
cmpl %r11d, %eax
cmovbl %eax, %r11d
cmpl $0x0, 0xec(%rbx)
jne 0x38f8
movl 0x44(%rbx), %eax
cmpl %r11d, %eax
cmovbl %eax, %r11d
movl 0x14(%rbx), %r10d
movl 0x10(%rbx), %eax
addl %r11d, %eax
cmpl %eax, %r10d
jns 0x39ad
leaq 0x88(%rbx), %rcx
leaq 0xa8(%rbx), %rdx
negl %eax
xorps %xmm0, %xmm0
movq (%rcx), %rdi
cmpq %rdi, %rcx
je 0x39ad
movq (%rdi), %r8
movq 0x8(%rdi), %r9
movq %r9, 0x8(%r8)
movq 0x8(%rdi), %r9
movq %r8, (%r9)
movups %xmm0, (%rdi)
movq 0xb0(%rbx), %r8
movq %r8, 0x8(%rdi)
movq %rdx, (%rdi)
movq %rdi, (%r8)
movq %rdi, 0xb0(%rbx)
decl 0x68(%rbx)
incl 0x60(%rbx)
movl (%rbx), %r8d
movl %r8d, 0x10(%rdi)
movl $0x51, 0x14(%rdi)
movl -0x34(%rbp), %r8d
movl %r8d, 0x1c(%rdi)
movl %r14d, 0x20(%rdi)
leal 0x1(%r10), %r8d
movl %r8d, 0x14(%rbx)
movl %r10d, 0x24(%rdi)
movl 0x18(%rbx), %r9d
movl %r9d, 0x28(%rdi)
movl %r14d, 0x30(%rdi)
movl 0x30(%rbx), %r9d
movl %r9d, 0x34(%rdi)
movq $0x0, 0x38(%rdi)
movl %eax, %edi
addl %r8d, %edi
movl %r8d, %r10d
js 0x391e
movl %r11d, -0x4c(%rbp)
movl 0xe8(%rbx), %eax
testl %eax, %eax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmovgl %eax, %ecx
movl %ecx, -0x48(%rbp)
movl $0x0, -0x30(%rbp)
cmpl $0x0, 0x6c(%rbx)
jne 0x39da
movl 0x30(%rbx), %eax
sarl $0x3, %eax
movl %eax, -0x30(%rbp)
leaq 0xa8(%rbx), %r13
movq 0xa8(%rbx), %r12
cmpq %r13, %r12
je 0x3bbf
addl %r14d, -0x30(%rbp)
movl $0x0, -0x2c(%rbp)
movl $0x0, -0x44(%rbp)
movl 0x3c(%r12), %ecx
testl %ecx, %ecx
je 0x3a31
cmpl 0x30(%r12), %r14d
js 0x3a4c
incl %ecx
movl %ecx, 0x3c(%r12)
incl 0x58(%rbx)
cmpl $0x0, 0x6c(%rbx)
je 0x3a7a
movl 0x30(%rbx), %ecx
movl %ecx, %eax
shrl $0x1f, %eax
addl %ecx, %eax
sarl %eax
jmp 0x3a7d
movl $0x1, 0x3c(%r12)
movl 0x30(%rbx), %eax
movl %eax, 0x34(%r12)
addl -0x30(%rbp), %eax
movl %eax, 0x30(%r12)
jmp 0x3a96
movb $0x1, %al
movl -0x48(%rbp), %edx
cmpl %edx, 0x38(%r12)
jb 0x3a98
incl %ecx
movl %ecx, 0x3c(%r12)
movl $0x0, 0x38(%r12)
movl 0x34(%r12), %eax
addl %r14d, %eax
movl %eax, 0x30(%r12)
incl -0x44(%rbp)
jmp 0x3a96
movl 0x30(%rbx), %eax
addl 0x34(%r12), %eax
movl %eax, 0x34(%r12)
addl %r14d, %eax
movl %eax, 0x30(%r12)
movl $0x1, -0x2c(%rbp)
xorl %eax, %eax
testb %al, %al
jne 0x3b56
movl %r14d, 0x20(%r12)
movl -0x34(%rbp), %eax
movl %eax, 0x1c(%r12)
movl 0x18(%rbx), %eax
movl %eax, 0x28(%r12)
movl %r15d, %edx
subl %esi, %edx
movl 0x2c(%r12), %eax
addl %edx, %eax
addl $0x18, %eax
cmpl 0x4(%rbx), %eax
jle 0x3ad5
movq %rbx, %rdi
callq 0x3c67
movq -0x40(%rbp), %r15
movl 0x10(%r12), %eax
movl %eax, (%r15)
movb 0x14(%r12), %al
movb %al, 0x4(%r15)
movb 0x18(%r12), %al
movb %al, 0x5(%r15)
movzwl 0x1c(%r12), %eax
movw %ax, 0x6(%r15)
movl 0x20(%r12), %eax
movl %eax, 0x8(%r15)
movl 0x24(%r12), %eax
movl %eax, 0xc(%r15)
movl 0x28(%r12), %eax
movl %eax, 0x10(%r15)
movl 0x2c(%r12), %eax
movl %eax, 0x14(%r15)
addq $0x18, %r15
movl 0x2c(%r12), %edx
testq %rdx, %rdx
je 0x3b41
leaq 0x40(%r12), %rsi
movq %r15, %rdi
callq 0x2220
movl 0x2c(%r12), %eax
addq %rax, %r15
movl 0x3c(%r12), %eax
cmpl 0x7c(%rbx), %eax
jb 0x3b52
movl $0xffffffff, 0xc(%rbx)  # imm = 0xFFFFFFFF
movq -0x40(%rbp), %rsi
movq (%r12), %r12
cmpq %r13, %r12
jne 0x3a03
cmpl $0x0, -0x44(%rbp)
sete %r12b
cmpl $0x0, -0x2c(%rbp)
sete %r14b
jmp 0x3bc5
movl 0x78(%rbx), %ecx
testl %ecx, %ecx
je 0x3c54
movl 0x4c(%rbx), %eax
cmpl 0x74(%rbx), %eax
js 0x3816
cmpl $0x1b57, %ecx           # imm = 0x1B57
ja 0x3b9b
movl $0x1b58, 0x78(%rbx)     # imm = 0x1B58
movl 0x78(%rbx), %ecx
movl %ecx, %edx
shrl %edx
addl %ecx, %edx
movl $0x1d4c0, %ecx          # imm = 0x1D4C0
cmpl %ecx, %edx
cmovael %ecx, %edx
movl %edx, 0x78(%rbx)
addl %eax, %edx
movl %edx, 0x74(%rbx)
orb $0x1, 0x48(%rbx)
jmp 0x3816
movb $0x1, %r12b
movb $0x1, %r14b
subl %esi, %r15d
testl %r15d, %r15d
jle 0x3bd8
movq %rbx, %rdi
movl %r15d, %edx
callq 0x3c67
testb %r12b, %r12b
jne 0x3c05
movl 0x14(%rbx), %eax
subl 0x10(%rbx), %eax
movl %eax, %ecx
shrl %ecx
cmpl $0x4, %eax
movl $0x2, %eax
cmovael %ecx, %eax
movl %eax, 0x24(%rbx)
addl -0x48(%rbp), %eax
movl %eax, 0x44(%rbx)
imull 0x8(%rbx), %eax
movl %eax, 0x80(%rbx)
testb %r14b, %r14b
movl -0x4c(%rbp), %ecx
jne 0x3c2f
movl %ecx, %eax
shrl %eax
cmpl $0x4, %ecx
movl $0x2, %ecx
cmovael %eax, %ecx
movl %ecx, 0x24(%rbx)
movl $0x1, 0x44(%rbx)
movl 0x8(%rbx), %eax
movl %eax, 0x80(%rbx)
cmpl $0x0, 0x44(%rbx)
jne 0x3c45
movl $0x1, 0x44(%rbx)
movl 0x8(%rbx), %eax
movl %eax, 0x80(%rbx)
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 0x3816