// File: /workspace/github_c_makefile_star2_O0/FH0[P]tun_direct/lwip-2.1.2/src/core/tcp_out.c
// Function: tcp_split_unsent_seg
err_t
tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
{
  struct tcp_seg *seg = NULL, *useg = NULL;
  struct pbuf *p = NULL;
  u8_t optlen;
  u8_t optflags;
  u8_t split_flags;
  u8_t remainder_flags;
  u16_t remainder;
  u16_t offset;
#if TCP_CHECKSUM_ON_COPY
  u16_t chksum = 0;
  u8_t chksum_swapped = 0;
  struct pbuf *q;
#endif /* TCP_CHECKSUM_ON_COPY */

  LWIP_ASSERT("tcp_split_unsent_seg: invalid pcb", pcb != NULL);

  useg = pcb->unsent;
  if (useg == NULL) {
    return ERR_MEM;
  }

  if (split == 0) {
    LWIP_ASSERT("Can't split segment into length 0", 0);
    return ERR_VAL;
  }

  if (useg->len <= split) {
    return ERR_OK;
  }

  LWIP_ASSERT("split <= mss", split <= pcb->mss);
  LWIP_ASSERT("useg->len > 0", useg->len > 0);

  /* We should check that we don't exceed TCP_SND_QUEUELEN but we need
   * to split this packet so we may actually exceed the max value by
   * one!
   */
  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: split_unsent_seg: %u\n", (unsigned int)pcb->snd_queuelen));

  optflags = useg->flags;
#if TCP_CHECKSUM_ON_COPY
  /* Remove since checksum is not stored until after tcp_create_segment() */
  optflags &= ~TF_SEG_DATA_CHECKSUMMED;
#endif /* TCP_CHECKSUM_ON_COPY */
  optlen = LWIP_TCP_OPT_LENGTH(optflags);
  remainder = useg->len - split;

  /* Create new pbuf for the remainder of the split */
  p = pbuf_alloc(PBUF_TRANSPORT, remainder + optlen, PBUF_RAM);
  if (p == NULL) {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
                ("tcp_split_unsent_seg: could not allocate memory for pbuf remainder %u\n", remainder));
    goto memerr;
  }

  /* Offset into the original pbuf is past TCP/IP headers, options, and split amount */
  offset = useg->p->tot_len - useg->len + split;
  /* Copy remainder into new pbuf, headers and options will not be filled out */
  if (pbuf_copy_partial(useg->p, (u8_t *)p->payload + optlen, remainder, offset ) != remainder) {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
                ("tcp_split_unsent_seg: could not copy pbuf remainder %u\n", remainder));
    goto memerr;
  }
#if TCP_CHECKSUM_ON_COPY
  /* calculate the checksum on remainder data */
  tcp_seg_add_chksum(~inet_chksum((const u8_t *)p->payload + optlen, remainder), remainder,
                     &chksum, &chksum_swapped);
#endif /* TCP_CHECKSUM_ON_COPY */

  /* Options are created when calling tcp_output() */

  /* Migrate flags from original segment */
  split_flags = TCPH_FLAGS(useg->tcphdr);
  remainder_flags = 0; /* ACK added in tcp_output() */

  if (split_flags & TCP_PSH) {
    split_flags &= ~TCP_PSH;
    remainder_flags |= TCP_PSH;
  }
  if (split_flags & TCP_FIN) {
    split_flags &= ~TCP_FIN;
    remainder_flags |= TCP_FIN;
  }
  /* SYN should be left on split, RST should not be present with data */

  seg = tcp_create_segment(pcb, p, remainder_flags, lwip_ntohl(useg->tcphdr->seqno) + split, optflags);
  if (seg == NULL) {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
                ("tcp_split_unsent_seg: could not create new TCP segment\n"));
    goto memerr;
  }

#if TCP_CHECKSUM_ON_COPY
  seg->chksum = chksum;
  seg->chksum_swapped = chksum_swapped;
  seg->flags |= TF_SEG_DATA_CHECKSUMMED;
#endif /* TCP_CHECKSUM_ON_COPY */

  /* Remove this segment from the queue since trimming it may free pbufs */
  pcb->snd_queuelen -= pbuf_clen(useg->p);

  /* Trim the original pbuf into our split size.  At this point our remainder segment must be setup
  successfully because we are modifying the original segment */
  pbuf_realloc(useg->p, useg->p->tot_len - remainder);
  useg->len -= remainder;
  TCPH_SET_FLAG(useg->tcphdr, split_flags);
#if TCP_OVERSIZE_DBGCHECK
  /* By trimming, realloc may have actually shrunk the pbuf, so clear oversize_left */
  useg->oversize_left = 0;
#endif /* TCP_OVERSIZE_DBGCHECK */

  /* Add back to the queue with new trimmed pbuf */
  pcb->snd_queuelen += pbuf_clen(useg->p);

#if TCP_CHECKSUM_ON_COPY
  /* The checksum on the split segment is now incorrect. We need to re-run it over the split */
  useg->chksum = 0;
  useg->chksum_swapped = 0;
  q = useg->p;
  offset = q->tot_len - useg->len; /* Offset due to exposed headers */

  /* Advance to the pbuf where the offset ends */
  while (q != NULL && offset > q->len) {
    offset -= q->len;
    q = q->next;
  }
  LWIP_ASSERT("Found start of payload pbuf", q != NULL);
  /* Checksum the first payload pbuf accounting for offset, then other pbufs are all payload */
  for (; q != NULL; offset = 0, q = q->next) {
    tcp_seg_add_chksum(~inet_chksum((const u8_t *)q->payload + offset, q->len - offset), q->len - offset,
                       &useg->chksum, &useg->chksum_swapped);
  }
#endif /* TCP_CHECKSUM_ON_COPY */

  /* Update number of segments on the queues. Note that length now may
   * exceed TCP_SND_QUEUELEN! We don't have to touch pcb->snd_buf
   * because the total amount of data is constant when packet is split */
  pcb->snd_queuelen += pbuf_clen(seg->p);

  /* Finally insert remainder into queue after split (which stays head) */
  seg->next = useg->next;
  useg->next = seg;

#if TCP_OVERSIZE
  /* If remainder is last segment on the unsent, ensure we clear the oversize amount
   * because the remainder is always sized to the exact remaining amount */
  if (seg->next == NULL) {
    pcb->unsent_oversize = 0;
  }
#endif /* TCP_OVERSIZE */

  return ERR_OK;
memerr:
  TCP_STATS_INC(tcp.memerr);

  LWIP_ASSERT("seg == NULL", seg == NULL);
  if (p != NULL) {
    pbuf_free(p);
  }

  return ERR_MEM;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movw %si, %ax
movq %rdi, -0x10(%rbp)
movw %ax, -0x12(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movw $0x0, -0x3a(%rbp)
movb $0x0, -0x3b(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0x1410d
jmp 0x140de
leaq 0x131e7(%rip), %rdi     # 0x272cc
leaq 0x14b58(%rip), %rsi     # 0x28c44
movl $0x34b, %edx            # imm = 0x34B
leaq 0x148da(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1410f
movq -0x10(%rbp), %rax
movq 0xa8(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x1412e
movb $-0x1, -0x1(%rbp)
jmp 0x146ad
movzwl -0x12(%rbp), %eax
cmpl $0x0, %eax
jne 0x1416a
jmp 0x14139
jmp 0x1413b
leaq 0x1318a(%rip), %rdi     # 0x272cc
leaq 0x14b1d(%rip), %rsi     # 0x28c66
movl $0x353, %edx            # imm = 0x353
leaq 0x1487d(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
movq -0x28(%rbp), %rax
movzwl 0x10(%rax), %eax
movzwl -0x12(%rbp), %ecx
cmpl %ecx, %eax
jg 0x14183
movb $0x0, -0x1(%rbp)
jmp 0x146ad
jmp 0x14185
movzwl -0x12(%rbp), %eax
movq -0x10(%rbp), %rcx
movzwl 0x6a(%rcx), %ecx
cmpl %ecx, %eax
jle 0x141c6
jmp 0x14197
leaq 0x1312e(%rip), %rdi     # 0x272cc
leaq 0x14ae3(%rip), %rsi     # 0x28c88
movl $0x35b, %edx            # imm = 0x35B
leaq 0x14821(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x141c8
jmp 0x141ca
movq -0x28(%rbp), %rax
movzwl 0x10(%rax), %eax
cmpl $0x0, %eax
jg 0x14208
jmp 0x141d9
leaq 0x130ec(%rip), %rdi     # 0x272cc
leaq 0x14aae(%rip), %rsi     # 0x28c95
movl $0x35c, %edx            # imm = 0x35C
leaq 0x147df(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1420a
jmp 0x1420c
jmp 0x1420e
movq -0x28(%rbp), %rax
movb 0x17(%rax), %al
movb %al, -0x32(%rbp)
movzbl -0x32(%rbp), %eax
andl $-0x5, %eax
movb %al, -0x32(%rbp)
movzbl -0x32(%rbp), %edx
andl $0x1, %edx
xorl %eax, %eax
movl $0x4, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movzbl -0x32(%rbp), %edx
andl $0x2, %edx
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %ecx
addl %ecx, %eax
movzbl -0x32(%rbp), %edx
andl $0x8, %edx
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %ecx
addl %ecx, %eax
movzbl -0x32(%rbp), %edx
andl $0x10, %edx
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %ecx
addl %ecx, %eax
movb %al, -0x31(%rbp)
movq -0x28(%rbp), %rax
movzwl 0x10(%rax), %eax
movzwl -0x12(%rbp), %ecx
subl %ecx, %eax
movw %ax, -0x36(%rbp)
movzwl -0x36(%rbp), %eax
movzbl -0x31(%rbp), %ecx
addl %ecx, %eax
movl $0x4a, %edi
movl $0x280, %edx            # imm = 0x280
movzwl %ax, %esi
callq 0x6e20
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x142ae
jmp 0x142a7
jmp 0x142a9
jmp 0x1465d
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movzwl 0x10(%rax), %eax
movq -0x28(%rbp), %rcx
movzwl 0x10(%rcx), %ecx
subl %ecx, %eax
movzwl -0x12(%rbp), %ecx
addl %ecx, %eax
movw %ax, -0x38(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rsi
movzbl -0x31(%rbp), %eax
cltq
addq %rax, %rsi
movw -0x36(%rbp), %ax
movzwl %ax, %edx
movzwl -0x38(%rbp), %ecx
callq 0x8250
movzwl %ax, %eax
movzwl -0x36(%rbp), %ecx
cmpl %ecx, %eax
je 0x1430b
jmp 0x14304
jmp 0x14306
jmp 0x1465d
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
movzbl -0x31(%rbp), %eax
cltq
addq %rax, %rdi
movzwl -0x36(%rbp), %esi
callq 0x25f20
movzwl %ax, %eax
xorl $-0x1, %eax
leaq -0x3a(%rbp), %rdx
leaq -0x3b(%rbp), %rcx
movzwl %ax, %edi
movzwl -0x36(%rbp), %esi
callq 0x13d40
movq -0x28(%rbp), %rax
movq 0x18(%rax), %rax
movzwl 0xc(%rax), %edi
callq 0x251c0
movzwl %ax, %eax
andl $0x3f, %eax
movb %al, -0x33(%rbp)
movb $0x0, -0x34(%rbp)
movzbl -0x33(%rbp), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x1437d
movzbl -0x33(%rbp), %eax
andl $-0x9, %eax
movb %al, -0x33(%rbp)
movzbl -0x34(%rbp), %eax
orl $0x8, %eax
movb %al, -0x34(%rbp)
movzbl -0x33(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x1439d
movzbl -0x33(%rbp), %eax
andl $-0x2, %eax
movb %al, -0x33(%rbp)
movzbl -0x34(%rbp), %eax
orl $0x1, %eax
movb %al, -0x34(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x58(%rbp)
movb -0x34(%rbp), %al
movb %al, -0x49(%rbp)
movq -0x28(%rbp), %rax
movq 0x18(%rax), %rax
movl 0x4(%rax), %edi
callq 0x251f0
movq -0x60(%rbp), %rdi
movq -0x58(%rbp), %rsi
movl %eax, %ecx
movb -0x49(%rbp), %al
movzwl -0x12(%rbp), %edx
addl %edx, %ecx
movzbl %al, %edx
movzbl -0x32(%rbp), %r8d
callq 0x13de0
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0x143f7
jmp 0x143f0
jmp 0x143f2
jmp 0x1465d
movw -0x3a(%rbp), %cx
movq -0x20(%rbp), %rax
movw %cx, 0x14(%rax)
movb -0x3b(%rbp), %cl
movq -0x20(%rbp), %rax
movb %cl, 0x16(%rax)
movq -0x20(%rbp), %rax
movzbl 0x17(%rax), %ecx
orl $0x4, %ecx
movb %cl, 0x17(%rax)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x7bf0
movzwl %ax, %edx
movq -0x10(%rbp), %rax
movzwl 0x9e(%rax), %ecx
subl %edx, %ecx
movw %cx, 0x9e(%rax)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rdi
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movzwl 0x10(%rax), %eax
movzwl -0x36(%rbp), %ecx
subl %ecx, %eax
movzwl %ax, %esi
callq 0x75a0
movzwl -0x36(%rbp), %edx
movq -0x28(%rbp), %rax
movzwl 0x10(%rax), %ecx
subl %edx, %ecx
movw %cx, 0x10(%rax)
movq -0x28(%rbp), %rax
movq 0x18(%rax), %rax
movzwl 0xc(%rax), %eax
movl %eax, -0x64(%rbp)
movzbl -0x33(%rbp), %eax
movzwl %ax, %edi
callq 0x251c0
movw %ax, %cx
movl -0x64(%rbp), %eax
movzwl %cx, %ecx
orl %ecx, %eax
movw %ax, %cx
movq -0x28(%rbp), %rax
movq 0x18(%rax), %rax
movw %cx, 0xc(%rax)
movq -0x28(%rbp), %rax
movw $0x0, 0x12(%rax)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x7bf0
movzwl %ax, %edx
movq -0x10(%rbp), %rax
movzwl 0x9e(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x9e(%rax)
movq -0x28(%rbp), %rax
movw $0x0, 0x14(%rax)
movq -0x28(%rbp), %rax
movb $0x0, 0x16(%rax)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movzwl 0x10(%rax), %eax
movq -0x28(%rbp), %rcx
movzwl 0x10(%rcx), %ecx
subl %ecx, %eax
movw %ax, -0x38(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x48(%rbp)
movb %al, -0x65(%rbp)
je 0x1452a
movzwl -0x38(%rbp), %eax
movq -0x48(%rbp), %rcx
movzwl 0x12(%rcx), %ecx
cmpl %ecx, %eax
setg %al
movb %al, -0x65(%rbp)
movb -0x65(%rbp), %al
testb $0x1, %al
jne 0x14533
jmp 0x14552
movq -0x48(%rbp), %rax
movzwl 0x12(%rax), %ecx
movzwl -0x38(%rbp), %eax
subl %ecx, %eax
movw %ax, -0x38(%rbp)
movq -0x48(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0x1450a
jmp 0x14554
cmpq $0x0, -0x48(%rbp)
jne 0x1458c
jmp 0x1455d
leaq 0x12d68(%rip), %rdi     # 0x272cc
leaq 0x14738(%rip), %rsi     # 0x28ca3
movl $0x3bb, %edx            # imm = 0x3BB
leaq 0x1445b(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x1458e
jmp 0x14590
cmpq $0x0, -0x48(%rbp)
je 0x14603
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rdi
movzwl -0x38(%rbp), %eax
cltq
addq %rax, %rdi
movq -0x48(%rbp), %rax
movzwl 0x12(%rax), %eax
movzwl -0x38(%rbp), %ecx
subl %ecx, %eax
movzwl %ax, %esi
callq 0x25f20
movzwl %ax, %eax
xorl $-0x1, %eax
movw %ax, %si
movq -0x48(%rbp), %rax
movzwl 0x12(%rax), %eax
movzwl -0x38(%rbp), %ecx
subl %ecx, %eax
movq -0x28(%rbp), %rdx
addq $0x14, %rdx
movq -0x28(%rbp), %rcx
addq $0x16, %rcx
movzwl %si, %edi
movzwl %ax, %esi
callq 0x13d40
movw $0x0, -0x38(%rbp)
movq -0x48(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x48(%rbp)
jmp 0x14590
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x7bf0
movzwl %ax, %edx
movq -0x10(%rbp), %rax
movzwl 0x9e(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x9e(%rax)
movq -0x28(%rbp), %rax
movq (%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x14657
movq -0x10(%rbp), %rax
movw $0x0, 0xa0(%rax)
movb $0x0, -0x1(%rbp)
jmp 0x146ad
jmp 0x1465f
cmpq $0x0, -0x20(%rbp)
je 0x14697
jmp 0x14668
leaq 0x12c5d(%rip), %rdi     # 0x272cc
leaq 0x14649(%rip), %rsi     # 0x28cbf
movl $0x3d8, %edx            # imm = 0x3D8
leaq 0x14350(%rip), %rcx     # 0x289d2
movb $0x0, %al
callq 0x20d0
xorl %eax, %eax
movl %eax, %edi
callq 0x21b0
callq 0x2040
jmp 0x14699
cmpq $0x0, -0x30(%rbp)
je 0x146a9
movq -0x30(%rbp), %rdi
callq 0x7260
movb $-0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
addq $0x70, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)