// File: /workspace/github_c_makefile_star2_O2/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, %eax
andl $0xe0, %eax
cmpl $0x20, %eax
jne 0xf173
pushq $0xe
popq %rax
jmp 0xf1dc
movl %edi, %ecx
andl $0xc0ff, %ecx           # imm = 0xC0FF
pushq $0x2
popq %rax
cmpq $0x80fe, %rcx           # imm = 0x80FE
je 0xf1dc
testq %rdi, %rdi
je 0xf19e
movl %edi, %eax
andl $0xfe, %eax
cmpl $0xfc, %eax
jne 0xf1b8
pushq $0x8
jmp 0xf170
cmpl $0x0, 0x4(%r14)
jne 0xf1cb
cmpl $0x0, 0x8(%r14)
jne 0xf1cb
cmpl $0x1000000, 0xc(%r14)   # imm = 0x1000000
je 0xf1dc
jmp 0xf1cb
cmpb $-0x1, %dil
jne 0xf1cb
callq 0x12ed7
shrl $0x10, %eax
andl $0xf, %eax
jmp 0xf1dc
xorl %eax, %eax
cmpl $0xc0fe, %ecx           # imm = 0xC0FE
setne %al
leal (%rax,%rax,8), %eax
addl $0x5, %eax
addq $0x98, %rbx
pushq $-0x48
popq %rdx
xorl %esi, %esi
pushq $0xf
popq %r8
movq %rbx, %r9
xorl %ecx, %ecx
xorl %r10d, %r10d
xorl %r11d, %r11d
testq %rdx, %rdx
je 0xf2fc
movb (%r9), %r15b
testb $0x10, %r15b
je 0xf2bc
movl (%rbx,%rdx), %r13d
movl %r13d, %r12d
andl $0xe0, %r12d
movb $0xe, %bpl
cmpl $0x20, %r12d
je 0xf25e
movl %r13d, %r12d
andl $0xc0ff, %r12d          # imm = 0xC0FF
movb $0x2, %bpl
cmpq $0x80fe, %r12           # imm = 0x80FE
je 0xf25e
movl %r13d, %edi
andl $0xfe, %edi
movb $0x8, %bpl
cmpl $0xfc, %edi
je 0xf25e
cmpl $0xc0fe, %r12d          # imm = 0xC0FE
movl %r8d, %ebp
pushq $0x5
popq %rdi
cmovel %edi, %ebp
cmpb $0x30, %r15b
sete %r12b
cmpl (%r14), %r13d
jne 0xf28e
movl 0x4(%rbx,%rdx), %edi
cmpl 0x4(%r14), %edi
jne 0xf28e
movl 0x8(%rbx,%rdx), %edi
movb $0x1, %r13b
cmpl 0x8(%r14), %edi
jne 0xf291
movl 0xc(%rbx,%rdx), %edi
cmpl 0xc(%r14), %edi
jne 0xf291
jmp 0xf2f6
xorl %r13d, %r13d
testq %rcx, %rcx
je 0xf2b0
cmpb %sil, %bpl
jae 0xf2a3
movzbl %bpl, %edi
cmpl %edi, %eax
jbe 0xf2b0
cmpb %sil, %bpl
jbe 0xf2c8
movzbl %sil, %edi
cmpl %edi, %eax
jbe 0xf2c8
leaq (%rbx,%rdx), %rcx
movl %ebp, %esi
movl %r12d, %r10d
movl %r13d, %r11d
addq $0x18, %rdx
incq %r9
jmp 0xf1f7
cmpb %sil, %bpl
jne 0xf2bc
xorl %edi, %edi
cmpb $0x30, %r15b
sete %dil
movzbl %r10b, %r15d
cmpl %r15d, %edi
ja 0xf2b0
sete %dil
cmpb %r11b, %r13b
seta %r15b
andb %dil, %r15b
cmpb $0x1, %r15b
je 0xf2b0
jmp 0xf2bc
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