// File: /workspace/github_c_makefile_star2_O0/Cyan4973[P]FiniteStateEntropy/programs/zlibh.c
// Function: build_tree
static void build_tree(tree_desc* desc)
{
    ct_data *tree         = desc->dyn_tree;
    const ct_data *stree  = desc->stat_desc->static_tree;
    int elems             = desc->max_code;
    unsigned long *csize  = desc->comp_size;
    int n;                              /* iterate over heap elements */
    int max_code = -1;                  /* largest code with non zero frequency */
    int huf_heap[2*ZLIBH_L_CODES+1];    /* heap used to build the Huffman trees */
    int heap_max;                       /* element of largest frequency */
    unsigned char depth[2*ZLIBH_L_CODES+1];
    /* Depth of each subtree used as tie breaker for trees of equal frequency */

    /* Construct the initial heap, with least frequent element in
    * huf_heap[SMALLEST]. The sons of huf_heap[n] are huf_heap[2*n] and huf_heap[2*n+1].
    * huf_heap[0] is used in replacement of heap_len (original Zlib).
    */

    huf_heap[0] = 0, heap_max = ZLIBH_HEAP_SIZE;

    for (n = 0; n <2*ZLIBH_L_CODES+1; n++)
        depth[n] = 0;

    for (n = 0; n < elems; n++) {
        if (tree[n].Freq != 0) {
            huf_heap[0]++;
            huf_heap[huf_heap[0]] = max_code = n;
            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.
    */

    if (huf_heap[0] > 1) {                /* at least two codes (non trivial tree) */
        int node;                           /* new node being created */
        unsigned short bl_count[ZLIBH_MAX_BITS+1];
        /* number of codes at each bit length for an optimal tree */

        desc->max_code = max_code;

        /* The elements huf_heap[huf_heap[0]/2+1 .. huf_heap[0]] are leaves of the tree,
        * establish sub-heaps of increasing lengths:
        */
        for (n = huf_heap[0]/2; n >= 1; n--) pqdownheap(tree, huf_heap, depth, n);

        /* Construct the Huffman tree by repeatedly combining the least two
        * frequent nodes.
        */
        node = elems;                          /* next internal node of the tree */
        do {
            int m;
            pqremove(tree, huf_heap, depth, n);  /* n = node of least frequency */
            m = huf_heap[SMALLEST];              /* m = node of next least frequency */

            huf_heap[--(heap_max)] = n;          /* keep the nodes sorted by frequency */
            huf_heap[--(heap_max)] = m;

            /* Create a new node father of n and m */
            tree[node].Freq = tree[n].Freq + tree[m].Freq;
            depth[node] = (unsigned char)((depth[n] >= depth[m] ? depth[n] : depth[m]) + 1);
            tree[n].Dad = tree[m].Dad = (unsigned short)node;

            /* and insert the new node in the heap */
            huf_heap[SMALLEST] = node++;
            pqdownheap(tree, huf_heap, depth, SMALLEST);

        } while (huf_heap[0] >= 2);

        huf_heap[--(heap_max)] = huf_heap[SMALLEST];

        /* At this point, the fields freq and dad are set. We can now
        * generate the bit lengths.
        */
        gen_bitlen((tree_desc *)desc, huf_heap, heap_max, bl_count);

        /* The field len is now set, we can generate the bit codes */
        gen_codes ((ct_data *)tree, max_code, bl_count);
    }
    else if (huf_heap[0] == 0) {     /* no code at all, create a single dummy zero code */
        desc->max_code = 0;
        tree[0].Len = 0;               // gen_bitlen shortcut
        tree[0].Code = 0;              // gen_codes shortcut (probably useless)
    }
    else {                           /* only one code, create a single one bit code */
        const int *extra     = desc->stat_desc->extra_bits;
        int base             = desc->stat_desc->extra_base;
        int xbits;                     /* extra bits */
        unsigned short f;              /* frequency */

        desc->max_code = max_code;
        for (n = 0; n < max_code; n++) {
            tree[n].Len = 0;
        }
        tree[max_code].Len = 1;        // gen_bitlen shortcut
        xbits = 0;
        if (max_code >= base) xbits = extra[max_code-base];
        f = tree[max_code].Freq;
        csize[0] += (unsigned long)f * (1 + xbits);
        if (stree) csize[1] += (unsigned long)f * (stree[max_code].Len + xbits);
        tree[max_code].Code = 0;       // gen_codes shortcut, not set earlier since it replaces .Freq
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xaa0, %rsp            # imm = 0xAA0
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
movl $0xffffffff, -0x30(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x840(%rbp)
movl $0x203, -0x844(%rbp)    # imm = 0x203
movl $0x0, -0x2c(%rbp)
cmpl $0x203, -0x2c(%rbp)     # imm = 0x203
jge 0xbf71
movslq -0x2c(%rbp), %rax
movb $0x0, -0xa50(%rbp,%rax)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0xbf51
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0xbfde
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movzwl (%rax,%rcx,4), %eax
cmpl $0x0, %eax
je 0xbfc2
movl -0x840(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x840(%rbp)
movl -0x2c(%rbp), %ecx
movl %ecx, -0x30(%rbp)
movslq -0x840(%rbp), %rax
movl %ecx, -0x840(%rbp,%rax,4)
movslq -0x2c(%rbp), %rax
movb $0x0, -0xa50(%rbp,%rax)
jmp 0xbfd1
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movw $0x0, 0x2(%rax,%rcx,4)
jmp 0xbfd3
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0xbf78
cmpl $0x1, -0x840(%rbp)
jle 0xc20d
movl -0x30(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x8(%rax)
movl -0x840(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x2c(%rbp)
cmpl $0x1, -0x2c(%rbp)
jl 0xc031
movq -0x10(%rbp), %rdi
leaq -0x840(%rbp), %rsi
leaq -0xa50(%rbp), %rdx
movl -0x2c(%rbp), %ecx
callq 0xddd0
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0xc006
movl -0x1c(%rbp), %eax
movl %eax, -0xa54(%rbp)
movl -0x83c(%rbp), %eax
movl %eax, -0x2c(%rbp)
movl -0x840(%rbp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, -0x840(%rbp)
cltq
movl -0x840(%rbp,%rax,4), %eax
movl %eax, -0x83c(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x840(%rbp), %rsi
leaq -0xa50(%rbp), %rdx
movl $0x1, %ecx
callq 0xddd0
movl -0x83c(%rbp), %eax
movl %eax, -0xa84(%rbp)
movl -0x2c(%rbp), %ecx
movl -0x844(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x844(%rbp)
cltq
movl %ecx, -0x840(%rbp,%rax,4)
movl -0xa84(%rbp), %ecx
movl -0x844(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x844(%rbp)
cltq
movl %ecx, -0x840(%rbp,%rax,4)
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movzwl (%rax,%rcx,4), %eax
movq -0x10(%rbp), %rcx
movslq -0xa84(%rbp), %rdx
movzwl (%rcx,%rdx,4), %ecx
addl %ecx, %eax
movw %ax, %dx
movq -0x10(%rbp), %rax
movslq -0xa54(%rbp), %rcx
movw %dx, (%rax,%rcx,4)
movslq -0x2c(%rbp), %rax
movzbl -0xa50(%rbp,%rax), %eax
movslq -0xa84(%rbp), %rcx
movzbl -0xa50(%rbp,%rcx), %ecx
cmpl %ecx, %eax
jl 0xc126
movslq -0x2c(%rbp), %rax
movzbl -0xa50(%rbp,%rax), %eax
movl %eax, -0xaa0(%rbp)
jmp 0xc13b
movslq -0xa84(%rbp), %rax
movzbl -0xa50(%rbp,%rax), %eax
movl %eax, -0xaa0(%rbp)
movl -0xaa0(%rbp), %eax
addl $0x1, %eax
movb %al, %cl
movslq -0xa54(%rbp), %rax
movb %cl, -0xa50(%rbp,%rax)
movl -0xa54(%rbp), %eax
movw %ax, %dx
movq -0x10(%rbp), %rax
movslq -0xa84(%rbp), %rcx
movw %dx, 0x2(%rax,%rcx,4)
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movw %dx, 0x2(%rax,%rcx,4)
movl -0xa54(%rbp), %eax
movl %eax, %ecx
addl $0x1, %ecx
movl %ecx, -0xa54(%rbp)
movl %eax, -0x83c(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x840(%rbp), %rsi
leaq -0xa50(%rbp), %rdx
movl $0x1, %ecx
callq 0xddd0
cmpl $0x2, -0x840(%rbp)
jge 0xc03a
movl -0x83c(%rbp), %ecx
movl -0x844(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x844(%rbp)
cltq
movl %ecx, -0x840(%rbp,%rax,4)
movq -0x8(%rbp), %rdi
leaq -0x840(%rbp), %rsi
movl -0x844(%rbp), %edx
leaq -0xa80(%rbp), %rcx
callq 0xdf60
movq -0x10(%rbp), %rdi
movl -0x30(%rbp), %esi
leaq -0xa80(%rbp), %rdx
callq 0xe270
jmp 0xc34a
cmpl $0x0, -0x840(%rbp)
jne 0xc239
movq -0x8(%rbp), %rax
movl $0x0, 0x8(%rax)
movq -0x10(%rbp), %rax
movw $0x0, 0x2(%rax)
movq -0x10(%rbp), %rax
movw $0x0, (%rax)
jmp 0xc348
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0xa90(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movl 0x10(%rax), %eax
movl %eax, -0xa94(%rbp)
movl -0x30(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x8(%rax)
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0xc290
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movw $0x0, 0x2(%rax,%rcx,4)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0xc26e
movq -0x10(%rbp), %rax
movslq -0x30(%rbp), %rcx
movw $0x1, 0x2(%rax,%rcx,4)
movl $0x0, -0xa98(%rbp)
movl -0x30(%rbp), %eax
cmpl -0xa94(%rbp), %eax
jl 0xc2d0
movq -0xa90(%rbp), %rax
movl -0x30(%rbp), %ecx
subl -0xa94(%rbp), %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0xa98(%rbp)
movq -0x10(%rbp), %rax
movslq -0x30(%rbp), %rcx
movw (%rax,%rcx,4), %ax
movw %ax, -0xa9a(%rbp)
movzwl -0xa9a(%rbp), %eax
movl %eax, %ecx
movl -0xa98(%rbp), %eax
addl $0x1, %eax
cltq
imulq %rax, %rcx
movq -0x28(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
cmpq $0x0, -0x18(%rbp)
je 0xc33a
movzwl -0xa9a(%rbp), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
movslq -0x30(%rbp), %rdx
movzwl 0x2(%rax,%rdx,4), %eax
addl -0xa98(%rbp), %eax
cltq
imulq %rax, %rcx
movq -0x28(%rbp), %rax
addq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rax
movslq -0x30(%rbp), %rcx
movw $0x0, (%rax,%rcx,4)
jmp 0xc34a
addq $0xaa0, %rsp            # imm = 0xAA0
popq %rbp
retq
nopw %cs:(%rax,%rax)