// File: tomfunkhouser[P]gaps/pkgs/jpeg/jdhuff.c
// Function: jpeg_fill_bit_buffer
GLOBAL(jboolean)
jpeg_fill_bit_buffer (bitread_working_state * state,
		      register bit_buf_type get_buffer, register int bits_left,
		      int nbits)
/* Load up the bit buffer to a depth of at least nbits */
{
  /* Copy heavily used state fields into locals (hopefully registers) */
  register const JOCTET * next_input_byte = state->next_input_byte;
  register size_t bytes_in_buffer = state->bytes_in_buffer;
  j_decompress_ptr cinfo = state->cinfo;

  /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
  /* (It is assumed that no request will be for more than that many bits.) */
  /* We fail to do so only if we hit a marker or are forced to suspend. */

  if (cinfo->unread_marker == 0) {	/* cannot advance past a marker */
    while (bits_left < MIN_GET_BITS) {
      register int c;

      /* Attempt to read a byte */
      if (bytes_in_buffer == 0) {
	if (! (*cinfo->src->fill_input_buffer) (cinfo))
	  return FALSE;
	next_input_byte = cinfo->src->next_input_byte;
	bytes_in_buffer = cinfo->src->bytes_in_buffer;
      }
      bytes_in_buffer--;
      c = GETJOCTET(*next_input_byte++);

      /* If it's 0xFF, check and discard stuffed zero byte */
      if (c == 0xFF) {
	/* Loop here to discard any padding FF's on terminating marker,
	 * so that we can save a valid unread_marker value.  NOTE: we will
	 * accept multiple FF's followed by a 0 as meaning a single FF data
	 * byte.  This data pattern is not valid according to the standard.
	 */
	do {
	  if (bytes_in_buffer == 0) {
	    if (! (*cinfo->src->fill_input_buffer) (cinfo))
	      return FALSE;
	    next_input_byte = cinfo->src->next_input_byte;
	    bytes_in_buffer = cinfo->src->bytes_in_buffer;
	  }
	  bytes_in_buffer--;
	  c = GETJOCTET(*next_input_byte++);
	} while (c == 0xFF);

	if (c == 0) {
	  /* Found FF/00, which represents an FF data byte */
	  c = 0xFF;
	} else {
	  /* Oops, it's actually a marker indicating end of compressed data.
	   * Save the marker code for later use.
	   * Fine point: it might appear that we should save the marker into
	   * bitread working state, not straight into permanent state.  But
	   * once we have hit a marker, we cannot need to suspend within the
	   * current MCU, because we will read no more bytes from the data
	   * source.  So it is OK to update permanent state right away.
	   */
	  cinfo->unread_marker = c;
	  /* See if we need to insert some fake zero bits. */
	  goto no_more_bytes;
	}
      }

      /* OK, load c into get_buffer */
      get_buffer = (get_buffer << 8) | c;
      bits_left += 8;
    } /* end while */
  } else {
  no_more_bytes:
    /* We get here if we've read the marker that terminates the compressed
     * data segment.  There should be enough bits in the buffer register
     * to satisfy the request; if so, no problem.
     */
    if (nbits > bits_left) {
      /* Uh-oh.  Report corrupted data to user and stuff zeroes into
       * the data stream, so that we can produce some kind of image.
       * We use a nonvolatile flag to ensure that only one warning message
       * appears per data segment.
       */
      if (! cinfo->entropy->insufficient_data) {
	WARNMS(cinfo, JWRN_HIT_MARKER);
	cinfo->entropy->insufficient_data = TRUE;
      }
      /* Fill the buffer with zero bits */
      get_buffer <<= MIN_GET_BITS - bits_left;
      bits_left = MIN_GET_BITS;
    }
  }

  /* Unload the local registers */
  state->next_input_byte = next_input_byte;
  state->bytes_in_buffer = bytes_in_buffer;
  state->get_buffer = get_buffer;
  state->bits_left = bits_left;

  return TRUE;
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x38(%rsp)
movq %rsi, 0x30(%rsp)
movl %edx, 0x2c(%rsp)
movl %ecx, 0x28(%rsp)
movq 0x38(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x20(%rsp)
movq 0x38(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x18(%rsp)
movq 0x38(%rsp), %rax
movq 0x20(%rax), %rax
movq %rax, 0x10(%rsp)
movq 0x10(%rsp), %rax
cmpl $0x0, 0x21c(%rax)
jne 0xe9996
jmp 0xe9833
cmpl $0x19, 0x2c(%rsp)
jge 0xe9994
cmpq $0x0, 0x18(%rsp)
jne 0xe988f
movq 0x10(%rsp), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rax
movq 0x10(%rsp), %rdi
callq *%rax
cmpl $0x0, %eax
jne 0xe986c
movl $0x0, 0x44(%rsp)
jmp 0xe9a4d
movq 0x10(%rsp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq %rax, 0x20(%rsp)
movq 0x10(%rsp), %rax
movq 0x28(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x18(%rsp)
movq 0x20(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x20(%rsp)
movzbl (%rax), %eax
movl %eax, 0xc(%rsp)
cmpl $0xff, 0xc(%rsp)
jne 0xe996e
jmp 0xe98c5
cmpq $0x0, 0x18(%rsp)
jne 0xe9916
movq 0x10(%rsp), %rax
movq 0x28(%rax), %rax
movq 0x18(%rax), %rax
movq 0x10(%rsp), %rdi
callq *%rax
cmpl $0x0, %eax
jne 0xe98f3
movl $0x0, 0x44(%rsp)
jmp 0xe9a4d
movq 0x10(%rsp), %rax
movq 0x28(%rax), %rax
movq (%rax), %rax
movq %rax, 0x20(%rsp)
movq 0x10(%rsp), %rax
movq 0x28(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x18(%rsp)
movq 0x20(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x20(%rsp)
movzbl (%rax), %eax
movl %eax, 0xc(%rsp)
cmpl $0xff, 0xc(%rsp)
je 0xe98c5
cmpl $0x0, 0xc(%rsp)
jne 0xe995b
movl $0xff, 0xc(%rsp)
jmp 0xe996c
movl 0xc(%rsp), %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x21c(%rax)
jmp 0xe9998
jmp 0xe996e
movq 0x30(%rsp), %rax
shlq $0x8, %rax
movslq 0xc(%rsp), %rcx
orq %rcx, %rax
movq %rax, 0x30(%rsp)
movl 0x2c(%rsp), %eax
addl $0x8, %eax
movl %eax, 0x2c(%rsp)
jmp 0xe9833
jmp 0xe9a10
jmp 0xe9998
movl 0x28(%rsp), %eax
cmpl 0x2c(%rsp), %eax
jle 0xe9a0e
movq 0x10(%rsp), %rax
movq 0x250(%rax), %rax
cmpl $0x0, 0x10(%rax)
jne 0xe99ee
movq 0x10(%rsp), %rax
movq (%rax), %rax
movl $0x75, 0x28(%rax)
movq 0x10(%rsp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq 0x10(%rsp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq *%rax
movq 0x10(%rsp), %rax
movq 0x250(%rax), %rax
movl $0x1, 0x10(%rax)
movl $0x19, %ecx
subl 0x2c(%rsp), %ecx
movq 0x30(%rsp), %rax
movl %ecx, %ecx
shlq %cl, %rax
movq %rax, 0x30(%rsp)
movl $0x19, 0x2c(%rsp)
jmp 0xe9a10
movq 0x20(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, (%rax)
movq 0x18(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, 0x8(%rax)
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, 0x10(%rax)
movl 0x2c(%rsp), %ecx
movq 0x38(%rsp), %rax
movl %ecx, 0x18(%rax)
movl $0x1, 0x44(%rsp)
movl 0x44(%rsp), %eax
addq $0x48, %rsp
retq
nopw %cs:(%rax,%rax)