// File: tomfunkhouser[P]gaps/pkgs/jpeg/jchuff.c
// Function: encode_one_block
LOCAL(jboolean)
encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
		  c_derived_tbl *dctbl, c_derived_tbl *actbl)
{
  register int temp, temp2;
  register int nbits;
  register int k, r, i;
  
  /* Encode the DC coefficient difference per section F.1.2.1 */
  
  temp = temp2 = block[0] - last_dc_val;

  if (temp < 0) {
    temp = -temp;		/* temp is abs value of input */
    /* For a negative input, want temp2 = bitwise complement of abs(input) */
    /* This code assumes we are on a two's complement machine */
    temp2--;
  }
  
  /* Find the number of bits needed for the magnitude of the coefficient */
  nbits = 0;
  while (temp) {
    nbits++;
    temp >>= 1;
  }
  /* Check for out-of-range coefficient values.
   * Since we're encoding a difference, the range limit is twice as much.
   */
  if (nbits > MAX_COEF_BITS+1)
    ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
  
  /* Emit the Huffman-coded symbol for the number of bits */
  if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
    return FALSE;

  /* Emit that number of bits of the value, if positive, */
  /* or the complement of its magnitude, if negative. */
  if (nbits)			/* emit_bits rejects calls with size 0 */
    if (! emit_bits(state, (unsigned int) temp2, nbits))
      return FALSE;

  /* Encode the AC coefficients per section F.1.2.2 */
  
  r = 0;			/* r = run length of zeros */
  
  for (k = 1; k < DCTSIZE2; k++) {
    if ((temp = block[jpeg_natural_order[k]]) == 0) {
      r++;
    } else {
      /* if run length > 15, must emit special run-length-16 codes (0xF0) */
      while (r > 15) {
	if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
	  return FALSE;
	r -= 16;
      }

      temp2 = temp;
      if (temp < 0) {
	temp = -temp;		/* temp is abs value of input */
	/* This code assumes we are on a two's complement machine */
	temp2--;
      }
      
      /* Find the number of bits needed for the magnitude of the coefficient */
      nbits = 1;		/* there must be at least one 1 bit */
      while ((temp >>= 1))
	nbits++;
      /* Check for out-of-range coefficient values */
      if (nbits > MAX_COEF_BITS)
	ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
      
      /* Emit Huffman symbol for run length / number of bits */
      i = (r << 4) + nbits;
      if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i]))
	return FALSE;

      /* Emit that number of bits of the value, if positive, */
      /* or the complement of its magnitude, if negative. */
      if (! emit_bits(state, (unsigned int) temp2, nbits))
	return FALSE;
      
      r = 0;
    }
  }

  /* If the last coef(s) were zero, emit an end-of-block code */
  if (r > 0)
    if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0]))
      return FALSE;

  return TRUE;
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x38(%rsp)
movq %rsi, 0x30(%rsp)
movl %edx, 0x2c(%rsp)
movq %rcx, 0x20(%rsp)
movq %r8, 0x18(%rsp)
movq 0x30(%rsp), %rax
movswl (%rax), %eax
subl 0x2c(%rsp), %eax
movl %eax, 0x10(%rsp)
movl %eax, 0x14(%rsp)
cmpl $0x0, 0x14(%rsp)
jge 0xdea3c
xorl %eax, %eax
subl 0x14(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x10(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x10(%rsp)
movl $0x0, 0xc(%rsp)
cmpl $0x0, 0x14(%rsp)
je 0xdea62
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
movl 0x14(%rsp), %eax
sarl %eax
movl %eax, 0x14(%rsp)
jmp 0xdea44
cmpl $0xb, 0xc(%rsp)
jle 0xdea96
movq 0x38(%rsp), %rax
movq 0x30(%rax), %rax
movq (%rax), %rax
movl $0x6, 0x28(%rax)
movq 0x38(%rsp), %rax
movq 0x30(%rax), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x38(%rsp), %rcx
movq 0x30(%rcx), %rdi
callq *%rax
movq 0x38(%rsp), %rdi
movq 0x20(%rsp), %rax
movslq 0xc(%rsp), %rcx
movl (%rax,%rcx,4), %esi
movq 0x20(%rsp), %rax
movslq 0xc(%rsp), %rcx
movsbl 0x400(%rax,%rcx), %edx
callq 0xdedb0
cmpl $0x0, %eax
jne 0xdead1
movl $0x0, 0x44(%rsp)
jmp 0xdeccc
cmpl $0x0, 0xc(%rsp)
je 0xdeafe
movq 0x38(%rsp), %rdi
movl 0x10(%rsp), %esi
movl 0xc(%rsp), %edx
callq 0xdedb0
cmpl $0x0, %eax
jne 0xdeafc
movl $0x0, 0x44(%rsp)
jmp 0xdeccc
jmp 0xdeafe
movl $0x0, 0x4(%rsp)
movl $0x1, 0x8(%rsp)
cmpl $0x40, 0x8(%rsp)
jge 0xdec8f
movq 0x30(%rsp), %rax
movslq 0x8(%rsp), %rdx
leaq 0x58a36(%rip), %rcx     # 0x137560
movslq (%rcx,%rdx,4), %rcx
movswl (%rax,%rcx,2), %eax
movl %eax, 0x14(%rsp)
cmpl $0x0, %eax
jne 0xdeb4b
movl 0x4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4(%rsp)
jmp 0xdec7d
jmp 0xdeb4d
cmpl $0xf, 0x4(%rsp)
jle 0xdeb94
movq 0x38(%rsp), %rdi
movq 0x18(%rsp), %rax
movl 0x3c0(%rax), %esi
movq 0x18(%rsp), %rax
movsbl 0x4f0(%rax), %edx
callq 0xdedb0
cmpl $0x0, %eax
jne 0xdeb87
movl $0x0, 0x44(%rsp)
jmp 0xdeccc
movl 0x4(%rsp), %eax
subl $0x10, %eax
movl %eax, 0x4(%rsp)
jmp 0xdeb4d
movl 0x14(%rsp), %eax
movl %eax, 0x10(%rsp)
cmpl $0x0, 0x14(%rsp)
jge 0xdebb8
xorl %eax, %eax
subl 0x14(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x10(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x10(%rsp)
movl $0x1, 0xc(%rsp)
movl 0x14(%rsp), %eax
sarl %eax
movl %eax, 0x14(%rsp)
cmpl $0x0, %eax
je 0xdebdc
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0xdebc0
cmpl $0xa, 0xc(%rsp)
jle 0xdec10
movq 0x38(%rsp), %rax
movq 0x30(%rax), %rax
movq (%rax), %rax
movl $0x6, 0x28(%rax)
movq 0x38(%rsp), %rax
movq 0x30(%rax), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x38(%rsp), %rcx
movq 0x30(%rcx), %rdi
callq *%rax
movl 0x4(%rsp), %eax
shll $0x4, %eax
addl 0xc(%rsp), %eax
movl %eax, (%rsp)
movq 0x38(%rsp), %rdi
movq 0x18(%rsp), %rax
movslq (%rsp), %rcx
movl (%rax,%rcx,4), %esi
movq 0x18(%rsp), %rax
movslq (%rsp), %rcx
movsbl 0x400(%rax,%rcx), %edx
callq 0xdedb0
cmpl $0x0, %eax
jne 0xdec54
movl $0x0, 0x44(%rsp)
jmp 0xdeccc
movq 0x38(%rsp), %rdi
movl 0x10(%rsp), %esi
movl 0xc(%rsp), %edx
callq 0xdedb0
cmpl $0x0, %eax
jne 0xdec75
movl $0x0, 0x44(%rsp)
jmp 0xdeccc
movl $0x0, 0x4(%rsp)
jmp 0xdec7f
movl 0x8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8(%rsp)
jmp 0xdeb0e
cmpl $0x0, 0x4(%rsp)
jle 0xdecc4
movq 0x38(%rsp), %rdi
movq 0x18(%rsp), %rax
movl (%rax), %esi
movq 0x18(%rsp), %rax
movsbl 0x400(%rax), %edx
callq 0xdedb0
cmpl $0x0, %eax
jne 0xdecc2
movl $0x0, 0x44(%rsp)
jmp 0xdeccc
jmp 0xdecc4
movl $0x1, 0x44(%rsp)
movl 0x44(%rsp), %eax
addq $0x48, %rsp
retq
nopw %cs:(%rax,%rax)