// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/jpeg/jchuff.c
// Function: jpeg_gen_optimal_table
GLOBAL(void)
jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])
{
#define MAX_CLEN 32		/* assumed maximum initial code length */
  UINT8 bits[MAX_CLEN+1];	/* bits[k] = # of symbols with code length k */
  int codesize[257];		/* codesize[k] = code length of symbol k */
  int others[257];		/* next symbol in current branch of tree */
  int c1, c2;
  int p, i, j;
  long v;

  /* This algorithm is explained in section K.2 of the JPEG standard */

  MEMZERO(bits, SIZEOF(bits));
  MEMZERO(codesize, SIZEOF(codesize));
  for (i = 0; i < 257; i++)
    others[i] = -1;		/* init links to empty */
  
  freq[256] = 1;		/* make sure 256 has a nonzero count */
  /* Including the pseudo-symbol 256 in the Huffman procedure guarantees
   * that no real symbol is given code-value of all ones, because 256
   * will be placed last in the largest codeword category.
   */

  /* Huffman's basic algorithm to assign optimal code lengths to symbols */

  for (;;) {
    /* Find the smallest nonzero frequency, set c1 = its symbol */
    /* In case of ties, take the larger symbol number */
    c1 = -1;
    v = 1000000000L;
    for (i = 0; i <= 256; i++) {
      if (freq[i] && freq[i] <= v) {
	v = freq[i];
	c1 = i;
      }
    }

    /* Find the next smallest nonzero frequency, set c2 = its symbol */
    /* In case of ties, take the larger symbol number */
    c2 = -1;
    v = 1000000000L;
    for (i = 0; i <= 256; i++) {
      if (freq[i] && freq[i] <= v && i != c1) {
	v = freq[i];
	c2 = i;
      }
    }

    /* Done if we've merged everything into one frequency */
    if (c2 < 0)
      break;
    
    /* Else merge the two counts/trees */
    freq[c1] += freq[c2];
    freq[c2] = 0;

    /* Increment the codesize of everything in c1's tree branch */
    codesize[c1]++;
    while (others[c1] >= 0) {
      c1 = others[c1];
      codesize[c1]++;
    }
    
    others[c1] = c2;		/* chain c2 onto c1's tree branch */
    
    /* Increment the codesize of everything in c2's tree branch */
    codesize[c2]++;
    while (others[c2] >= 0) {
      c2 = others[c2];
      codesize[c2]++;
    }
  }

  /* Now count the number of symbols of each code length */
  for (i = 0; i <= 256; i++) {
    if (codesize[i]) {
      /* The JPEG standard seems to think that this can't happen, */
      /* but I'm paranoid... */
      if (codesize[i] > MAX_CLEN)
	ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW);

      bits[codesize[i]]++;
    }
  }

  /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
   * Huffman procedure assigned any such lengths, we must adjust the coding.
   * Here is what the JPEG spec says about how this next bit works:
   * Since symbols are paired for the longest Huffman code, the symbols are
   * removed from this length category two at a time.  The prefix for the pair
   * (which is one bit shorter) is allocated to one of the pair; then,
   * skipping the BITS entry for that prefix length, a code word from the next
   * shortest nonzero BITS entry is converted into a prefix for two code words
   * one bit longer.
   */
  
  for (i = MAX_CLEN; i > 16; i--) {
    while (bits[i] > 0) {
      j = i - 2;		/* find length of new prefix to be used */
      while (bits[j] == 0)
	j--;
      
      bits[i] -= 2;		/* remove two symbols */
      bits[i-1]++;		/* one goes in this length */
      bits[j+1] += 2;		/* two new symbols in this length */
      bits[j]--;		/* symbol of this length is now a prefix */
    }
  }

  /* Remove the count for the pseudo-symbol 256 from the largest codelength */
  while (bits[i] == 0)		/* find largest codelength still in use */
    i--;
  bits[i]--;
  
  /* Return final symbol counts (only for lengths 0..16) */
  MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits));
  
  /* Return a list of the symbols sorted by code length */
  /* It's not real clear to me why we don't need to consider the codelength
   * changes made above, but the JPEG spec seems to think this works.
   */
  p = 0;
  for (i = 1; i <= MAX_CLEN; i++) {
    for (j = 0; j <= 255; j++) {
      if (codesize[j] == i) {
	htbl->huffval[p] = (UINT8) j;
	p++;
      }
    }
  }

  /* Set sent_table FALSE so updated table will be written to JPEG file. */
  htbl->sent_table = FALSE;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x848, %rsp            # imm = 0x848
movq %rdx, %r15
movq %rsi, %rbx
movq %rdi, %r14
xorps %xmm0, %xmm0
movaps %xmm0, (%rsp)
movaps %xmm0, 0x10(%rsp)
movb $0x0, 0x20(%rsp)
leaq 0x30(%rsp), %rdi
xorl %r12d, %r12d
movl $0x404, %edx            # imm = 0x404
xorl %esi, %esi
callq 0xe260
leaq 0x440(%rsp), %rdi
movl $0x404, %edx            # imm = 0x404
movl $0xff, %esi
callq 0xe260
movq $0x1, 0x800(%r15)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl $0x3b9aca00, %ecx       # imm = 0x3B9ACA00
movq (%r15,%r12,8), %rdx
testq %rdx, %rdx
sete %sil
cmpq %rcx, %rdx
setg %dil
orb %sil, %dil
cmovel %r12d, %eax
cmoveq %rdx, %rcx
incq %r12
cmpq $0x101, %r12            # imm = 0x101
jne 0x76dc7
movl %eax, %edx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movl $0x3b9aca00, %edi       # imm = 0x3B9ACA00
xorl %esi, %esi
movq (%r15,%rsi,8), %r8
testq %r8, %r8
sete %r9b
cmpq %rdi, %r8
setg %r10b
cmpq %rsi, %rdx
sete %r11b
orb %r9b, %r11b
orb %r10b, %r11b
jne 0x76e24
movl %esi, %ecx
movq %r8, %rdi
incq %rsi
cmpq $0x101, %rsi            # imm = 0x101
jne 0x76dfe
testl %ecx, %ecx
js 0x76e9e
movl %ecx, %edx
movq (%r15,%rdx,8), %rsi
cltq
addq %rsi, (%r15,%rax,8)
movq $0x0, (%r15,%rdx,8)
incl 0x30(%rsp,%rax,4)
movl 0x440(%rsp,%rax,4), %esi
testl %esi, %esi
js 0x76e5b
movl %esi, %eax
jmp 0x76e48
movl %ecx, 0x440(%rsp,%rax,4)
incl 0x30(%rsp,%rdx,4)
movl 0x440(%rsp,%rdx,4), %edx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl $0x3b9aca00, %ecx       # imm = 0x3B9ACA00
movl $0x0, %r12d
testl %edx, %edx
js 0x76dc7
movl %edx, %edx
incl 0x30(%rsp,%rdx,4)
movl 0x440(%rsp,%rdx,4), %edx
testl %edx, %edx
jns 0x76e85
xorl %r12d, %r12d
jmp 0x76dc7
xorl %r15d, %r15d
movslq 0x30(%rsp,%r15,4), %r12
testq %r12, %r12
je 0x76ec4
cmpl $0x21, %r12d
jl 0x76ec0
movq (%r14), %rax
movl $0x27, 0x28(%rax)
movq %r14, %rdi
callq *(%rax)
incb (%rsp,%r12)
incq %r15
cmpq $0x101, %r15            # imm = 0x101
jne 0x76ea1
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
movl $0x20, %esi
movabsq $0x2000000000, %rcx     # imm = 0x2000000000
leaq 0x1f(%rsp), %rdx
movb (%rsp,%rsi), %dil
testb %dil, %dil
je 0x76f25
movq %rcx, %r8
movq %rdx, %r9
addq %rax, %r8
cmpb $0x0, -0x1(%r9)
leaq -0x1(%r9), %r9
je 0x76efd
addb $-0x2, %dil
movb %dil, (%rsp,%rsi)
incb -0x1(%rsp,%rsi)
sarq $0x20, %r8
addb $0x2, (%rsp,%r8)
decb (%r9)
jmp 0x76eee
leaq -0x1(%rsi), %rdi
decq %rdx
addq %rax, %rcx
cmpq $0x11, %rsi
movq %rdi, %rsi
ja 0x76eee
leaq 0x11(%rsp), %rax
movb -0x1(%rax), %cl
decq %rax
testb %cl, %cl
je 0x76f3d
decb %cl
movb %cl, (%rax)
movb 0x10(%rsp), %al
movb %al, 0x10(%rbx)
movaps (%rsp), %xmm0
movups %xmm0, (%rbx)
xorl %eax, %eax
movl $0x1, %ecx
xorl %edx, %edx
cmpl %ecx, 0x30(%rsp,%rdx,4)
jne 0x76f70
cltq
movb %dl, 0x11(%rbx,%rax)
incl %eax
incq %rdx
cmpq $0x100, %rdx            # imm = 0x100
jne 0x76f62
incl %ecx
cmpl $0x21, %ecx
jne 0x76f60
movl $0x0, 0x114(%rbx)
addq $0x848, %rsp            # imm = 0x848
popq %rbx
popq %r12
popq %r14
popq %r15
retq