// File: /workspace/github_cpp_makefile_star2_O2/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 0xe270
cmpq $0x101, %r12            # imm = 0x101
je 0x6c67e
orl $-0x1, 0x440(%rsp,%r12,4)
incq %r12
jmp 0x6c667
movq $0x1, 0x800(%r15)
movl $0x3b9aca00, %edx       # imm = 0x3B9ACA00
pushq $-0x1
popq %rax
xorl %esi, %esi
movl %eax, %ecx
movl %ecx, %ecx
cmpq $0x101, %rsi            # imm = 0x101
je 0x6c6c1
movq (%r15,%rsi,8), %rdi
testq %rdi, %rdi
sete %r8b
cmpq %rdx, %rdi
setg %r9b
orb %r8b, %r9b
cmovel %esi, %ecx
cmoveq %rdi, %rdx
incq %rsi
jmp 0x6c695
movl $0x3b9aca00, %edi       # imm = 0x3B9ACA00
xorl %esi, %esi
movl %eax, %edx
cmpq $0x101, %rsi            # imm = 0x101
je 0x6c6fe
movq (%r15,%rsi,8), %r8
testq %r8, %r8
sete %r9b
cmpq %rdi, %r8
setg %r10b
cmpq %rsi, %rcx
sete %r11b
orb %r9b, %r11b
orb %r10b, %r11b
jne 0x6c6f9
movl %esi, %edx
movq %r8, %rdi
incq %rsi
jmp 0x6c6ca
testl %edx, %edx
js 0x6c751
movl %edx, %esi
movq (%r15,%rsi,8), %r8
movslq %ecx, %rdi
addq %r8, (%r15,%rdi,8)
andq $0x0, (%r15,%rsi,8)
incl 0x30(%rsp,%rdi,4)
movslq %ecx, %r8
movslq 0x440(%rsp,%r8,4), %rdi
movl %edi, %ecx
testq %rdi, %rdi
jns 0x6c714
movl %edx, 0x440(%rsp,%r8,4)
incl 0x30(%rsp,%rsi,4)
movl %edx, %ecx
movslq 0x440(%rsp,%rcx,4), %rsi
movl %esi, %edx
testq %rsi, %rsi
jns 0x6c732
movl $0x3b9aca00, %edx       # imm = 0x3B9ACA00
jmp 0x6c691
xorl %r15d, %r15d
cmpq $0x101, %r15            # imm = 0x101
je 0x6c785
movslq 0x30(%rsp,%r15,4), %r12
testq %r12, %r12
je 0x6c780
cmpl $0x21, %r12d
jl 0x6c77c
movq (%r14), %rax
movl $0x27, 0x28(%rax)
movq %r14, %rdi
callq *(%rax)
incb (%rsp,%r12)
incq %r15
jmp 0x6c754
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
pushq $0x20
popq %rsi
movabsq $0x2000000000, %rcx     # imm = 0x2000000000
leaq 0x1f(%rsp), %rdx
cmpq $0x10, %rsi
jbe 0x6c7ed
leaq -0x1(%rsi), %rdi
movb (%rsp,%rsi), %r8b
testb %r8b, %r8b
je 0x6c7e2
movq %rcx, %r9
movq %rdx, %r10
addq %rax, %r9
cmpb $0x0, -0x1(%r10)
leaq -0x1(%r10), %r10
je 0x6c7ba
addb $-0x2, %r8b
movb %r8b, (%rsp,%rsi)
incb -0x1(%rsp,%rsi)
sarq $0x20, %r9
addb $0x2, (%rsp,%r9)
decb (%r10)
jmp 0x6c7ab
decq %rdx
addq %rax, %rcx
movq %rdi, %rsi
jmp 0x6c7a1
leaq 0x11(%rsp), %rax
movb -0x1(%rax), %cl
decq %rax
testb %cl, %cl
je 0x6c7f2
decb %cl
movb %cl, (%rax)
movb 0x10(%rsp), %al
movb %al, 0x10(%rbx)
movaps (%rsp), %xmm0
movups %xmm0, (%rbx)
pushq $0x1
popq %rax
xorl %ecx, %ecx
cmpl $0x21, %eax
je 0x6c83b
xorl %edx, %edx
cmpq $0x100, %rdx            # imm = 0x100
je 0x6c837
cmpl %eax, 0x30(%rsp,%rdx,4)
jne 0x6c832
movslq %ecx, %rcx
movb %dl, 0x11(%rbx,%rcx)
incl %ecx
incq %rdx
jmp 0x6c81a
incl %eax
jmp 0x6c813
andl $0x0, 0x114(%rbx)
addq $0x848, %rsp            # imm = 0x848
popq %rbx
popq %r12
popq %r14
popq %r15
retq