// File: /workspace/github_cpp_makefile_star2_O1/tomfunkhouser[P]gaps/pkgs/png/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)((s->depth[n] >= s->depth[m] ?
                                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), %rbp
movabsq $0x23d00000000, %rcx    # imm = 0x23D00000000
movq %rcx, 0x14a4(%rdi)
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
testq %rbp, %rbp
jle 0x9931b
xorl %ecx, %ecx
cmpw $0x0, (%rbx,%rcx,4)
je 0x9930c
movslq 0x14a4(%r14), %rdx
leal 0x1(%rdx), %edi
movl %edi, 0x14a4(%r14)
movl %ecx, 0xbb4(%r14,%rdx,4)
movb $0x0, 0x14ac(%r14,%rcx)
movl %ecx, %r13d
jmp 0x99313
movw $0x0, 0x2(%rbx,%rcx,4)
incq %rcx
cmpq %rcx, %rbp
jne 0x992de
movl 0x14a4(%r14), %r12d
cmpl $0x1, %r12d
jg 0x99387
xorl %ecx, %ecx
leal 0x1(%r13), %edx
cmpl $0x2, %r13d
cmovll %edx, %r13d
cmovgel %ecx, %edx
leal 0x1(%r12), %edi
movl %edi, 0x14a4(%r14)
movslq %r12d, %rdi
movl %edx, 0xbb4(%r14,%rdi,4)
movslq %edx, %rdx
movw $0x1, (%rbx,%rdx,4)
movb $0x0, 0x14ac(%r14,%rdx)
decq 0x1708(%r14)
testq %rax, %rax
je 0x9937a
movzwl 0x2(%rax,%rdx,4), %edx
subq %rdx, 0x1710(%r14)
movl 0x14a4(%r14), %r12d
cmpl $0x2, %r12d
jl 0x9932a
movq %rsi, 0x10(%rsp)
movl %r13d, 0x8(%rsi)
cmpl $0x2, %r12d
jb 0x993b5
shrl %r12d
movq %r14, %rdi
movq %rbx, %rsi
movl %r12d, %edx
callq 0x99c4b
leal -0x1(%r12), %eax
cmpl $0x1, %r12d
movl %eax, %r12d
jg 0x99399
movq %rbp, %r12
movslq 0xbb4(%r14), %r15
movslq 0x14a4(%r14), %rax
leal -0x1(%rax), %ecx
movl %ecx, 0x14a4(%r14)
movl 0xbb0(%r14,%rax,4), %eax
movl %eax, 0xbb4(%r14)
movq %r14, %rdi
movq %rbx, %rsi
movl $0x1, %edx
callq 0x99c4b
movslq 0xbb4(%r14), %rax
movslq 0x14a8(%r14), %rcx
leal -0x1(%rcx), %edx
movl %edx, 0x14a8(%r14)
movl %r15d, 0xbac(%r14,%rcx,4)
movslq 0x14a8(%r14), %rcx
leal -0x1(%rcx), %edx
movl %edx, 0x14a8(%r14)
movl %eax, 0xbac(%r14,%rcx,4)
movzwl (%rbx,%rax,4), %ecx
addw (%rbx,%r15,4), %cx
movw %cx, (%rbx,%rbp,4)
movzbl 0x14ac(%r14,%r15), %ecx
movzbl 0x14ac(%r14,%rax), %edx
cmpb %dl, %cl
cmoval %ecx, %edx
incb %dl
movb %dl, 0x14ac(%r14,%rbp)
movw %bp, 0x2(%rbx,%rax,4)
movw %bp, 0x2(%rbx,%r15,4)
incq %r12
movl %ebp, 0xbb4(%r14)
movq %r14, %rdi
movq %rbx, %rsi
movl $0x1, %edx
callq 0x99c4b
cmpl $0x1, 0x14a4(%r14)
movq %r12, %rbp
jg 0x993b8
movl 0xbb4(%r14), %eax
movslq 0x14a8(%r14), %rcx
leal -0x1(%rcx), %edx
movl %edx, 0x14a8(%r14)
movl %eax, 0xbac(%r14,%rcx,4)
movq 0x10(%rsp), %rdx
movq (%rdx), %rax
movl 0x8(%rdx), %ecx
movq 0x10(%rdx), %rdx
movq (%rdx), %rsi
movq %rsi, 0x10(%rsp)
movq 0x8(%rdx), %rsi
movq %rsi, 0x18(%rsp)
movl 0x10(%rdx), %esi
movl %esi, 0xc(%rsp)
movslq 0x18(%rdx), %rdx
leaq 0xb90(%r14), %rsi
xorps %xmm0, %xmm0
movups %xmm0, 0xba0(%r14)
movups %xmm0, 0xb90(%r14)
movslq 0x14a8(%r14), %rdi
movslq 0xbb0(%r14,%rdi,4), %rdi
movw $0x0, 0x2(%rax,%rdi,4)
movslq 0x14a8(%r14), %rdi
cmpq $0x23b, %rdi            # imm = 0x23B
jg 0x995d3
xorl %r8d, %r8d
movslq 0xbb4(%r14,%rdi,4), %r12
movzwl 0x2(%rax,%r12,4), %r9d
movzwl 0x2(%rax,%r9,4), %r9d
xorl %ebp, %ebp
movl %edx, %r10d
cmpl %r9d, %edx
setle %r15b
jle 0x99546
incl %r9d
movl %r9d, %r10d
movw %r10w, 0x2(%rax,%r12,4)
cmpl %ecx, %r12d
jg 0x995b1
movslq %r10d, %r9
incw (%rsi,%r9,2)
xorl %r11d, %r11d
cmpl 0xc(%rsp), %r12d
jl 0x99577
movl %r12d, %r9d
subl 0xc(%rsp), %r9d
movslq %r9d, %r9
movq 0x18(%rsp), %r11
movl (%r11,%r9,4), %r11d
movzwl (%rax,%r12,4), %r9d
addl %r11d, %r10d
movslq %r10d, %r10
imulq %r9, %r10
addq %r10, 0x1708(%r14)
cmpq $0x0, 0x10(%rsp)
je 0x995b1
movq 0x10(%rsp), %r10
movzwl 0x2(%r10,%r12,4), %r10d
movslq %r11d, %r11
addq %r10, %r11
imulq %r9, %r11
addq %r11, 0x1710(%r14)
movb %r15b, %bpl
addl %ebp, %r8d
movq %rdi, %r9
incq %r9
cmpl $0x23b, %edi            # imm = 0x23B
movq %r9, %rdi
jne 0x9951e
movl $0x23d, %edi            # imm = 0x23D
jmp 0x995d8
incl %edi
xorl %r8d, %r8d
testl %r8d, %r8d
je 0x9969c
movq %rdx, %r10
shlq $0x20, %r10
movabsq $0x100000000, %r9       # imm = 0x100000000
addq %r10, %r9
leaq (%r14,%rdx,2), %r10
addq $0xb90, %r10            # imm = 0xB90
movabsq $-0x100000000, %r11     # imm = 0xFFFFFFFF00000000
movq %r10, %r12
movq %r9, %r15
addq %r11, %r15
movzwl -0x2(%r12), %ebp
addq $-0x2, %r12
testw %bp, %bp
je 0x99610
decl %ebp
movw %bp, (%r12)
sarq $0x1f, %r15
addw $0x2, (%rsi,%r15)
decw (%rsi,%rdx,2)
leal -0x2(%r8), %ebp
cmpl $0x2, %r8d
movl %ebp, %r8d
jg 0x9960a
testl %edx, %edx
je 0x9969c
leaq 0xbac(%r14), %r8
movzwl (%rsi,%rdx,2), %r9d
testl %r9d, %r9d
je 0x99697
movslq %edi, %r10
leaq (%r8,%r10,4), %r11
movslq (%r11), %r10
decl %edi
addq $-0x4, %r11
cmpl %ecx, %r10d
jg 0x99660
movzwl 0x2(%rax,%r10,4), %r15d
movq %rdx, %r11
subq %r15, %r11
je 0x99692
movzwl (%rax,%r10,4), %r15d
imulq %r15, %r11
addq %r11, 0x1708(%r14)
movw %dx, 0x2(%rax,%r10,4)
decl %r9d
jne 0x99659
decq %rdx
jne 0x9964f
xorl %eax, %eax
xorl %ecx, %ecx
andl $0xfffe, %ecx           # imm = 0xFFFE
movzwl 0xb90(%r14,%rax,2), %edx
addl %ecx, %edx
addl %edx, %edx
movw %dx, 0x22(%rsp,%rax,2)
incq %rax
movl %edx, %ecx
cmpq $0xf, %rax
jne 0x996a0
testl %r13d, %r13d
js 0x99708
incl %r13d
xorl %eax, %eax
movzwl 0x2(%rbx,%rax,4), %ecx
testl %ecx, %ecx
je 0x99700
movl %ecx, %esi
movzwl 0x20(%rsp,%rsi,2), %edx
leal 0x1(%rdx), %edi
movw %di, 0x20(%rsp,%rsi,2)
incl %ecx
xorl %esi, %esi
movl %edx, %edi
andl $0x1, %edi
orl %esi, %edi
shrl %edx
leal (%rdi,%rdi), %esi
decl %ecx
cmpl $0x1, %ecx
jg 0x996e9
movw %di, (%rbx,%rax,4)
incq %rax
cmpq %r13, %rax
jne 0x996cd
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq