// File: tomfunkhouser[P]gaps/pkgs/jpeg/jcdctmgr.c
// Function: forward_DCT
METHODDEF(void)
forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
	     JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
	     JDIMENSION start_row, JDIMENSION start_col,
	     JDIMENSION num_blocks)
/* This version is used for integer DCT implementations. */
{
  /* This routine is heavily used, so it's worth coding it tightly. */
  my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
  forward_DCT_method_ptr do_dct = fdct->do_dct;
  DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
  DCTELEM workspace[DCTSIZE2];	/* work area for FDCT subroutine */
  JDIMENSION bi;

  sample_data += start_row;	/* fold in the vertical offset once */

  for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
    /* Load data into workspace, applying unsigned->signed conversion */
    { register DCTELEM *workspaceptr;
      register JSAMPROW elemptr;
      register int elemr;

      workspaceptr = workspace;
      for (elemr = 0; elemr < DCTSIZE; elemr++) {
	elemptr = sample_data[elemr] + start_col;
#if DCTSIZE == 8		/* unroll the inner loop */
	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
#else
	{ register int elemc;
	  for (elemc = DCTSIZE; elemc > 0; elemc--) {
	    *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
	  }
	}
#endif
      }
    }

    /* Perform the DCT */
    (*do_dct) (workspace);

    /* Quantize/descale the coefficients, and store into coef_blocks[] */
    { register DCTELEM temp, qval;
      register int i;
      register JCOEFPTR output_ptr = coef_blocks[bi];

      for (i = 0; i < DCTSIZE2; i++) {
	qval = divisors[i];
	temp = workspace[i];
	/* Divide the coefficient value by qval, ensuring proper rounding.
	 * Since C does not specify the direction of rounding for negative
	 * quotients, we have to force the dividend positive for portability.
	 *
	 * In most files, at least half of the output values will be zero
	 * (at default quantization settings, more like three-quarters...)
	 * so we should ensure that this case is fast.  On many machines,
	 * a comparison is enough cheaper than a divide to make a special test
	 * a win.  Since both inputs will be nonnegative, we need only test
	 * for a < b to discover whether a/b is 0.
	 * If your machine's division is fast enough, define FAST_DIVIDE.
	 */
#ifdef FAST_DIVIDE
#define DIVIDE_BY(a,b)	a /= b
#else
#define DIVIDE_BY(a,b)	if (a >= b) a /= b; else a = 0
#endif
	if (temp < 0) {
	  temp = -temp;
	  temp += qval>>1;	/* for rounding */
	  DIVIDE_BY(temp, qval);
	  temp = -temp;
	} else {
	  temp += qval>>1;	/* for rounding */
	  DIVIDE_BY(temp, qval);
	}
	output_ptr[i] = (JCOEF) temp;
      }
    }
  }
}

// Assembly:
subq $0x178, %rsp            # imm = 0x178
movl 0x180(%rsp), %eax
movq %rdi, 0x170(%rsp)
movq %rsi, 0x168(%rsp)
movq %rdx, 0x160(%rsp)
movq %rcx, 0x158(%rsp)
movl %r8d, 0x154(%rsp)
movl %r9d, 0x150(%rsp)
movq 0x170(%rsp), %rax
movq 0x1e8(%rax), %rax
movq %rax, 0x148(%rsp)
movq 0x148(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x140(%rsp)
movq 0x148(%rsp), %rax
movq 0x168(%rsp), %rcx
movslq 0x10(%rcx), %rcx
movq 0x18(%rax,%rcx,8), %rax
movq %rax, 0x138(%rsp)
movl 0x154(%rsp), %ecx
movq 0x160(%rsp), %rax
movl %ecx, %ecx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x160(%rsp)
movl $0x0, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
cmpl 0x180(%rsp), %eax
jae 0xe0e9a
leaq 0x30(%rsp), %rax
movq %rax, 0x20(%rsp)
movl $0x0, 0x14(%rsp)
cmpl $0x8, 0x14(%rsp)
jge 0xe0d78
movq 0x160(%rsp), %rax
movslq 0x14(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movl 0x150(%rsp), %ecx
addq %rcx, %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %ecx
subl $0x80, %ecx
movq 0x20(%rsp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, 0x20(%rsp)
movl %ecx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %ecx
subl $0x80, %ecx
movq 0x20(%rsp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, 0x20(%rsp)
movl %ecx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %ecx
subl $0x80, %ecx
movq 0x20(%rsp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, 0x20(%rsp)
movl %ecx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %ecx
subl $0x80, %ecx
movq 0x20(%rsp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, 0x20(%rsp)
movl %ecx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %ecx
subl $0x80, %ecx
movq 0x20(%rsp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, 0x20(%rsp)
movl %ecx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %ecx
subl $0x80, %ecx
movq 0x20(%rsp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, 0x20(%rsp)
movl %ecx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %ecx
subl $0x80, %ecx
movq 0x20(%rsp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, 0x20(%rsp)
movl %ecx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x18(%rsp)
movzbl (%rax), %ecx
subl $0x80, %ecx
movq 0x20(%rsp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, 0x20(%rsp)
movl %ecx, (%rax)
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0xe0bd5
movq 0x140(%rsp), %rax
leaq 0x30(%rsp), %rdi
callq *%rax
movq 0x158(%rsp), %rax
movl 0x2c(%rsp), %ecx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, (%rsp)
movl $0x0, 0x8(%rsp)
cmpl $0x40, 0x8(%rsp)
jge 0xe0e77
movq 0x138(%rsp), %rax
movslq 0x8(%rsp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0xc(%rsp)
movslq 0x8(%rsp), %rax
movl 0x30(%rsp,%rax,4), %eax
movl %eax, 0x10(%rsp)
cmpl $0x0, 0x10(%rsp)
jge 0xe0e20
xorl %eax, %eax
subl 0x10(%rsp), %eax
movl %eax, 0x10(%rsp)
movl 0xc(%rsp), %eax
sarl %eax
addl 0x10(%rsp), %eax
movl %eax, 0x10(%rsp)
movl 0x10(%rsp), %eax
cmpl 0xc(%rsp), %eax
jl 0xe0e0c
movl 0xc(%rsp), %ecx
movl 0x10(%rsp), %eax
cltd
idivl %ecx
movl %eax, 0x10(%rsp)
jmp 0xe0e14
movl $0x0, 0x10(%rsp)
xorl %eax, %eax
subl 0x10(%rsp), %eax
movl %eax, 0x10(%rsp)
jmp 0xe0e53
movl 0xc(%rsp), %eax
sarl %eax
addl 0x10(%rsp), %eax
movl %eax, 0x10(%rsp)
movl 0x10(%rsp), %eax
cmpl 0xc(%rsp), %eax
jl 0xe0e49
movl 0xc(%rsp), %ecx
movl 0x10(%rsp), %eax
cltd
idivl %ecx
movl %eax, 0x10(%rsp)
jmp 0xe0e51
movl $0x0, 0x10(%rsp)
jmp 0xe0e53
movl 0x10(%rsp), %eax
movw %ax, %dx
movq (%rsp), %rax
movslq 0x8(%rsp), %rcx
movw %dx, (%rax,%rcx,2)
movl 0x8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8(%rsp)
jmp 0xe0da6
jmp 0xe0e79
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
movl 0x150(%rsp), %eax
addl $0x8, %eax
movl %eax, 0x150(%rsp)
jmp 0xe0bb2
addq $0x178, %rsp            # imm = 0x178
retq
nopw %cs:(%rax,%rax)