// File: tomfunkhouser[P]gaps/pkgs/jpeg/jmemmgr.c
// Function: access_virt_sarray
METHODDEF(JSAMPARRAY)
access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
		    JDIMENSION start_row, JDIMENSION num_rows,
		    jboolean writable)
/* Access the part of a virtual sample array starting at start_row */
/* and extending for num_rows rows.  writable is true if  */
/* caller intends to modify the accessed area. */
{
  JDIMENSION end_row = start_row + num_rows;
  JDIMENSION undef_row;

  /* debugging check */
  if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
      ptr->mem_buffer == NULL)
    ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);

  /* Make the desired part of the virtual array accessible */
  if (start_row < ptr->cur_start_row ||
      end_row > ptr->cur_start_row+ptr->rows_in_mem) {
    if (! ptr->b_s_open)
      ERREXIT(cinfo, JERR_VIRTUAL_BUG);
    /* Flush old buffer contents if necessary */
    if (ptr->dirty) {
      do_sarray_io(cinfo, ptr, TRUE);
      ptr->dirty = FALSE;
    }
    /* Decide what part of virtual array to access.
     * Algorithm: if target address > current window, assume forward scan,
     * load starting at target address.  If target address < current window,
     * assume backward scan, load so that target area is top of window.
     * Note that when switching from forward write to forward read, will have
     * start_row = 0, so the limiting case applies and we load from 0 anyway.
     */
    if (start_row > ptr->cur_start_row) {
      ptr->cur_start_row = start_row;
    } else {
      /* use long arithmetic here to avoid overflow & unsigned problems */
      long ltemp;

      ltemp = (long) end_row - (long) ptr->rows_in_mem;
      if (ltemp < 0)
	ltemp = 0;		/* don't fall off front end of file */
      ptr->cur_start_row = (JDIMENSION) ltemp;
    }
    /* Read in the selected part of the array.
     * During the initial write pass, we will do no actual read
     * because the selected part is all undefined.
     */
    do_sarray_io(cinfo, ptr, FALSE);
  }
  /* Ensure the accessed part of the array is defined; prezero if needed.
   * To improve locality of access, we only prezero the part of the array
   * that the caller is about to access, not the entire in-memory array.
   */
  if (ptr->first_undef_row < end_row) {
    if (ptr->first_undef_row < start_row) {
      if (writable)		/* writer skipped over a section of array */
	ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
      undef_row = start_row;	/* but reader is allowed to read ahead */
    } else {
      undef_row = ptr->first_undef_row;
    }
    if (writable)
      ptr->first_undef_row = end_row;
    if (ptr->pre_zero) {
      size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
      undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
      end_row -= ptr->cur_start_row;
      while (undef_row < end_row) {
	jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
	undef_row++;
      }
    } else {
      if (! writable)		/* reader looking at undefined data */
	ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
    }
  }
  /* Flag the buffer dirty if caller will write in it */
  if (writable)
    ptr->dirty = TRUE;
  /* Return address of proper part of the buffer */
  return ptr->mem_buffer + (start_row - ptr->cur_start_row);
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x30(%rsp)
movq %rsi, 0x28(%rsp)
movl %edx, 0x24(%rsp)
movl %ecx, 0x20(%rsp)
movl %r8d, 0x1c(%rsp)
movl 0x24(%rsp), %eax
addl 0x20(%rsp), %eax
movl %eax, 0x18(%rsp)
movl 0x18(%rsp), %eax
movq 0x28(%rsp), %rcx
cmpl 0x8(%rcx), %eax
ja 0xfa80e
movl 0x20(%rsp), %eax
movq 0x28(%rsp), %rcx
cmpl 0x10(%rcx), %eax
ja 0xfa80e
movq 0x28(%rsp), %rax
cmpq $0x0, (%rax)
jne 0xfa82f
movq 0x30(%rsp), %rax
movq (%rax), %rax
movl $0x16, 0x28(%rax)
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x30(%rsp), %rdi
callq *%rax
movl 0x24(%rsp), %eax
movq 0x28(%rsp), %rcx
cmpl 0x1c(%rcx), %eax
jb 0xfa859
movl 0x18(%rsp), %eax
movq 0x28(%rsp), %rcx
movl 0x1c(%rcx), %ecx
movq 0x28(%rsp), %rdx
addl 0x14(%rdx), %ecx
cmpl %ecx, %eax
jbe 0xfa911
movq 0x28(%rsp), %rax
cmpl $0x0, 0x2c(%rax)
jne 0xfa885
movq 0x30(%rsp), %rax
movq (%rax), %rax
movl $0x45, 0x28(%rax)
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x30(%rsp), %rdi
callq *%rax
movq 0x28(%rsp), %rax
cmpl $0x0, 0x28(%rax)
je 0xfa8b0
movq 0x30(%rsp), %rdi
movq 0x28(%rsp), %rsi
movl $0x1, %edx
callq 0xfb030
movq 0x28(%rsp), %rax
movl $0x0, 0x28(%rax)
movl 0x24(%rsp), %eax
movq 0x28(%rsp), %rcx
cmpl 0x1c(%rcx), %eax
jbe 0xfa8cc
movl 0x24(%rsp), %ecx
movq 0x28(%rsp), %rax
movl %ecx, 0x1c(%rax)
jmp 0xfa900
movl 0x18(%rsp), %eax
movq 0x28(%rsp), %rcx
movl 0x14(%rcx), %ecx
subq %rcx, %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, 0x8(%rsp)
jge 0xfa8f1
movq $0x0, 0x8(%rsp)
movq 0x8(%rsp), %rax
movl %eax, %ecx
movq 0x28(%rsp), %rax
movl %ecx, 0x1c(%rax)
movq 0x30(%rsp), %rdi
movq 0x28(%rsp), %rsi
xorl %edx, %edx
callq 0xfb030
movq 0x28(%rsp), %rax
movl 0x20(%rax), %eax
cmpl 0x18(%rsp), %eax
jae 0xfaa1f
movq 0x28(%rsp), %rax
movl 0x20(%rax), %eax
cmpl 0x24(%rsp), %eax
jae 0xfa963
cmpl $0x0, 0x1c(%rsp)
je 0xfa959
movq 0x30(%rsp), %rax
movq (%rax), %rax
movl $0x16, 0x28(%rax)
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x30(%rsp), %rdi
callq *%rax
movl 0x24(%rsp), %eax
movl %eax, 0x14(%rsp)
jmp 0xfa96f
movq 0x28(%rsp), %rax
movl 0x20(%rax), %eax
movl %eax, 0x14(%rsp)
cmpl $0x0, 0x1c(%rsp)
je 0xfa982
movl 0x18(%rsp), %ecx
movq 0x28(%rsp), %rax
movl %ecx, 0x20(%rax)
movq 0x28(%rsp), %rax
cmpl $0x0, 0x24(%rax)
je 0xfa9f3
movq 0x28(%rsp), %rax
movl 0xc(%rax), %eax
shlq $0x0, %rax
movq %rax, (%rsp)
movq 0x28(%rsp), %rax
movl 0x1c(%rax), %ecx
movl 0x14(%rsp), %eax
subl %ecx, %eax
movl %eax, 0x14(%rsp)
movq 0x28(%rsp), %rax
movl 0x1c(%rax), %ecx
movl 0x18(%rsp), %eax
subl %ecx, %eax
movl %eax, 0x18(%rsp)
movl 0x14(%rsp), %eax
cmpl 0x18(%rsp), %eax
jae 0xfa9f1
movq 0x28(%rsp), %rax
movq (%rax), %rax
movl 0x14(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
movq (%rsp), %rsi
callq 0xf9470
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0xfa9c1
jmp 0xfaa1d
cmpl $0x0, 0x1c(%rsp)
jne 0xfaa1b
movq 0x30(%rsp), %rax
movq (%rax), %rax
movl $0x16, 0x28(%rax)
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x30(%rsp), %rdi
callq *%rax
jmp 0xfaa1d
jmp 0xfaa1f
cmpl $0x0, 0x1c(%rsp)
je 0xfaa32
movq 0x28(%rsp), %rax
movl $0x1, 0x28(%rax)
movq 0x28(%rsp), %rax
movq (%rax), %rax
movl 0x24(%rsp), %ecx
movq 0x28(%rsp), %rdx
subl 0x1c(%rdx), %ecx
movl %ecx, %ecx
shlq $0x3, %rcx
addq %rcx, %rax
addq $0x38, %rsp
retq
nopw %cs:(%rax,%rax)