// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movb $0x0, -0x2b(%rbp)
movb $0x0, -0x2f(%rbp)
movb $0x0, -0x30(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %eax
andq $0xe0, %rax
cmpq $0x20, %rax
jne 0x1c2c7
movb $0xe, -0x29(%rbp)
jmp 0x1c380
movq -0x18(%rbp), %rax
movl (%rax), %eax
andq $0xc0ff, %rax           # imm = 0xC0FF
cmpq $0x80fe, %rax           # imm = 0x80FE
je 0x1c310
movq -0x18(%rbp), %rax
movl (%rax), %eax
cmpq $0x0, %rax
jne 0x1c316
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
cmpq $0x0, %rax
jne 0x1c316
movq -0x18(%rbp), %rax
movl 0x8(%rax), %eax
cmpq $0x0, %rax
jne 0x1c316
movq -0x18(%rbp), %rax
movl 0xc(%rax), %eax
cmpq $0x1000000, %rax        # imm = 0x1000000
jne 0x1c316
movb $0x2, -0x29(%rbp)
jmp 0x1c37e
movq -0x18(%rbp), %rax
movl (%rax), %eax
andq $0xfe, %rax
cmpq $0xfc, %rax
jne 0x1c330
movb $0x8, -0x29(%rbp)
jmp 0x1c37c
movq -0x18(%rbp), %rax
movl (%rax), %eax
andq $0xff, %rax
cmpq $0xff, %rax
jne 0x1c35a
movq -0x18(%rbp), %rax
movl (%rax), %edi
callq 0x251f0
shrl $0x10, %eax
andl $0xf, %eax
movb %al, -0x29(%rbp)
jmp 0x1c37a
movq -0x18(%rbp), %rax
movl (%rax), %eax
andq $0xc0ff, %rax           # imm = 0xC0FF
cmpq $0xc0fe, %rax           # imm = 0xC0FE
jne 0x1c374
movb $0x5, -0x29(%rbp)
jmp 0x1c378
movb $0xe, -0x29(%rbp)
jmp 0x1c37a
jmp 0x1c37c
jmp 0x1c37e
jmp 0x1c380
movq $0x0, -0x20(%rbp)
movb $0x0, -0x2c(%rbp)
movzbl -0x2c(%rbp), %eax
cmpl $0x3, %eax
jge 0x1c571
movq -0x10(%rbp), %rax
movzbl -0x2c(%rbp), %ecx
movzbl 0x98(%rax,%rcx), %eax
andl $0x10, %eax
cmpl $0x0, %eax
jne 0x1c3b6
jmp 0x1c564
movq -0x10(%rbp), %rax
addq $0x50, %rax
movzbl -0x2c(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movl (%rax), %eax
andq $0xe0, %rax
cmpq $0x20, %rax
jne 0x1c3e5
movb $0xe, -0x2a(%rbp)
jmp 0x1c43d
movq -0x28(%rbp), %rax
movl (%rax), %eax
andq $0xc0ff, %rax           # imm = 0xC0FF
cmpq $0x80fe, %rax           # imm = 0x80FE
jne 0x1c3ff
movb $0x2, -0x2a(%rbp)
jmp 0x1c43b
movq -0x28(%rbp), %rax
movl (%rax), %eax
andq $0xfe, %rax
cmpq $0xfc, %rax
jne 0x1c419
movb $0x8, -0x2a(%rbp)
jmp 0x1c439
movq -0x28(%rbp), %rax
movl (%rax), %eax
andq $0xc0ff, %rax           # imm = 0xC0FF
cmpq $0xc0fe, %rax           # imm = 0xC0FE
jne 0x1c433
movb $0x5, -0x2a(%rbp)
jmp 0x1c437
movb $0xf, -0x2a(%rbp)
jmp 0x1c439
jmp 0x1c43b
jmp 0x1c43d
movq -0x10(%rbp), %rax
movzbl -0x2c(%rbp), %ecx
movzbl 0x98(%rax,%rcx), %eax
cmpl $0x30, %eax
sete %al
andb $0x1, %al
movzbl %al, %eax
movb %al, -0x2d(%rbp)
movq -0x28(%rbp), %rax
movl (%rax), %ecx
movq -0x18(%rbp), %rdx
xorl %eax, %eax
cmpl (%rdx), %ecx
movb %al, -0x31(%rbp)
jne 0x1c482
movq -0x28(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x18(%rbp), %rcx
cmpl 0x4(%rcx), %eax
sete %al
movb %al, -0x31(%rbp)
movb -0x31(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movb %al, -0x2e(%rbp)
movzbl -0x2e(%rbp), %eax
cmpl $0x0, %eax
je 0x1c4d2
movq -0x28(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x18(%rbp), %rcx
cmpl 0x8(%rcx), %eax
jne 0x1c4d2
movq -0x28(%rbp), %rax
movl 0xc(%rax), %eax
movq -0x18(%rbp), %rcx
cmpl 0xc(%rcx), %eax
jne 0x1c4d2
movq -0x10(%rbp), %rax
addq $0x50, %rax
movzbl -0x2c(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x8(%rbp)
jmp 0x1c579
cmpq $0x0, -0x20(%rbp)
je 0x1c539
movsbl -0x2a(%rbp), %eax
movsbl -0x2b(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1c4f1
movsbl -0x2a(%rbp), %eax
movsbl -0x29(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1c539
movsbl -0x2a(%rbp), %eax
movsbl -0x2b(%rbp), %ecx
cmpl %ecx, %eax
jle 0x1c509
movsbl -0x2b(%rbp), %eax
movsbl -0x29(%rbp), %ecx
cmpl %ecx, %eax
jl 0x1c539
movsbl -0x2a(%rbp), %eax
movsbl -0x2b(%rbp), %ecx
cmpl %ecx, %eax
jne 0x1c562
movzbl -0x2d(%rbp), %eax
movzbl -0x2f(%rbp), %ecx
cmpl %ecx, %eax
jg 0x1c539
movzbl -0x2d(%rbp), %eax
movzbl -0x2f(%rbp), %ecx
cmpl %ecx, %eax
jne 0x1c562
movzbl -0x2e(%rbp), %eax
movzbl -0x30(%rbp), %ecx
cmpl %ecx, %eax
jle 0x1c562
movq -0x10(%rbp), %rax
addq $0x50, %rax
movzbl -0x2c(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x20(%rbp)
movb -0x2a(%rbp), %al
movb %al, -0x2b(%rbp)
movb -0x2d(%rbp), %al
movb %al, -0x2f(%rbp)
movb -0x2e(%rbp), %al
movb %al, -0x30(%rbp)
jmp 0x1c564
movb -0x2c(%rbp), %al
addb $0x1, %al
movb %al, -0x2c(%rbp)
jmp 0x1c38c
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)