// File: tomfunkhouser[P]gaps/pkgs/png/trees.c
// Function: gen_bitlen
local void gen_bitlen(s, desc)
    deflate_state *s;
    tree_desc *desc;    /* the tree descriptor */
{
    ct_data *tree        = desc->dyn_tree;
    int max_code         = desc->max_code;
    const ct_data *stree = desc->stat_desc->static_tree;
    const intf *extra    = desc->stat_desc->extra_bits;
    int base             = desc->stat_desc->extra_base;
    int max_length       = desc->stat_desc->max_length;
    int h;              /* heap index */
    int n, m;           /* iterate over the tree elements */
    int bits;           /* bit length */
    int xbits;          /* extra bits */
    ush f;              /* frequency */
    int overflow = 0;   /* number of elements with bit length too large */

    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;

    /* In a first pass, compute the optimal bit lengths (which may
     * overflow in the case of the bit length tree).
     */
    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */

    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
        n = s->heap[h];
        bits = tree[tree[n].Dad].Len + 1;
        if (bits > max_length) bits = max_length, overflow++;
        tree[n].Len = (ush)bits;
        /* We overwrite tree[n].Dad which is no longer needed */

        if (n > max_code) continue; /* not a leaf node */

        s->bl_count[bits]++;
        xbits = 0;
        if (n >= base) xbits = extra[n-base];
        f = tree[n].Freq;
        s->opt_len += (ulg)f * (bits + xbits);
        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
    }
    if (overflow == 0) return;

    Trace((stderr,"\nbit length overflow\n"));
    /* This happens for example on obj2 and pic of the Calgary corpus */

    /* Find the first bit length which could increase: */
    do {
        bits = max_length-1;
        while (s->bl_count[bits] == 0) bits--;
        s->bl_count[bits]--;      /* move one leaf down the tree */
        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
        s->bl_count[max_length]--;
        /* The brother of the overflow item also moves one step up,
         * but this does not affect bl_count[max_length]
         */
        overflow -= 2;
    } while (overflow > 0);

    /* Now recompute all bit lengths, scanning in increasing frequency.
     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
     * lengths instead of fixing only the wrong ones. This idea is taken
     * from 'ar' written by Haruhiko Okumura.)
     */
    for (bits = max_length; bits != 0; bits--) {
        n = s->bl_count[bits];
        while (n != 0) {
            m = s->heap[--h];
            if (m > max_code) continue;
            if ((unsigned) tree[m].Len != (unsigned) bits) {
                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
                s->opt_len += ((long)bits - (long)tree[m].Len)
                              *(long)tree[m].Freq;
                tree[m].Len = (ush)bits;
            }
            n--;
        }
    }
}

// Assembly:
movq %rdi, -0x8(%rsp)
movq %rsi, -0x10(%rsp)
movq -0x10(%rsp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rsp)
movq -0x10(%rsp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x1c(%rsp)
movq -0x10(%rsp), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq %rax, -0x28(%rsp)
movq -0x10(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rsp)
movq -0x10(%rsp), %rax
movq 0x10(%rax), %rax
movl 0x10(%rax), %eax
movl %eax, -0x34(%rsp)
movq -0x10(%rsp), %rax
movq 0x10(%rax), %rax
movl 0x18(%rax), %eax
movl %eax, -0x38(%rsp)
movl $0x0, -0x54(%rsp)
movl $0x0, -0x48(%rsp)
cmpl $0xf, -0x48(%rsp)
jg 0x1215ae
movq -0x8(%rsp), %rax
movslq -0x48(%rsp), %rcx
movw $0x0, 0xb90(%rax,%rcx,2)
movl -0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rsp)
jmp 0x121586
movq -0x18(%rsp), %rax
movq -0x8(%rsp), %rcx
movq -0x8(%rsp), %rdx
movslq 0x14a8(%rdx), %rdx
movslq 0xbb0(%rcx,%rdx,4), %rcx
movw $0x0, 0x2(%rax,%rcx,4)
movq -0x8(%rsp), %rax
movl 0x14a8(%rax), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rsp)
cmpl $0x23d, -0x3c(%rsp)     # imm = 0x23D
jge 0x121739
movq -0x8(%rsp), %rax
movslq -0x3c(%rsp), %rcx
movl 0xbb0(%rax,%rcx,4), %eax
movl %eax, -0x40(%rsp)
movq -0x18(%rsp), %rax
movq -0x18(%rsp), %rcx
movslq -0x40(%rsp), %rdx
movzwl 0x2(%rcx,%rdx,4), %ecx
movzwl 0x2(%rax,%rcx,4), %eax
addl $0x1, %eax
movl %eax, -0x48(%rsp)
movl -0x48(%rsp), %eax
cmpl -0x38(%rsp), %eax
jle 0x121645
movl -0x38(%rsp), %eax
movl %eax, -0x48(%rsp)
movl -0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rsp)
movl -0x48(%rsp), %eax
movw %ax, %dx
movq -0x18(%rsp), %rax
movslq -0x40(%rsp), %rcx
movw %dx, 0x2(%rax,%rcx,4)
movl -0x40(%rsp), %eax
cmpl -0x1c(%rsp), %eax
jle 0x12166a
jmp 0x121729
movq -0x8(%rsp), %rax
movslq -0x48(%rsp), %rcx
movw 0xb90(%rax,%rcx,2), %dx
addw $0x1, %dx
movw %dx, 0xb90(%rax,%rcx,2)
movl $0x0, -0x4c(%rsp)
movl -0x40(%rsp), %eax
cmpl -0x34(%rsp), %eax
jl 0x1216b1
movq -0x30(%rsp), %rax
movl -0x40(%rsp), %ecx
subl -0x34(%rsp), %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x4c(%rsp)
movq -0x18(%rsp), %rax
movslq -0x40(%rsp), %rcx
movw (%rax,%rcx,4), %ax
movw %ax, -0x4e(%rsp)
movzwl -0x4e(%rsp), %eax
movl %eax, %ecx
movl -0x48(%rsp), %eax
addl -0x4c(%rsp), %eax
cltq
imulq %rax, %rcx
movq -0x8(%rsp), %rax
addq 0x1708(%rax), %rcx
movq %rcx, 0x1708(%rax)
cmpq $0x0, -0x28(%rsp)
je 0x121727
movzwl -0x4e(%rsp), %eax
movl %eax, %ecx
movq -0x28(%rsp), %rax
movslq -0x40(%rsp), %rdx
movzwl 0x2(%rax,%rdx,4), %eax
addl -0x4c(%rsp), %eax
cltq
imulq %rax, %rcx
movq -0x8(%rsp), %rax
addq 0x1710(%rax), %rcx
movq %rcx, 0x1710(%rax)
jmp 0x121729
movl -0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rsp)
jmp 0x1215e5
cmpl $0x0, -0x54(%rsp)
jne 0x121745
jmp 0x1218d1
jmp 0x121747
movl -0x38(%rsp), %eax
subl $0x1, %eax
movl %eax, -0x48(%rsp)
movq -0x8(%rsp), %rax
movslq -0x48(%rsp), %rcx
movzwl 0xb90(%rax,%rcx,2), %eax
cmpl $0x0, %eax
jne 0x121776
movl -0x48(%rsp), %eax
addl $-0x1, %eax
movl %eax, -0x48(%rsp)
jmp 0x121752
movq -0x8(%rsp), %rax
movslq -0x48(%rsp), %rcx
movw 0xb90(%rax,%rcx,2), %dx
addw $-0x1, %dx
movw %dx, 0xb90(%rax,%rcx,2)
movq -0x8(%rsp), %rax
movl -0x48(%rsp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movzwl 0xb90(%rax,%rcx,2), %edx
addl $0x2, %edx
movw %dx, 0xb90(%rax,%rcx,2)
movq -0x8(%rsp), %rax
movslq -0x38(%rsp), %rcx
movw 0xb90(%rax,%rcx,2), %dx
addw $-0x1, %dx
movw %dx, 0xb90(%rax,%rcx,2)
movl -0x54(%rsp), %eax
subl $0x2, %eax
movl %eax, -0x54(%rsp)
cmpl $0x0, -0x54(%rsp)
jg 0x121747
movl -0x38(%rsp), %eax
movl %eax, -0x48(%rsp)
cmpl $0x0, -0x48(%rsp)
je 0x1218d1
movq -0x8(%rsp), %rax
movslq -0x48(%rsp), %rcx
movzwl 0xb90(%rax,%rcx,2), %eax
movl %eax, -0x40(%rsp)
cmpl $0x0, -0x40(%rsp)
je 0x1218bf
movq -0x8(%rsp), %rax
movl -0x3c(%rsp), %ecx
addl $-0x1, %ecx
movl %ecx, -0x3c(%rsp)
movslq %ecx, %rcx
movl 0xbb0(%rax,%rcx,4), %eax
movl %eax, -0x44(%rsp)
movl -0x44(%rsp), %eax
cmpl -0x1c(%rsp), %eax
jle 0x121848
jmp 0x121813
movq -0x18(%rsp), %rax
movslq -0x44(%rsp), %rcx
movzwl 0x2(%rax,%rcx,4), %eax
cmpl -0x48(%rsp), %eax
je 0x1218af
movslq -0x48(%rsp), %rcx
movq -0x18(%rsp), %rax
movslq -0x44(%rsp), %rdx
movzwl 0x2(%rax,%rdx,4), %eax
subq %rax, %rcx
movq -0x18(%rsp), %rax
movslq -0x44(%rsp), %rdx
movzwl (%rax,%rdx,4), %eax
imulq %rax, %rcx
movq -0x8(%rsp), %rax
addq 0x1708(%rax), %rcx
movq %rcx, 0x1708(%rax)
movl -0x48(%rsp), %eax
movw %ax, %dx
movq -0x18(%rsp), %rax
movslq -0x44(%rsp), %rcx
movw %dx, 0x2(%rax,%rcx,4)
movl -0x40(%rsp), %eax
addl $-0x1, %eax
movl %eax, -0x40(%rsp)
jmp 0x121813
jmp 0x1218c1
movl -0x48(%rsp), %eax
addl $-0x1, %eax
movl %eax, -0x48(%rsp)
jmp 0x1217f2
retq
nopw %cs:(%rax,%rax)