// File: tomfunkhouser[P]gaps/pkgs/jpeg/jchuff.c
// Function: jpeg_make_c_derived_tbl
GLOBAL(void)
jpeg_make_c_derived_tbl (j_compress_ptr cinfo, jboolean isDC, int tblno,
			 c_derived_tbl ** pdtbl)
{
  JHUFF_TBL *htbl;
  c_derived_tbl *dtbl;
  int p, i, l, lastp, si, maxsymbol;
  char huffsize[257];
  unsigned int huffcode[257];
  unsigned int code;

  /* Note that huffsize[] and huffcode[] are filled in code-length order,
   * paralleling the order of the symbols themselves in htbl->huffval[].
   */

  /* Find the input Huffman table */
  if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
  htbl =
    isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
  if (htbl == NULL)
    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);

  /* Allocate a workspace if we haven't already done so. */
  if (*pdtbl == NULL)
    *pdtbl = (c_derived_tbl *)
      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
				  SIZEOF(c_derived_tbl));
  dtbl = *pdtbl;
  
  /* Figure C.1: make table of Huffman code length for each symbol */

  p = 0;
  for (l = 1; l <= 16; l++) {
    i = (int) htbl->bits[l];
    if (i < 0 || p + i > 256)	/* protect against table overrun */
      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
    while (i--)
      huffsize[p++] = (char) l;
  }
  huffsize[p] = 0;
  lastp = p;
  
  /* Figure C.2: generate the codes themselves */
  /* We also validate that the counts represent a legal Huffman code tree. */

  code = 0;
  si = huffsize[0];
  p = 0;
  while (huffsize[p]) {
    while (((int) huffsize[p]) == si) {
      huffcode[p++] = code;
      code++;
    }
    /* code is now 1 more than the last code used for codelength si; but
     * it must still fit in si bits, since no code is allowed to be all ones.
     */
    if (((INT32) code) >= (((INT32) 1) << si))
      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
    code <<= 1;
    si++;
  }
  
  /* Figure C.3: generate encoding tables */
  /* These are code and size indexed by symbol value */

  /* Set all codeless symbols to have code length 0;
   * this lets us detect duplicate VAL entries here, and later
   * allows emit_bits to detect any attempt to emit such symbols.
   */
  MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi));

  /* This is also a convenient place to check for out-of-range
   * and duplicated VAL entries.  We allow 0..255 for AC symbols
   * but only 0..15 for DC.  (We could constrain them further
   * based on data depth and mode, but this seems enough.)
   */
  maxsymbol = isDC ? 15 : 255;

  for (p = 0; p < lastp; p++) {
    i = htbl->huffval[p];
    if (i < 0 || i > maxsymbol || dtbl->ehufsi[i])
      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
    dtbl->ehufco[i] = huffcode[p];
    dtbl->ehufsi[i] = huffsize[p];
  }
}

// Assembly:
subq $0x568, %rsp            # imm = 0x568
movq %rdi, 0x560(%rsp)
movl %esi, 0x55c(%rsp)
movl %edx, 0x558(%rsp)
movq %rcx, 0x550(%rsp)
cmpl $0x0, 0x558(%rsp)
jl 0xdd459
cmpl $0x4, 0x558(%rsp)
jl 0xdd498
movq 0x560(%rsp), %rax
movq (%rax), %rax
movl $0x32, 0x28(%rax)
movl 0x558(%rsp), %ecx
movq 0x560(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0x560(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x560(%rsp), %rdi
callq *%rax
cmpl $0x0, 0x55c(%rsp)
je 0xdd4c0
movq 0x560(%rsp), %rax
movslq 0x558(%rsp), %rcx
movq 0x80(%rax,%rcx,8), %rax
movq %rax, (%rsp)
jmp 0xdd4dc
movq 0x560(%rsp), %rax
movslq 0x558(%rsp), %rcx
movq 0xa0(%rax,%rcx,8), %rax
movq %rax, (%rsp)
movq (%rsp), %rax
movq %rax, 0x548(%rsp)
cmpq $0x0, 0x548(%rsp)
jne 0xdd532
movq 0x560(%rsp), %rax
movq (%rax), %rax
movl $0x32, 0x28(%rax)
movl 0x558(%rsp), %ecx
movq 0x560(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x2c(%rax)
movq 0x560(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x560(%rsp), %rdi
callq *%rax
movq 0x550(%rsp), %rax
cmpq $0x0, (%rax)
jne 0xdd571
movq 0x560(%rsp), %rax
movq 0x8(%rax), %rax
movq (%rax), %rax
movq 0x560(%rsp), %rdi
movl $0x1, %esi
movl $0x500, %edx            # imm = 0x500
callq *%rax
movq %rax, %rcx
movq 0x550(%rsp), %rax
movq %rcx, (%rax)
movq 0x550(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x540(%rsp)
movl $0x0, 0x53c(%rsp)
movl $0x1, 0x534(%rsp)
cmpl $0x10, 0x534(%rsp)
jg 0xdd665
movq 0x548(%rsp), %rax
movslq 0x534(%rsp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, 0x538(%rsp)
cmpl $0x0, 0x538(%rsp)
jl 0xdd5e2
movl 0x53c(%rsp), %eax
addl 0x538(%rsp), %eax
cmpl $0x100, %eax            # imm = 0x100
jle 0xdd60c
movq 0x560(%rsp), %rax
movq (%rax), %rax
movl $0x8, 0x28(%rax)
movq 0x560(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x560(%rsp), %rdi
callq *%rax
jmp 0xdd60e
movl 0x538(%rsp), %eax
movl %eax, %ecx
addl $-0x1, %ecx
movl %ecx, 0x538(%rsp)
cmpl $0x0, %eax
je 0xdd64d
movl 0x534(%rsp), %eax
movb %al, %cl
movl 0x53c(%rsp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x53c(%rsp)
cltq
movb %cl, 0x420(%rsp,%rax)
jmp 0xdd60e
jmp 0xdd64f
movl 0x534(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x534(%rsp)
jmp 0xdd59a
movslq 0x53c(%rsp), %rax
movb $0x0, 0x420(%rsp,%rax)
movl 0x53c(%rsp), %eax
movl %eax, 0x530(%rsp)
movl $0x0, 0xc(%rsp)
movsbl 0x420(%rsp), %eax
movl %eax, 0x52c(%rsp)
movl $0x0, 0x53c(%rsp)
movslq 0x53c(%rsp), %rax
cmpb $0x0, 0x420(%rsp,%rax)
je 0xdd765
jmp 0xdd6bd
movslq 0x53c(%rsp), %rax
movsbl 0x420(%rsp,%rax), %eax
cmpl 0x52c(%rsp), %eax
jne 0xdd700
movl 0xc(%rsp), %ecx
movl 0x53c(%rsp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x53c(%rsp)
cltq
movl %ecx, 0x10(%rsp,%rax,4)
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0xdd6bd
movl 0xc(%rsp), %eax
movl 0x52c(%rsp), %ecx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
cmpq %rcx, %rax
jl 0xdd745
movq 0x560(%rsp), %rax
movq (%rax), %rax
movl $0x8, 0x28(%rax)
movq 0x560(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x560(%rsp), %rdi
callq *%rax
movl 0xc(%rsp), %eax
shll %eax
movl %eax, 0xc(%rsp)
movl 0x52c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x52c(%rsp)
jmp 0xdd6a5
movq 0x540(%rsp), %rdi
addq $0x400, %rdi            # imm = 0x400
xorl %esi, %esi
movl $0x100, %edx            # imm = 0x100
callq 0xf280
movl 0x55c(%rsp), %edx
movl $0xff, %eax
movl $0xf, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movl %eax, 0x528(%rsp)
movl $0x0, 0x53c(%rsp)
movl 0x53c(%rsp), %eax
cmpl 0x530(%rsp), %eax
jge 0xdd895
movq 0x548(%rsp), %rax
movslq 0x53c(%rsp), %rcx
movzbl 0x11(%rax,%rcx), %eax
movl %eax, 0x538(%rsp)
cmpl $0x0, 0x538(%rsp)
jl 0xdd810
movl 0x538(%rsp), %eax
cmpl 0x528(%rsp), %eax
jg 0xdd810
movq 0x540(%rsp), %rax
movslq 0x538(%rsp), %rcx
movsbl 0x400(%rax,%rcx), %eax
cmpl $0x0, %eax
je 0xdd83a
movq 0x560(%rsp), %rax
movq (%rax), %rax
movl $0x8, 0x28(%rax)
movq 0x560(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x560(%rsp), %rdi
callq *%rax
movslq 0x53c(%rsp), %rax
movl 0x10(%rsp,%rax,4), %edx
movq 0x540(%rsp), %rax
movslq 0x538(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
movslq 0x53c(%rsp), %rax
movb 0x420(%rsp,%rax), %dl
movq 0x540(%rsp), %rax
movslq 0x538(%rsp), %rcx
movb %dl, 0x400(%rax,%rcx)
movl 0x53c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x53c(%rsp)
jmp 0xdd7a9
addq $0x568, %rsp            # imm = 0x568
retq
nopl (%rax)