// File: tomfunkhouser[P]gaps/pkgs/png/pngwtran.c
// Function: png_do_shift
void /* PRIVATE */
png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
{
   png_debug(1, "in png_do_shift");

   if (
      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
   {
      int shift_start[4], shift_dec[4];
      int channels = 0;

      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->red;
         shift_dec[channels] = bit_depth->red;
         channels++;
         shift_start[channels] = row_info->bit_depth - bit_depth->green;
         shift_dec[channels] = bit_depth->green;
         channels++;
         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
         shift_dec[channels] = bit_depth->blue;
         channels++;
      }
      else
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
         shift_dec[channels] = bit_depth->gray;
         channels++;
      }
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
         shift_dec[channels] = bit_depth->alpha;
         channels++;
      }

      /* With low row depths, could only be grayscale, so one channel */
      if (row_info->bit_depth < 8)
      {
         png_bytep bp = row;
         png_uint_32 i;
         png_byte mask;
         png_uint_32 row_bytes = row_info->rowbytes;

         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
            mask = 0x55;
         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
            mask = 0x11;
         else
            mask = 0xff;

         for (i = 0; i < row_bytes; i++, bp++)
         {
            png_uint_16 v;
            int j;

            v = *bp;
            *bp = 0;
            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
            {
               if (j > 0)
                  *bp |= (png_byte)((v << j) & 0xff);
               else
                  *bp |= (png_byte)((v >> (-j)) & mask);
            }
         }
      }
      else if (row_info->bit_depth == 8)
      {
         png_bytep bp = row;
         png_uint_32 i;
         png_uint_32 istop = channels * row_info->width;

         for (i = 0; i < istop; i++, bp++)
         {

            png_uint_16 v;
            int j;
            int c = (int)(i%channels);

            v = *bp;
            *bp = 0;
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
            {
               if (j > 0)
                  *bp |= (png_byte)((v << j) & 0xff);
               else
                  *bp |= (png_byte)((v >> (-j)) & 0xff);
            }
         }
      }
      else
      {
         png_bytep bp;
         png_uint_32 i;
         png_uint_32 istop = channels * row_info->width;

         for (bp = row, i = 0; i < istop; i++)
         {
            int c = (int)(i%channels);
            png_uint_16 value, v;
            int j;

            v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
            value = 0;
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
            {
               if (j > 0)
                  value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
               else
                  value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
            }
            *bp++ = (png_byte)(value >> 8);
            *bp++ = (png_byte)(value & 0xff);
         }
      }
   }
}

// Assembly:
subq $0x28, %rsp
movq %rdi, 0x20(%rsp)
movq %rsi, 0x18(%rsp)
movq %rdx, 0x10(%rsp)
movq 0x20(%rsp), %rax
movzbl 0x10(%rax), %eax
cmpl $0x3, %eax
je 0x1129b5
movl $0x0, -0x14(%rsp)
movq 0x20(%rsp), %rax
movzbl 0x10(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x1125bd
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %ecx
movq 0x10(%rsp), %rax
movzbl (%rax), %eax
subl %eax, %ecx
movslq -0x14(%rsp), %rax
movl %ecx, (%rsp,%rax,4)
movq 0x10(%rsp), %rax
movzbl (%rax), %ecx
movslq -0x14(%rsp), %rax
movl %ecx, -0x10(%rsp,%rax,4)
movl -0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rsp)
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %ecx
movq 0x10(%rsp), %rax
movzbl 0x1(%rax), %eax
subl %eax, %ecx
movslq -0x14(%rsp), %rax
movl %ecx, (%rsp,%rax,4)
movq 0x10(%rsp), %rax
movzbl 0x1(%rax), %ecx
movslq -0x14(%rsp), %rax
movl %ecx, -0x10(%rsp,%rax,4)
movl -0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rsp)
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %ecx
movq 0x10(%rsp), %rax
movzbl 0x2(%rax), %eax
subl %eax, %ecx
movslq -0x14(%rsp), %rax
movl %ecx, (%rsp,%rax,4)
movq 0x10(%rsp), %rax
movzbl 0x2(%rax), %ecx
movslq -0x14(%rsp), %rax
movl %ecx, -0x10(%rsp,%rax,4)
movl -0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rsp)
jmp 0x1125f6
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %ecx
movq 0x10(%rsp), %rax
movzbl 0x3(%rax), %eax
subl %eax, %ecx
movslq -0x14(%rsp), %rax
movl %ecx, (%rsp,%rax,4)
movq 0x10(%rsp), %rax
movzbl 0x3(%rax), %ecx
movslq -0x14(%rsp), %rax
movl %ecx, -0x10(%rsp,%rax,4)
movl -0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rsp)
movq 0x20(%rsp), %rax
movzbl 0x10(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x112640
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %ecx
movq 0x10(%rsp), %rax
movzbl 0x4(%rax), %eax
subl %eax, %ecx
movslq -0x14(%rsp), %rax
movl %ecx, (%rsp,%rax,4)
movq 0x10(%rsp), %rax
movzbl 0x4(%rax), %ecx
movslq -0x14(%rsp), %rax
movl %ecx, -0x10(%rsp,%rax,4)
movl -0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rsp)
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %eax
cmpl $0x8, %eax
jge 0x112778
movq 0x18(%rsp), %rax
movq %rax, -0x20(%rsp)
movq 0x20(%rsp), %rax
movq 0x8(%rax), %rax
movl %eax, -0x2c(%rsp)
movq 0x10(%rsp), %rax
movzbl 0x3(%rax), %eax
cmpl $0x1, %eax
jne 0x11268c
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %eax
cmpl $0x2, %eax
jne 0x11268c
movb $0x55, -0x25(%rsp)
jmp 0x1126b6
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %eax
cmpl $0x4, %eax
jne 0x1126af
movq 0x10(%rsp), %rax
movzbl 0x3(%rax), %eax
cmpl $0x3, %eax
jne 0x1126af
movb $0x11, -0x25(%rsp)
jmp 0x1126b4
movb $-0x1, -0x25(%rsp)
jmp 0x1126b6
movl $0x0, -0x24(%rsp)
movl -0x24(%rsp), %eax
cmpl -0x2c(%rsp), %eax
jae 0x112773
movq -0x20(%rsp), %rax
movzbl (%rax), %eax
movw %ax, -0x2e(%rsp)
movq -0x20(%rsp), %rax
movb $0x0, (%rax)
movl (%rsp), %eax
movl %eax, -0x34(%rsp)
movl -0x34(%rsp), %eax
xorl %ecx, %ecx
subl -0x10(%rsp), %ecx
cmpl %ecx, %eax
jle 0x112753
cmpl $0x0, -0x34(%rsp)
jle 0x11271e
movzwl -0x2e(%rsp), %eax
movl -0x34(%rsp), %ecx
shll %cl, %eax
andl $0xff, %eax
movzbl %al, %edx
movq -0x20(%rsp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
jmp 0x112741
movzwl -0x2e(%rsp), %eax
xorl %ecx, %ecx
subl -0x34(%rsp), %ecx
sarl %cl, %eax
movzbl -0x25(%rsp), %ecx
andl %ecx, %eax
movzbl %al, %edx
movq -0x20(%rsp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
jmp 0x112743
movl -0x10(%rsp), %ecx
movl -0x34(%rsp), %eax
subl %ecx, %eax
movl %eax, -0x34(%rsp)
jmp 0x1126e8
jmp 0x112755
movl -0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rsp)
movq -0x20(%rsp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rsp)
jmp 0x1126be
jmp 0x1129b3
movq 0x20(%rsp), %rax
movzbl 0x11(%rax), %eax
cmpl $0x8, %eax
jne 0x112881
movq 0x18(%rsp), %rax
movq %rax, -0x40(%rsp)
movl -0x14(%rsp), %eax
movq 0x20(%rsp), %rcx
imull (%rcx), %eax
movl %eax, -0x48(%rsp)
movl $0x0, -0x44(%rsp)
movl -0x44(%rsp), %eax
cmpl -0x48(%rsp), %eax
jae 0x11287c
movl -0x44(%rsp), %eax
xorl %edx, %edx
divl -0x14(%rsp)
movl %edx, -0x54(%rsp)
movq -0x40(%rsp), %rax
movzbl (%rax), %eax
movw %ax, -0x4a(%rsp)
movq -0x40(%rsp), %rax
movb $0x0, (%rax)
movslq -0x54(%rsp), %rax
movl (%rsp,%rax,4), %eax
movl %eax, -0x50(%rsp)
movl -0x50(%rsp), %eax
movslq -0x54(%rsp), %rdx
xorl %ecx, %ecx
subl -0x10(%rsp,%rdx,4), %ecx
cmpl %ecx, %eax
jle 0x11285c
cmpl $0x0, -0x50(%rsp)
jle 0x112824
movzwl -0x4a(%rsp), %eax
movl -0x50(%rsp), %ecx
shll %cl, %eax
andl $0xff, %eax
movzbl %al, %edx
movq -0x40(%rsp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
jmp 0x112845
movzwl -0x4a(%rsp), %eax
xorl %ecx, %ecx
subl -0x50(%rsp), %ecx
sarl %cl, %eax
andl $0xff, %eax
movzbl %al, %edx
movq -0x40(%rsp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
jmp 0x112847
movslq -0x54(%rsp), %rax
movl -0x10(%rsp,%rax,4), %ecx
movl -0x50(%rsp), %eax
subl %ecx, %eax
movl %eax, -0x50(%rsp)
jmp 0x1127e9
jmp 0x11285e
movl -0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rsp)
movq -0x40(%rsp), %rax
addq $0x1, %rax
movq %rax, -0x40(%rsp)
jmp 0x1127ac
jmp 0x1129b1
movl -0x14(%rsp), %eax
movq 0x20(%rsp), %rcx
imull (%rcx), %eax
movl %eax, -0x68(%rsp)
movq 0x18(%rsp), %rax
movq %rax, -0x60(%rsp)
movl $0x0, -0x64(%rsp)
movl -0x64(%rsp), %eax
cmpl -0x68(%rsp), %eax
jae 0x1129af
movl -0x64(%rsp), %eax
xorl %edx, %edx
divl -0x14(%rsp)
movl %edx, -0x6c(%rsp)
movq -0x60(%rsp), %rax
movzbl (%rax), %eax
movzwl %ax, %eax
shll $0x8, %eax
movq -0x60(%rsp), %rcx
movzbl 0x1(%rcx), %ecx
addl %ecx, %eax
movw %ax, -0x70(%rsp)
movw $0x0, -0x6e(%rsp)
movslq -0x6c(%rsp), %rax
movl (%rsp,%rax,4), %eax
movl %eax, -0x74(%rsp)
movl -0x74(%rsp), %eax
movslq -0x6c(%rsp), %rdx
xorl %ecx, %ecx
subl -0x10(%rsp,%rdx,4), %ecx
cmpl %ecx, %eax
jle 0x112963
cmpl $0x0, -0x74(%rsp)
jle 0x11292b
movzwl -0x70(%rsp), %eax
movl -0x74(%rsp), %ecx
shll %cl, %eax
andl $0xffff, %eax           # imm = 0xFFFF
movzwl %ax, %ecx
movzwl -0x6e(%rsp), %eax
orl %ecx, %eax
movw %ax, -0x6e(%rsp)
jmp 0x11294c
movzwl -0x70(%rsp), %eax
xorl %ecx, %ecx
subl -0x74(%rsp), %ecx
sarl %cl, %eax
andl $0xffff, %eax           # imm = 0xFFFF
movzwl %ax, %ecx
movzwl -0x6e(%rsp), %eax
orl %ecx, %eax
movw %ax, -0x6e(%rsp)
jmp 0x11294e
movslq -0x6c(%rsp), %rax
movl -0x10(%rsp,%rax,4), %ecx
movl -0x74(%rsp), %eax
subl %ecx, %eax
movl %eax, -0x74(%rsp)
jmp 0x1128f0
movzwl -0x6e(%rsp), %eax
sarl $0x8, %eax
movb %al, %cl
movq -0x60(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x60(%rsp)
movb %cl, (%rax)
movzwl -0x6e(%rsp), %eax
andl $0xff, %eax
movb %al, %cl
movq -0x60(%rsp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x60(%rsp)
movb %cl, (%rax)
movl -0x64(%rsp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rsp)
jmp 0x1128a3
jmp 0x1129b1
jmp 0x1129b3
jmp 0x1129b5
addq $0x28, %rsp
retq
nopw (%rax,%rax)