// File: /workspace/github_c_makefile_star2_O2/snej[P]zdelta/trees.c
// Function: build_tree
local void build_tree(s, desc)
     deflate_state *s;
     tree_desc *desc; /* the tree descriptor */
{
  ct_data *tree         = desc->dyn_tree;
  const ct_data *stree  = desc->stat_desc->static_tree;
  int elems             = desc->stat_desc->elems;
  int n, m;          /* iterate over heap elements */
  int max_code = -1; /* largest code with non zero frequency */
  int node;          /* new node being created */

  /* Construct the initial heap, with least frequent element in
   * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
   * heap[0] is not used.
   */
  s->heap_len = 0, s->heap_max = HEAP_SIZE;

  for (n = 0; n < elems; n++) {
    if (tree[n].Freq != 0) {
      s->heap[++(s->heap_len)] = max_code = n;
      s->depth[n] = 0;
    } else {
      tree[n].Len = 0;
    }
  }

  /* The pkzip format requires that at least one distance code exists,
   * and that at least one bit should be sent even if there is only one
   * possible code. So to avoid special checks later on we force at least
   * two codes of non zero frequency.
   */
  while (s->heap_len < 2) {
    node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
    tree[node].Freq = 1;
    s->depth[node] = 0;
    s->opt_len--; if (stree) s->static_len -= stree[node].Len;
    /* node is 0 or 1 so it does not have extra bits */
  }
  desc->max_code = max_code;
  
  /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
   * establish sub-heaps of increasing lengths:
   */
  for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);

  /* Construct the Huffman tree by repeatedly combining the least two
   * frequent nodes.
   */
  node = elems;              /* next internal node of the tree */
  do {
    pqremove(s, tree, n);  /* n = node of least frequency */
    m = s->heap[SMALLEST]; /* m = node of next least frequency */
    
    s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
    s->heap[--(s->heap_max)] = m;
    
    /* Create a new node father of n and m */
    tree[node].Freq = tree[n].Freq + tree[m].Freq;
    s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
    tree[n].Dad = tree[m].Dad = (ush)node;
#ifdef DUMP_BL_TREE 
    if (tree == s->bl_tree) {
      fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
	      node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
    }
#endif
    /* and insert the new node in the heap */
    s->heap[SMALLEST] = node++;
    pqdownheap(s, tree, SMALLEST);
    
  } while (s->heap_len >= 2);
  
  s->heap[--(s->heap_max)] = s->heap[SMALLEST];
  
  /* At this point, the fields freq and dad are set. We can now
   * generate the bit lengths.
   */
  gen_bitlen(s, (tree_desc *)desc);
  
  /* The field len is now set, we can generate the bit codes */
  gen_codes ((ct_data *)tree, max_code, s->bl_count);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdi, %r14
movq (%rsi), %rbx
movq 0x10(%rsi), %rcx
movq (%rcx), %rax
movslq 0x14(%rcx), %r15
movabsq $0x23f00000000, %rcx    # imm = 0x23F00000000
movq %rcx, 0x17ec(%rdi)
xorl %ecx, %ecx
testl %r15d, %r15d
movl $0x0, %edx
cmovgl %r15d, %edx
pushq $-0x1
popq %rdi
cmpq %rcx, %rdx
je 0x4f78
cmpw $0x0, (%rbx,%rcx,4)
je 0x4f6d
movslq 0x17ec(%r14), %r8
leal 0x1(%r8), %edi
movl %edi, 0x17ec(%r14)
movl %ecx, 0xef4(%r14,%r8,4)
movb $0x0, 0x17f4(%r14,%rcx)
movl %ecx, %edi
jmp 0x4f73
andw $0x0, 0x2(%rbx,%rcx,4)
incq %rcx
jmp 0x4f3a
xorl %ecx, %ecx
movslq 0x17ec(%r14), %r12
cmpq $0x1, %r12
jg 0x4fd3
leal 0x1(%rdi), %edx
cmpl $0x2, %edi
cmovll %edx, %edi
cmovgel %ecx, %edx
leal 0x1(%r12), %r8d
movl %r8d, 0x17ec(%r14)
movl %edx, 0xef4(%r14,%r12,4)
movslq %edx, %rdx
movw $0x1, (%rbx,%rdx,4)
movb $0x0, 0x17f4(%r14,%rdx)
decq 0x1a58(%r14)
testq %rax, %rax
je 0x4f7a
movzwl 0x2(%rax,%rdx,4), %edx
subq %rdx, 0x1a60(%r14)
jmp 0x4f7a
movq %rdi, 0x10(%rsp)
movq %rsi, 0x8(%rsp)
movl %edi, 0x8(%rsi)
shrl %r12d
testl %r12d, %r12d
jle 0x4ffb
movq %r14, %rdi
movq %rbx, %rsi
movl %r12d, %edx
callq 0x5970
decl %r12d
jmp 0x4fe3
movl 0x17ec(%r14), %eax
pushq $0x1
popq %rbp
movq %r15, %r12
movslq 0xef4(%r14), %r13
leal -0x1(%rax), %ecx
movl %ecx, 0x17ec(%r14)
cltq
movl 0xef0(%r14,%rax,4), %eax
movl %eax, 0xef4(%r14)
movq %r14, %rdi
movq %rbx, %rsi
movl %ebp, %edx
callq 0x5970
movslq 0xef4(%r14), %rax
movslq 0x17f0(%r14), %rcx
leal -0x1(%rcx), %edx
movl %edx, 0x17f0(%r14)
movl %r13d, 0xeec(%r14,%rcx,4)
movslq 0x17f0(%r14), %rcx
leal -0x1(%rcx), %edx
movl %edx, 0x17f0(%r14)
movl %eax, 0xeec(%r14,%rcx,4)
movzwl (%rbx,%rax,4), %ecx
addw (%rbx,%r13,4), %cx
movw %cx, (%rbx,%r15,4)
movzbl 0x17f4(%r14,%r13), %ecx
movzbl 0x17f4(%r14,%rax), %edx
cmpb %dl, %cl
cmoval %ecx, %edx
incb %dl
movb %dl, 0x17f4(%r14,%r15)
movw %r15w, 0x2(%rbx,%rax,4)
movw %r15w, 0x2(%rbx,%r13,4)
incq %r12
movl %r15d, 0xef4(%r14)
movq %r14, %rdi
movq %rbx, %rsi
movl %ebp, %edx
callq 0x5970
movl 0x17ec(%r14), %eax
movq %r12, %r15
cmpl $0x1, %eax
jg 0x5008
movl 0xef4(%r14), %eax
movslq 0x17f0(%r14), %rcx
leal -0x1(%rcx), %edx
movl %edx, 0x17f0(%r14)
movl %eax, 0xeec(%r14,%rcx,4)
movq 0x8(%rsp), %rdx
movq (%rdx), %rax
movl 0x8(%rdx), %ecx
movq 0x10(%rdx), %rdx
movq (%rdx), %r8
movq 0x8(%rdx), %rsi
movq %rsi, 0x18(%rsp)
movl 0x10(%rdx), %esi
movl %esi, 0x8(%rsp)
movslq 0x18(%rdx), %rdx
xorl %esi, %esi
cmpq $0x10, %rsi
je 0x5132
andw $0x0, 0xed0(%r14,%rsi,2)
incq %rsi
jmp 0x511d
movslq 0x17f0(%r14), %rsi
movslq 0xef0(%r14,%rsi,4), %rsi
andw $0x0, 0x2(%rax,%rsi,4)
movslq 0x17f0(%r14), %r11
leal 0x1(%r11), %esi
xorl %edi, %edi
cmpq $0x23d, %r11            # imm = 0x23D
jg 0x51ff
movslq 0xef4(%r14,%r11,4), %r12
movzwl 0x2(%rax,%r12,4), %r9d
movzwl 0x2(%rax,%r9,4), %r9d
xorl %ebp, %ebp
movl %edx, %r13d
cmpl %r9d, %edx
setle %r15b
jle 0x5189
incl %r9d
movl %r9d, %r13d
movw %r13w, 0x2(%rax,%r12,4)
cmpl %ecx, %r12d
jg 0x51f0
movslq %r13d, %r9
incw 0xed0(%r14,%r9,2)
xorl %r9d, %r9d
cmpl 0x8(%rsp), %r12d
jl 0x51be
movl %r12d, %r9d
subl 0x8(%rsp), %r9d
movslq %r9d, %r9
movq 0x18(%rsp), %r10
movl (%r10,%r9,4), %r9d
movzwl (%rax,%r12,4), %r10d
addl %r9d, %r13d
movslq %r13d, %r13
imulq %r10, %r13
addq %r13, 0x1a58(%r14)
testq %r8, %r8
je 0x51f0
movzwl 0x2(%r8,%r12,4), %r12d
movslq %r9d, %r9
addq %r12, %r9
imulq %r10, %r9
addq %r9, 0x1a60(%r14)
movb %r15b, %bpl
addl %ebp, %edi
incl %esi
incq %r11
jmp 0x5154
testl %edi, %edi
je 0x52cf
movq %rdx, %r9
shlq $0x20, %r9
movabsq $0x100000000, %r8       # imm = 0x100000000
addq %r9, %r8
leaq (%r14,%rdx,2), %r9
addq $0xed0, %r9             # imm = 0xED0
movabsq $-0x100000000, %r10     # imm = 0xFFFFFFFF00000000
movq %r9, %r15
movq %r8, %r11
addq %r10, %r11
movzwl -0x2(%r15), %ebp
addq $-0x2, %r15
testw %bp, %bp
je 0x5236
decl %ebp
movw %bp, (%r15)
sarq $0x1f, %r11
addw $0x2, 0xed0(%r14,%r11)
decw 0xed0(%r14,%rdx,2)
leal -0x2(%rdi), %r11d
cmpl $0x2, %edi
movl %r11d, %edi
jg 0x5230
leaq 0xeec(%r14), %rdi
movq %rdx, %r8
subq $0x1, %r8
jb 0x52cf
movzwl 0xed2(%r14,%r8,2), %r9d
subl $0x1, %r9d
jb 0x52ca
movslq %esi, %r10
leaq (%rdi,%r10,4), %r11
movslq (%r11), %r10
decl %esi
addq $-0x4, %r11
cmpl %ecx, %r10d
jg 0x5296
movzwl 0x2(%rax,%r10,4), %r15d
movq %rdx, %r11
subq %r15, %r11
je 0x5289
movzwl (%rax,%r10,4), %r15d
imulq %r15, %r11
addq %r11, 0x1a58(%r14)
movw %dx, 0x2(%rax,%r10,4)
jmp 0x5289
movq %r8, %rdx
jmp 0x527a
xorl %eax, %eax
xorl %ecx, %ecx
movq 0x10(%rsp), %rdx
cmpq $0xf, %rax
je 0x52f3
addw 0xed0(%r14,%rax,2), %cx
addl %ecx, %ecx
movw %cx, 0x22(%rsp,%rax,2)
incq %rax
jmp 0x52d8
testl %edx, %edx
pushq $-0x1
popq %rax
cmovnsl %edx, %eax
cltq
incq %rax
xorl %ecx, %ecx
cmpq %rax, %rcx
je 0x534e
movzwl 0x2(%rbx,%rcx,4), %edx
testl %edx, %edx
je 0x5349
movl %edx, %edi
movzwl 0x20(%rsp,%rdi,2), %esi
movl %esi, %r8d
incl %r8d
movw %r8w, 0x20(%rsp,%rdi,2)
incl %edx
xorl %edi, %edi
movl %esi, %r9d
andl $0x1, %r9d
movzwl %si, %esi
movl %edi, %r8d
orl %r9d, %r8d
shrl %esi
leal (%r8,%r8), %edi
decl %edx
cmpl $0x1, %edx
ja 0x5327
movw %r8w, (%rbx,%rcx,4)
incq %rcx
jmp 0x5302
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq