// File: /workspace/github_c_makefile_star2_O1/FH0[P]tun_direct/lwip-2.1.2/src/core/ipv6/ip6.c
// Function: ip6_select_source_address
const ip_addr_t *
ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
{
  const ip_addr_t *best_addr;
  const ip6_addr_t *cand_addr;
  s8_t dest_scope, cand_scope;
  s8_t best_scope = IP6_MULTICAST_SCOPE_RESERVED;
  u8_t i, cand_pref, cand_bits;
  u8_t best_pref = 0;
  u8_t best_bits = 0;

  /* Start by determining the scope of the given destination address. These
   * tests are hopefully (roughly) in order of likeliness to match. */
  if (ip6_addr_isglobal(dest)) {
    dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
  } else if (ip6_addr_islinklocal(dest) || ip6_addr_isloopback(dest)) {
    dest_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
  } else if (ip6_addr_isuniquelocal(dest)) {
    dest_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
  } else if (ip6_addr_ismulticast(dest)) {
    dest_scope = ip6_addr_multicast_scope(dest);
  } else if (ip6_addr_issitelocal(dest)) {
    dest_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
  } else {
    /* no match, consider scope global */
    dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
  }

  best_addr = NULL;

  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
    /* Consider only valid (= preferred and deprecated) addresses. */
    if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
      continue;
    }
    /* Determine the scope of this candidate address. Same ordering idea. */
    cand_addr = netif_ip6_addr(netif, i);
    if (ip6_addr_isglobal(cand_addr)) {
      cand_scope = IP6_MULTICAST_SCOPE_GLOBAL;
    } else if (ip6_addr_islinklocal(cand_addr)) {
      cand_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
    } else if (ip6_addr_isuniquelocal(cand_addr)) {
      cand_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
    } else if (ip6_addr_issitelocal(cand_addr)) {
      cand_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
    } else {
      /* no match, treat as low-priority global scope */
      cand_scope = IP6_MULTICAST_SCOPE_RESERVEDF;
    }
    cand_pref = ip6_addr_ispreferred(netif_ip6_addr_state(netif, i));
    /* @todo compute the actual common bits, for longest matching prefix. */
    /* We cannot count on the destination address having a proper zone
     * assignment, so do not compare zones in this case. */
    cand_bits = ip6_addr_netcmp_zoneless(cand_addr, dest); /* just 1 or 0 for now */
    if (cand_bits && ip6_addr_nethostcmp(cand_addr, dest)) {
      return netif_ip_addr6(netif, i); /* Rule 1 */
    }
    if ((best_addr == NULL) || /* no alternative yet */
        ((cand_scope < best_scope) && (cand_scope >= dest_scope)) ||
        ((cand_scope > best_scope) && (best_scope < dest_scope)) || /* Rule 2 */
        ((cand_scope == best_scope) && ((cand_pref > best_pref) || /* Rule 3 */
        ((cand_pref == best_pref) && (cand_bits > best_bits))))) { /* Rule 8 */
      /* We found a new "winning" candidate. */
      best_addr = netif_ip_addr6(netif, i);
      best_scope = cand_scope;
      best_pref = cand_pref;
      best_bits = cand_bits;
    }
  }

  return best_addr; /* may be NULL */
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movl (%rsi), %edi
movl %edi, %ecx
andl $0xe0, %ecx
movl $0xe, %eax
cmpl $0x20, %ecx
je 0xfb80
movl %edi, %ecx
andl $0xc0ff, %ecx           # imm = 0xC0FF
movl $0x2, %eax
cmpq $0x80fe, %rcx           # imm = 0x80FE
je 0xfb80
testq %rdi, %rdi
jne 0xfb47
cmpl $0x0, 0x4(%r14)
jne 0xfb47
cmpl $0x0, 0x8(%r14)
jne 0xfb47
cmpl $0x1000000, 0xc(%r14)   # imm = 0x1000000
je 0xfb80
movl %edi, %edx
andl $0xfe, %edx
movl $0x8, %eax
cmpl $0xfc, %edx
je 0xfb80
cmpb $-0x1, %dil
jne 0xfb6f
callq 0x13c57
shrl $0x10, %eax
andl $0xf, %eax
jmp 0xfb80
xorl %eax, %eax
cmpl $0xc0fe, %ecx           # imm = 0xC0FE
setne %al
leal (%rax,%rax,8), %eax
addl $0x5, %eax
addq $0x98, %rbx
movq $-0x48, %rdx
xorl %edi, %edi
movl $0x5, %esi
movq %rbx, %r8
xorl %r10d, %r10d
xorl %ecx, %ecx
xorl %r9d, %r9d
movb (%r8), %r11b
testb $0x10, %r11b
je 0xfc67
movl (%rbx,%rdx), %r12d
movl %r12d, %r15d
andl $0xe0, %r15d
movb $0xe, %bpl
cmpl $0x20, %r15d
je 0xfbff
movl %r12d, %r15d
andl $0xc0ff, %r15d          # imm = 0xC0FF
movb $0x2, %bpl
cmpq $0x80fe, %r15           # imm = 0x80FE
je 0xfbff
movl %r12d, %r13d
andl $0xfe, %r13d
movb $0x8, %bpl
cmpl $0xfc, %r13d
je 0xfbff
cmpl $0xc0fe, %r15d          # imm = 0xC0FE
movl $0xf, %ebp
cmovel %esi, %ebp
cmpb $0x30, %r11b
sete %r15b
cmpl (%r14), %r12d
jne 0xfc1b
movl 0x4(%rbx,%rdx), %r12d
cmpl 0x4(%r14), %r12d
sete %r12b
jmp 0xfc1e
xorl %r12d, %r12d
testb %r12b, %r12b
je 0xfc39
movl 0x8(%rbx,%rdx), %r13d
cmpl 0x8(%r14), %r13d
jne 0xfc39
movl 0xc(%rbx,%rdx), %r13d
cmpl 0xc(%r14), %r13d
je 0xfc98
testq %rcx, %rcx
je 0xfc5a
cmpb %r9b, %bpl
jae 0xfc4c
movzbl %bpl, %r13d
cmpl %r13d, %eax
jbe 0xfc5a
cmpb %r9b, %bpl
jbe 0xfc76
movzbl %r9b, %r13d
cmpl %r13d, %eax
jbe 0xfc76
leaq (%rbx,%rdx), %rcx
movl %ebp, %r9d
movl %r15d, %r10d
movl %r12d, %edi
incq %r8
addq $0x18, %rdx
jne 0xfba0
jmp 0xfc9e
cmpb %r9b, %bpl
jne 0xfc67
xorl %r13d, %r13d
cmpb $0x30, %r11b
sete %r13b
movzbl %r10b, %r11d
cmpl %r11d, %r13d
ja 0xfc5a
jne 0xfc67
cmpb %dil, %r12b
ja 0xfc5a
jmp 0xfc67
addq %rdx, %rbx
movq %rbx, %rcx
movq %rcx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq