// File: /workspace/github_cpp_makefile_star2_O3/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 0x3c17
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdi, %rbx
movl 0x4c(%rdi), %eax
movl %eax, -0x5c(%rbp)
movq 0xe0(%rdi), %r15
movl (%rdi), %edi
movl 0x18(%rbx), %esi
movl 0x3c(%rbx), %eax
xorl %r13d, %r13d
subl 0x64(%rbx), %eax
cmovbl %r13d, %eax
movl %eax, -0x2c(%rbp)
movslq 0xd0(%rbx), %rcx
movl $0x0, %r12d
movq %r15, -0x38(%rbp)
testq %rcx, %rcx
movl %edi, -0x48(%rbp)
jle 0x380a
xorl %r14d, %r14d
movq -0x38(%rbp), %r15
movl %r15d, %edx
movq -0x38(%rbp), %r12
subl %r12d, %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
jle 0x37c8
movq %rbx, %rdi
movl %esi, %r15d
movq %r12, %rsi
movq %rbx, %r13
movq %rcx, %rbx
callq 0x3c2b
movq %rbx, %rcx
movq %r13, %rbx
movl -0x48(%rbp), %edi
movl %r15d, %esi
movq %r12, %r15
movq 0xc8(%rbx), %rax
movl (%rax,%r14,8), %r12d
movl 0x4(%rax,%r14,8), %r13d
movl %edi, (%r15)
movw $0x52, 0x4(%r15)
movl -0x2c(%rbp), %eax
movw %ax, 0x6(%r15)
movl %r13d, 0x8(%r15)
movl %r12d, 0xc(%r15)
movl %esi, 0x10(%r15)
movl $0x0, 0x14(%r15)
addq $0x18, %r15
incq %r14
cmpq %r14, %rcx
jne 0x3793
movl $0x0, 0xd0(%rbx)
cmpl $0x0, 0x40(%rbx)
je 0x3b44
movq $0x0, 0x74(%rbx)
movl 0x48(%rbx), %eax
testb $0x1, %al
je 0x3880
movl %r15d, %edx
subl -0x38(%rbp), %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
jle 0x3853
movq %rbx, %rdi
movq -0x38(%rbp), %r15
movl %esi, %r14d
movq %r15, %rsi
callq 0x3c2b
movl -0x48(%rbp), %edi
movl %r14d, %esi
movl %edi, (%r15)
movw $0x53, 0x4(%r15)
movl -0x2c(%rbp), %eax
movw %ax, 0x6(%r15)
movl %r13d, 0x8(%r15)
movl %r12d, 0xc(%r15)
movl %esi, 0x10(%r15)
movl $0x0, 0x14(%r15)
addq $0x18, %r15
movl 0x48(%rbx), %eax
testb $0x2, %al
je 0x38d4
movl %r15d, %edx
subl -0x38(%rbp), %edx
leal 0x18(%rdx), %eax
cmpl 0x4(%rbx), %eax
jle 0x38aa
movq %rbx, %rdi
movq -0x38(%rbp), %r15
movl %esi, %r14d
movq %r15, %rsi
callq 0x3c2b
movl -0x48(%rbp), %edi
movl %r14d, %esi
movl %edi, (%r15)
movw $0x54, 0x4(%r15)
movl -0x2c(%rbp), %eax
movw %ax, 0x6(%r15)
movl %r13d, 0x8(%r15)
movl %r12d, 0xc(%r15)
movl %esi, 0x10(%r15)
movl $0x0, 0x14(%r15)
addq $0x18, %r15
movl $0x0, 0x48(%rbx)
movl 0x38(%rbx), %eax
movl 0x40(%rbx), %r10d
cmpl %r10d, %eax
cmovbl %eax, %r10d
cmpl $0x0, 0xec(%rbx)
movq -0x38(%rbp), %r14
movl -0x5c(%rbp), %r12d
jne 0x3904
movl 0x44(%rbx), %eax
cmpl %r10d, %eax
cmovbl %eax, %r10d
movl 0x14(%rbx), %esi
movl 0x10(%rbx), %eax
addl %r10d, %eax
cmpl %eax, %esi
jns 0x39a6
leaq 0x88(%rbx), %rcx
leaq 0xa8(%rbx), %rdx
negl %eax
xorps %xmm0, %xmm0
movq (%rcx), %rdi
cmpq %rdi, %rcx
je 0x39a6
movq (%rdi), %r8
movq 0x8(%rdi), %r9
movq %r9, 0x8(%r8)
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 -0x2c(%rbp), %r8d
movl %r8d, 0x1c(%rdi)
movl %r12d, 0x20(%rdi)
leal 0x1(%rsi), %r8d
movl %r8d, 0x14(%rbx)
movl %esi, 0x24(%rdi)
movl 0x18(%rbx), %esi
movl %esi, 0x28(%rdi)
movl %r12d, 0x30(%rdi)
movl 0x30(%rbx), %esi
movl %esi, 0x34(%rdi)
movq $0x0, 0x38(%rdi)
movl %eax, %esi
addl %r8d, %esi
movl %r8d, %esi
js 0x3928
movl %r10d, -0x58(%rbp)
movl 0xe8(%rbx), %eax
testl %eax, %eax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmovgl %eax, %ecx
movl %ecx, -0x50(%rbp)
movl $0x0, -0x3c(%rbp)
cmpl $0x0, 0x6c(%rbx)
jne 0x39d3
movl 0x30(%rbx), %eax
sarl $0x3, %eax
movl %eax, -0x3c(%rbp)
leaq 0xa8(%rbx), %rax
movq 0xa8(%rbx), %r13
movq %rax, -0x48(%rbp)
cmpq %rax, %r13
je 0x3b8a
addl %r12d, -0x3c(%rbp)
movl $0x0, -0x54(%rbp)
movl $0x0, -0x4c(%rbp)
movl 0x3c(%r13), %eax
testl %eax, %eax
je 0x3a42
cmpl 0x30(%r13), %r12d
js 0x3a5a
incl %eax
movl %eax, 0x3c(%r13)
incl 0x58(%rbx)
movl 0x30(%rbx), %eax
movl %eax, %ecx
shrl $0x1f, %ecx
addl %eax, %ecx
sarl %ecx
cmpl $0x0, 0x6c(%rbx)
cmovel %eax, %ecx
addl 0x34(%r13), %ecx
movl %ecx, 0x34(%r13)
addl %r12d, %ecx
movl %ecx, 0x30(%r13)
movl $0x1, -0x54(%rbp)
jmp 0x3a83
movl $0x1, 0x3c(%r13)
movl 0x30(%rbx), %eax
movl %eax, 0x34(%r13)
addl -0x3c(%rbp), %eax
movl %eax, 0x30(%r13)
jmp 0x3a83
movl -0x50(%rbp), %ecx
cmpl %ecx, 0x38(%r13)
jb 0x3b24
incl %eax
movl %eax, 0x3c(%r13)
movl $0x0, 0x38(%r13)
movl 0x34(%r13), %eax
addl %r12d, %eax
movl %eax, 0x30(%r13)
incl -0x4c(%rbp)
movl %r12d, 0x20(%r13)
movl -0x2c(%rbp), %eax
movl %eax, 0x1c(%r13)
movl 0x18(%rbx), %eax
movl %eax, 0x28(%r13)
movl %r15d, %edx
subl %r14d, %edx
movl 0x2c(%r13), %eax
addl %edx, %eax
addl $0x18, %eax
cmpl 0x4(%rbx), %eax
jle 0x3ab7
movq %rbx, %rdi
movq %r14, %rsi
callq 0x3c2b
movq %r14, %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 0x3b14
leaq 0x40(%r13), %rsi
movq %r15, %rdi
callq 0x2230
movl 0x2c(%r13), %eax
addq %rax, %r15
movl 0x3c(%r13), %eax
cmpl 0x7c(%rbx), %eax
jb 0x3b24
movl $0xffffffff, 0xc(%rbx)  # imm = 0xFFFFFFFF
movq (%r13), %r13
cmpq -0x48(%rbp), %r13
jne 0x3a00
cmpl $0x0, -0x4c(%rbp)
sete %r12b
cmpl $0x0, -0x54(%rbp)
sete %r14b
jmp 0x3b90
movl 0x78(%rbx), %ecx
testl %ecx, %ecx
je 0x3c18
movl 0x4c(%rbx), %eax
cmpl 0x74(%rbx), %eax
js 0x3826
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 0x3826
movb $0x1, %r12b
movb $0x1, %r14b
movq -0x38(%rbp), %rsi
subl %esi, %r15d
testl %r15d, %r15d
movl -0x58(%rbp), %r13d
jle 0x3bab
movq %rbx, %rdi
movl %r15d, %edx
callq 0x3c2b
testb %r12b, %r12b
jne 0x3bd8
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 -0x50(%rbp), %eax
movl %eax, 0x44(%rbx)
imull 0x8(%rbx), %eax
movl %eax, 0x80(%rbx)
testb %r14b, %r14b
je 0x3be5
cmpl $0x0, 0x44(%rbx)
jne 0x3c09
jmp 0x3bf9
movl %r13d, %eax
shrl %eax
cmpl $0x4, %r13d
movl $0x2, %ecx
cmovael %eax, %ecx
movl %ecx, 0x24(%rbx)
movl $0x1, 0x44(%rbx)
movl 0x8(%rbx), %eax
movl %eax, 0x80(%rbx)
addq $0x38, %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 0x3826