-/* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file
- *
- * For Intel x86 CPU and Microsoft Visual C++ compiler
- *
- * libpng version 1.2.5rc3 - September 18, 2002
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2002 Glenn Randers-Pehrson
- * Copyright (c) 1998, Intel Corporation
- *
- * Contributed by Nirav Chhatrapati, Intel Corporation, 1998
- * Interface to libpng contributed by Gilles Vollant, 1999
- *
- *
- * In png_do_read_interlace() in libpng versions 1.0.3a through 1.0.4d,
- * a sign error in the post-MMX cleanup code for each pixel_depth resulted
- * in bad pixels at the beginning of some rows of some images, and also
- * (due to out-of-range memory reads and writes) caused heap corruption
- * when compiled with MSVC 6.0. The error was fixed in version 1.0.4e.
- *
- * [png_read_filter_row_mmx_avg() bpp == 2 bugfix, GRR 20000916]
- *
- * [runtime MMX configuration, GRR 20010102]
- *
- */
-
-#define PNG_INTERNAL
-#include "png.h"
-
-#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)
-
-static int mmx_supported=2;
-
-
-int PNGAPI
-png_mmx_support(void)
-{
- int mmx_supported_local = 0;
- _asm {
- push ebx /*CPUID will trash these */
- push ecx
- push edx
-
- pushfd /*Save Eflag to stack */
- pop eax /*Get Eflag from stack into eax */
- mov ecx, eax /*Make another copy of Eflag in ecx */
- xor eax, 0x200000 /*Toggle ID bit in Eflag [i.e. bit(21)] */
- push eax /*Save modified Eflag back to stack */
-
- popfd /*Restored modified value back to Eflag reg */
- pushfd /*Save Eflag to stack */
- pop eax /*Get Eflag from stack */
- push ecx /* save original Eflag to stack */
- popfd /* restore original Eflag */
- xor eax, ecx /*Compare the new Eflag with the original Eflag */
- jz NOT_SUPPORTED /*If the same, CPUID instruction is not supported, */
- /*skip following instructions and jump to */
- /*NOT_SUPPORTED label */
-
- xor eax, eax /*Set eax to zero */
-
- _asm _emit 0x0f /*CPUID instruction (two bytes opcode) */
- _asm _emit 0xa2
-
- cmp eax, 1 /*make sure eax return non-zero value */
- jl NOT_SUPPORTED /*If eax is zero, mmx not supported */
-
- xor eax, eax /*set eax to zero */
- inc eax /*Now increment eax to 1. This instruction is */
- /*faster than the instruction "mov eax, 1" */
-
- _asm _emit 0x0f /*CPUID instruction */
- _asm _emit 0xa2
-
- and edx, 0x00800000 /*mask out all bits but mmx bit(24) */
- cmp edx, 0 /* 0 = mmx not supported */
- jz NOT_SUPPORTED /* non-zero = Yes, mmx IS supported */
-
- mov mmx_supported_local, 1 /*set return value to 1 */
-
-NOT_SUPPORTED:
- mov eax, mmx_supported_local /*move return value to eax */
- pop edx /*CPUID trashed these */
- pop ecx
- pop ebx
- }
-
- /*mmx_supported_local=0; // test code for force don't support MMX */
- /*printf("MMX : %u (1=MMX supported)\n",mmx_supported_local); */
-
- mmx_supported = mmx_supported_local;
- return mmx_supported_local;
-}
-
-/* Combines the row recently read in with the previous row.
- This routine takes care of alpha and transparency if requested.
- This routine also handles the two methods of progressive display
- of interlaced images, depending on the mask value.
- The mask value describes which pixels are to be combined with
- the row. The pattern always repeats every 8 pixels, so just 8
- bits are needed. A one indicates the pixel is to be combined; a
- zero indicates the pixel is to be skipped. This is in addition
- to any alpha or transparency value associated with the pixel. If
- you want all pixels to be combined, pass 0xff (255) in mask. */
-
-/* Use this routine for x86 platform - uses faster MMX routine if machine
- supports MMX */
-
-void /* PRIVATE */
-png_combine_row(png_structp png_ptr, png_bytep row, int mask)
-{
-#ifdef PNG_USE_LOCAL_ARRAYS
- const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-#endif
-
- png_debug(1,"in png_combine_row_asm\n");
-
- if (mmx_supported == 2) {
- /* this should have happened in png_init_mmx_flags() already */
- png_warning(png_ptr, "asm_flags may not have been initialized");
- png_mmx_support();
- }
-
- if (mask == 0xff)
- {
- png_memcpy(row, png_ptr->row_buf + 1,
- (png_size_t)((png_ptr->width * png_ptr->row_info.pixel_depth + 7) >> 3));
- }
- /* GRR: add "else if (mask == 0)" case?
- * or does png_combine_row() not even get called in that case? */
- else
- {
- switch (png_ptr->row_info.pixel_depth)
- {
- case 1:
- {
- png_bytep sp;
- png_bytep dp;
- int s_inc, s_start, s_end;
- int m;
- int shift;
- png_uint_32 i;
-
- sp = png_ptr->row_buf + 1;
- dp = row;
- m = 0x80;
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
- {
- s_start = 0;
- s_end = 7;
- s_inc = 1;
- }
- else
-#endif
- {
- s_start = 7;
- s_end = 0;
- s_inc = -1;
- }
-
- shift = s_start;
-
- for (i = 0; i < png_ptr->width; i++)
- {
- if (m & mask)
- {
- int value;
-
- value = (*sp >> shift) & 0x1;
- *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
- *dp |= (png_byte)(value << shift);
- }
-
- if (shift == s_end)
- {
- shift = s_start;
- sp++;
- dp++;
- }
- else
- shift += s_inc;
-
- if (m == 1)
- m = 0x80;
- else
- m >>= 1;
- }
- break;
- }
-
- case 2:
- {
- png_bytep sp;
- png_bytep dp;
- int s_start, s_end, s_inc;
- int m;
- int shift;
- png_uint_32 i;
- int value;
-
- sp = png_ptr->row_buf + 1;
- dp = row;
- m = 0x80;
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
- {
- s_start = 0;
- s_end = 6;
- s_inc = 2;
- }
- else
-#endif
- {
- s_start = 6;
- s_end = 0;
- s_inc = -2;
- }
-
- shift = s_start;
-
- for (i = 0; i < png_ptr->width; i++)
- {
- if (m & mask)
- {
- value = (*sp >> shift) & 0x3;
- *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *dp |= (png_byte)(value << shift);
- }
-
- if (shift == s_end)
- {
- shift = s_start;
- sp++;
- dp++;
- }
- else
- shift += s_inc;
- if (m == 1)
- m = 0x80;
- else
- m >>= 1;
- }
- break;
- }
-
- case 4:
- {
- png_bytep sp;
- png_bytep dp;
- int s_start, s_end, s_inc;
- int m;
- int shift;
- png_uint_32 i;
- int value;
-
- sp = png_ptr->row_buf + 1;
- dp = row;
- m = 0x80;
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
- {
- s_start = 0;
- s_end = 4;
- s_inc = 4;
- }
- else
-#endif
- {
- s_start = 4;
- s_end = 0;
- s_inc = -4;
- }
- shift = s_start;
-
- for (i = 0; i < png_ptr->width; i++)
- {
- if (m & mask)
- {
- value = (*sp >> shift) & 0xf;
- *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *dp |= (png_byte)(value << shift);
- }
-
- if (shift == s_end)
- {
- shift = s_start;
- sp++;
- dp++;
- }
- else
- shift += s_inc;
- if (m == 1)
- m = 0x80;
- else
- m >>= 1;
- }
- break;
- }
-
- case 8:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int m;
- int diff, unmask;
-
- __int64 mask0=0x0102040810204080;
-
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- {
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
- m = 0x80;
- unmask = ~mask;
- len = png_ptr->width &~7; /*reduce to multiple of 8 */
- diff = png_ptr->width & 7; /*amount lost */
-
- _asm
- {
- movd mm7, unmask /*load bit pattern */
- psubb mm6,mm6 /*zero mm6 */
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 /*fill register with 8 masks */
-
- movq mm0,mask0
-
- pand mm0,mm7 /*nonzero if keep byte */
- pcmpeqb mm0,mm6 /*zeros->1s, v versa */
-
- mov ecx,len /*load length of line (pixels) */
- mov esi,srcptr /*load source */
- mov ebx,dstptr /*load dest */
- cmp ecx,0 /*lcr */
- je mainloop8end
-
-mainloop8:
- movq mm4,[esi]
- pand mm4,mm0
- movq mm6,mm0
- pandn mm6,[ebx]
- por mm4,mm6
- movq [ebx],mm4
-
- add esi,8 /*inc by 8 bytes processed */
- add ebx,8
- sub ecx,8 /*dec by 8 pixels processed */
-
- ja mainloop8
-mainloop8end:
-
- mov ecx,diff
- cmp ecx,0
- jz end8
-
- mov edx,mask
- sal edx,24 /*make low byte the high byte */
-
-secondloop8:
- sal edx,1 /*move high bit to CF */
- jnc skip8 /*if CF = 0 */
- mov al,[esi]
- mov [ebx],al
-skip8:
- inc esi
- inc ebx
-
- dec ecx
- jnz secondloop8
-end8:
- emms
- }
- }
- else /* mmx not supported - use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
-
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
-
- break;
- } /* end 8 bpp */
-
- case 16:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int unmask, diff;
- __int64 mask1=0x0101020204040808,
- mask0=0x1010202040408080;
-
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- {
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
-
- unmask = ~mask;
- len = (png_ptr->width)&~7;
- diff = (png_ptr->width)&7;
- _asm
- {
- movd mm7, unmask /*load bit pattern */
- psubb mm6,mm6 /*zero mm6 */
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 /*fill register with 8 masks */
-
- movq mm0,mask0
- movq mm1,mask1
-
- pand mm0,mm7
- pand mm1,mm7
-
- pcmpeqb mm0,mm6
- pcmpeqb mm1,mm6
-
- mov ecx,len /*load length of line */
- mov esi,srcptr /*load source */
- mov ebx,dstptr /*load dest */
- cmp ecx,0 /*lcr */
- jz mainloop16end
-
-mainloop16:
- movq mm4,[esi]
- pand mm4,mm0
- movq mm6,mm0
- movq mm7,[ebx]
- pandn mm6,mm7
- por mm4,mm6
- movq [ebx],mm4
-
- movq mm5,[esi+8]
- pand mm5,mm1
- movq mm7,mm1
- movq mm6,[ebx+8]
- pandn mm7,mm6
- por mm5,mm7
- movq [ebx+8],mm5
-
- add esi,16 /*inc by 16 bytes processed */
- add ebx,16
- sub ecx,8 /*dec by 8 pixels processed */
-
- ja mainloop16
-
-mainloop16end:
- mov ecx,diff
- cmp ecx,0
- jz end16
-
- mov edx,mask
- sal edx,24 /*make low byte the high byte */
-secondloop16:
- sal edx,1 /*move high bit to CF */
- jnc skip16 /*if CF = 0 */
- mov ax,[esi]
- mov [ebx],ax
-skip16:
- add esi,2
- add ebx,2
-
- dec ecx
- jnz secondloop16
-end16:
- emms
- }
- }
- else /* mmx not supported - use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
-
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
-
- break;
- } /* end 16 bpp */
-
- case 24:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int unmask, diff;
-
- __int64 mask2=0x0101010202020404, /*24bpp */
- mask1=0x0408080810101020,
- mask0=0x2020404040808080;
-
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
-
- unmask = ~mask;
- len = (png_ptr->width)&~7;
- diff = (png_ptr->width)&7;
-
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- {
- _asm
- {
- movd mm7, unmask /*load bit pattern */
- psubb mm6,mm6 /*zero mm6 */
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 /*fill register with 8 masks */
-
- movq mm0,mask0
- movq mm1,mask1
- movq mm2,mask2
-
- pand mm0,mm7
- pand mm1,mm7
- pand mm2,mm7
-
- pcmpeqb mm0,mm6
- pcmpeqb mm1,mm6
- pcmpeqb mm2,mm6
-
- mov ecx,len /*load length of line */
- mov esi,srcptr /*load source */
- mov ebx,dstptr /*load dest */
- cmp ecx,0
- jz mainloop24end
-
-mainloop24:
- movq mm4,[esi]
- pand mm4,mm0
- movq mm6,mm0
- movq mm7,[ebx]
- pandn mm6,mm7
- por mm4,mm6
- movq [ebx],mm4
-
-
- movq mm5,[esi+8]
- pand mm5,mm1
- movq mm7,mm1
- movq mm6,[ebx+8]
- pandn mm7,mm6
- por mm5,mm7
- movq [ebx+8],mm5
-
- movq mm6,[esi+16]
- pand mm6,mm2
- movq mm4,mm2
- movq mm7,[ebx+16]
- pandn mm4,mm7
- por mm6,mm4
- movq [ebx+16],mm6
-
- add esi,24 /*inc by 24 bytes processed */
- add ebx,24
- sub ecx,8 /*dec by 8 pixels processed */
-
- ja mainloop24
-
-mainloop24end:
- mov ecx,diff
- cmp ecx,0
- jz end24
-
- mov edx,mask
- sal edx,24 /*make low byte the high byte */
-secondloop24:
- sal edx,1 /*move high bit to CF */
- jnc skip24 /*if CF = 0 */
- mov ax,[esi]
- mov [ebx],ax
- xor eax,eax
- mov al,[esi+2]
- mov [ebx+2],al
-skip24:
- add esi,3
- add ebx,3
-
- dec ecx
- jnz secondloop24
-
-end24:
- emms
- }
- }
- else /* mmx not supported - use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
-
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
-
- break;
- } /* end 24 bpp */
-
- case 32:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int unmask, diff;
-
- __int64 mask3=0x0101010102020202, /*32bpp */
- mask2=0x0404040408080808,
- mask1=0x1010101020202020,
- mask0=0x4040404080808080;
-
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
-
- unmask = ~mask;
- len = (png_ptr->width)&~7;
- diff = (png_ptr->width)&7;
-
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- {
- _asm
- {
- movd mm7, unmask /*load bit pattern */
- psubb mm6,mm6 /*zero mm6 */
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 /*fill register with 8 masks */
-
- movq mm0,mask0
- movq mm1,mask1
- movq mm2,mask2
- movq mm3,mask3
-
- pand mm0,mm7
- pand mm1,mm7
- pand mm2,mm7
- pand mm3,mm7
-
- pcmpeqb mm0,mm6
- pcmpeqb mm1,mm6
- pcmpeqb mm2,mm6
- pcmpeqb mm3,mm6
-
- mov ecx,len /*load length of line */
- mov esi,srcptr /*load source */
- mov ebx,dstptr /*load dest */
-
- cmp ecx,0 /*lcr */
- jz mainloop32end
-
-mainloop32:
- movq mm4,[esi]
- pand mm4,mm0
- movq mm6,mm0
- movq mm7,[ebx]
- pandn mm6,mm7
- por mm4,mm6
- movq [ebx],mm4
-
- movq mm5,[esi+8]
- pand mm5,mm1
- movq mm7,mm1
- movq mm6,[ebx+8]
- pandn mm7,mm6
- por mm5,mm7
- movq [ebx+8],mm5
-
- movq mm6,[esi+16]
- pand mm6,mm2
- movq mm4,mm2
- movq mm7,[ebx+16]
- pandn mm4,mm7
- por mm6,mm4
- movq [ebx+16],mm6
-
- movq mm7,[esi+24]
- pand mm7,mm3
- movq mm5,mm3
- movq mm4,[ebx+24]
- pandn mm5,mm4
- por mm7,mm5
- movq [ebx+24],mm7
-
- add esi,32 /*inc by 32 bytes processed */
- add ebx,32
- sub ecx,8 /*dec by 8 pixels processed */
-
- ja mainloop32
-
-mainloop32end:
- mov ecx,diff
- cmp ecx,0
- jz end32
-
- mov edx,mask
- sal edx,24 /*make low byte the high byte */
-secondloop32:
- sal edx,1 /*move high bit to CF */
- jnc skip32 /*if CF = 0 */
- mov eax,[esi]
- mov [ebx],eax
-skip32:
- add esi,4
- add ebx,4
-
- dec ecx
- jnz secondloop32
-
-end32:
- emms
- }
- }
- else /* mmx _not supported - Use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
-
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
-
- break;
- } /* end 32 bpp */
-
- case 48:
- {
- png_bytep srcptr;
- png_bytep dstptr;
- png_uint_32 len;
- int unmask, diff;
-
- __int64 mask5=0x0101010101010202,
- mask4=0x0202020204040404,
- mask3=0x0404080808080808,
- mask2=0x1010101010102020,
- mask1=0x2020202040404040,
- mask0=0x4040808080808080;
-
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
- /* && mmx_supported */ )
- {
- srcptr = png_ptr->row_buf + 1;
- dstptr = row;
-
- unmask = ~mask;
- len = (png_ptr->width)&~7;
- diff = (png_ptr->width)&7;
- _asm
- {
- movd mm7, unmask /*load bit pattern */
- psubb mm6,mm6 /*zero mm6 */
- punpcklbw mm7,mm7
- punpcklwd mm7,mm7
- punpckldq mm7,mm7 /*fill register with 8 masks */
-
- movq mm0,mask0
- movq mm1,mask1
- movq mm2,mask2
- movq mm3,mask3
- movq mm4,mask4
- movq mm5,mask5
-
- pand mm0,mm7
- pand mm1,mm7
- pand mm2,mm7
- pand mm3,mm7
- pand mm4,mm7
- pand mm5,mm7
-
- pcmpeqb mm0,mm6
- pcmpeqb mm1,mm6
- pcmpeqb mm2,mm6
- pcmpeqb mm3,mm6
- pcmpeqb mm4,mm6
- pcmpeqb mm5,mm6
-
- mov ecx,len /*load length of line */
- mov esi,srcptr /*load source */
- mov ebx,dstptr /*load dest */
-
- cmp ecx,0
- jz mainloop48end
-
-mainloop48:
- movq mm7,[esi]
- pand mm7,mm0
- movq mm6,mm0
- pandn mm6,[ebx]
- por mm7,mm6
- movq [ebx],mm7
-
- movq mm6,[esi+8]
- pand mm6,mm1
- movq mm7,mm1
- pandn mm7,[ebx+8]
- por mm6,mm7
- movq [ebx+8],mm6
-
- movq mm6,[esi+16]
- pand mm6,mm2
- movq mm7,mm2
- pandn mm7,[ebx+16]
- por mm6,mm7
- movq [ebx+16],mm6
-
- movq mm7,[esi+24]
- pand mm7,mm3
- movq mm6,mm3
- pandn mm6,[ebx+24]
- por mm7,mm6
- movq [ebx+24],mm7
-
- movq mm6,[esi+32]
- pand mm6,mm4
- movq mm7,mm4
- pandn mm7,[ebx+32]
- por mm6,mm7
- movq [ebx+32],mm6
-
- movq mm7,[esi+40]
- pand mm7,mm5
- movq mm6,mm5
- pandn mm6,[ebx+40]
- por mm7,mm6
- movq [ebx+40],mm7
-
- add esi,48 /*inc by 32 bytes processed */
- add ebx,48
- sub ecx,8 /*dec by 8 pixels processed */
-
- ja mainloop48
-mainloop48end:
-
- mov ecx,diff
- cmp ecx,0
- jz end48
-
- mov edx,mask
- sal edx,24 /*make low byte the high byte */
-
-secondloop48:
- sal edx,1 /*move high bit to CF */
- jnc skip48 /*if CF = 0 */
- mov eax,[esi]
- mov [ebx],eax
-skip48:
- add esi,4
- add ebx,4
-
- dec ecx
- jnz secondloop48
-
-end48:
- emms
- }
- }
- else /* mmx _not supported - Use modified C routine */
- {
- register unsigned int incr1, initial_val, final_val;
- png_size_t pixel_bytes;
- png_uint_32 i;
- register int disp = png_pass_inc[png_ptr->pass];
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
-
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dstptr, srcptr, pixel_bytes);
- srcptr += incr1;
- dstptr += incr1;
- }
- } /* end of else */
-
- break;
- } /* end 48 bpp */
-
- default:
- {
- png_bytep sptr;
- png_bytep dp;
- png_size_t pixel_bytes;
- int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
- unsigned int i;
- register int disp = png_pass_inc[png_ptr->pass]; /* get the offset */
- register unsigned int incr1, initial_val, final_val;
-
- pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
- sptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
- pixel_bytes;
- dp = row + offset_table[png_ptr->pass]*pixel_bytes;
- initial_val = offset_table[png_ptr->pass]*pixel_bytes;
- final_val = png_ptr->width*pixel_bytes;
- incr1 = (disp)*pixel_bytes;
- for (i = initial_val; i < final_val; i += incr1)
- {
- png_memcpy(dp, sptr, pixel_bytes);
- sptr += incr1;
- dp += incr1;
- }
- break;
- }
- } /* end switch (png_ptr->row_info.pixel_depth) */
- } /* end if (non-trivial mask) */
-
-} /* end png_combine_row() */
-
-
-#if defined(PNG_READ_INTERLACING_SUPPORTED)
-
-void /* PRIVATE */
-png_do_read_interlace(png_structp png_ptr)
-{
- png_row_infop row_info = &(png_ptr->row_info);
- png_bytep row = png_ptr->row_buf + 1;
- int pass = png_ptr->pass;
- png_uint_32 transformations = png_ptr->transformations;
-#ifdef PNG_USE_LOCAL_ARRAYS
- const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-#endif
-
- png_debug(1,"in png_do_read_interlace\n");
-
- if (mmx_supported == 2) {
- /* this should have happened in png_init_mmx_flags() already */
- png_warning(png_ptr, "asm_flags may not have been initialized");
- png_mmx_support();
- }
-
- if (row != NULL && row_info != NULL)
- {
- png_uint_32 final_width;
-
- final_width = row_info->width * png_pass_inc[pass];
-
- switch (row_info->pixel_depth)
- {
- case 1:
- {
- png_bytep sp, dp;
- int sshift, dshift;
- int s_start, s_end, s_inc;
- png_byte v;
- png_uint_32 i;
- int j;
-
- sp = row + (png_size_t)((row_info->width - 1) >> 3);
- dp = row + (png_size_t)((final_width - 1) >> 3);
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (transformations & PNG_PACKSWAP)
- {
- sshift = (int)((row_info->width + 7) & 7);
- dshift = (int)((final_width + 7) & 7);
- s_start = 7;
- s_end = 0;
- s_inc = -1;
- }
- else
-#endif
- {
- sshift = 7 - (int)((row_info->width + 7) & 7);
- dshift = 7 - (int)((final_width + 7) & 7);
- s_start = 0;
- s_end = 7;
- s_inc = 1;
- }
-
- for (i = row_info->width; i; i--)
- {
- v = (png_byte)((*sp >> sshift) & 0x1);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
- if (dshift == s_end)
- {
- dshift = s_start;
- dp--;
- }
- else
- dshift += s_inc;
- }
- if (sshift == s_end)
- {
- sshift = s_start;
- sp--;
- }
- else
- sshift += s_inc;
- }
- break;
- }
-
- case 2:
- {
- png_bytep sp, dp;
- int sshift, dshift;
- int s_start, s_end, s_inc;
- png_uint_32 i;
-
- sp = row + (png_size_t)((row_info->width - 1) >> 2);
- dp = row + (png_size_t)((final_width - 1) >> 2);
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (transformations & PNG_PACKSWAP)
- {
- sshift = (png_size_t)(((row_info->width + 3) & 3) << 1);
- dshift = (png_size_t)(((final_width + 3) & 3) << 1);
- s_start = 6;
- s_end = 0;
- s_inc = -2;
- }
- else
-#endif
- {
- sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
- dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
- s_start = 0;
- s_end = 6;
- s_inc = 2;
- }
-
- for (i = row_info->width; i; i--)
- {
- png_byte v;
- int j;
-
- v = (png_byte)((*sp >> sshift) & 0x3);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
- if (dshift == s_end)
- {
- dshift = s_start;
- dp--;
- }
- else
- dshift += s_inc;
- }
- if (sshift == s_end)
- {
- sshift = s_start;
- sp--;
- }
- else
- sshift += s_inc;
- }
- break;
- }
-
- case 4:
- {
- png_bytep sp, dp;
- int sshift, dshift;
- int s_start, s_end, s_inc;
- png_uint_32 i;
-
- sp = row + (png_size_t)((row_info->width - 1) >> 1);
- dp = row + (png_size_t)((final_width - 1) >> 1);
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (transformations & PNG_PACKSWAP)
- {
- sshift = (png_size_t)(((row_info->width + 1) & 1) << 2);
- dshift = (png_size_t)(((final_width + 1) & 1) << 2);
- s_start = 4;
- s_end = 0;
- s_inc = -4;
- }
- else
-#endif
- {
- sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
- dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
- s_start = 0;
- s_end = 4;
- s_inc = 4;
- }
-
- for (i = row_info->width; i; i--)
- {
- png_byte v;
- int j;
-
- v = (png_byte)((*sp >> sshift) & 0xf);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
- if (dshift == s_end)
- {
- dshift = s_start;
- dp--;
- }
- else
- dshift += s_inc;
- }
- if (sshift == s_end)
- {
- sshift = s_start;
- sp--;
- }
- else
- sshift += s_inc;
- }
- break;
- }
-
- default: /* This is the place where the routine is modified */
- {
- __int64 const4 = 0x0000000000FFFFFF;
- /* __int64 const5 = 0x000000FFFFFF0000; // unused... */
- __int64 const6 = 0x00000000000000FF;
- png_bytep sptr, dp;
- png_uint_32 i;
- png_size_t pixel_bytes;
- int width = row_info->width;
-
- pixel_bytes = (row_info->pixel_depth >> 3);
-
- sptr = row + (width - 1) * pixel_bytes;
- dp = row + (final_width - 1) * pixel_bytes;
- /* New code by Nirav Chhatrapati - Intel Corporation */
- /* sign fix by GRR */
- /* NOTE: there is NO MMX code for 48-bit and 64-bit images */
-
- /* use MMX routine if machine supports it */
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE)
- /* && mmx_supported */ )
- {
- if (pixel_bytes == 3)
- {
- if (((pass == 0) || (pass == 1)) && width)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width
- sub edi, 21 /* (png_pass_inc[pass] - 1)*pixel_bytes */
-loop_pass0:
- movd mm0, [esi] ; X X X X X v2 v1 v0
- pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0
- movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0
- psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0
- movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0
- psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0
- psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1
- por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0
- por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1
- movq mm3, mm0 ; v2 v1 v0 v2 v1 v0 v2 v1
- psllq mm0, 16 ; v0 v2 v1 v0 v2 v1 0 0
- movq mm4, mm3 ; v2 v1 v0 v2 v1 v0 v2 v1
- punpckhdq mm3, mm0 ; v0 v2 v1 v0 v2 v1 v0 v2
- movq [edi+16] , mm4
- psrlq mm0, 32 ; 0 0 0 0 v0 v2 v1 v0
- movq [edi+8] , mm3
- punpckldq mm0, mm4 ; v1 v0 v2 v1 v0 v2 v1 v0
- sub esi, 3
- movq [edi], mm0
- sub edi, 24
- /*sub esi, 3 */
- dec ecx
- jnz loop_pass0
- EMMS
- }
- }
- else if (((pass == 2) || (pass == 3)) && width)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width
- sub edi, 9 /* (png_pass_inc[pass] - 1)*pixel_bytes */
-loop_pass2:
- movd mm0, [esi] ; X X X X X v2 v1 v0
- pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0
- movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0
- psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0
- movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0
- psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0
- psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1
- por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0
- por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1
- movq [edi+4], mm0 ; move to memory
- psrlq mm0, 16 ; 0 0 v2 v1 v0 v2 v1 v0
- movd [edi], mm0 ; move to memory
- sub esi, 3
- sub edi, 12
- dec ecx
- jnz loop_pass2
- EMMS
- }
- }
- else if (width) /* && ((pass == 4) || (pass == 5)) */
- {
- int width_mmx = ((width >> 1) << 1) - 8;
- if (width_mmx < 0)
- width_mmx = 0;
- width -= width_mmx; /* 8 or 9 pix, 24 or 27 bytes */
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 3
- sub edi, 9
-loop_pass4:
- movq mm0, [esi] ; X X v2 v1 v0 v5 v4 v3
- movq mm7, mm0 ; X X v2 v1 v0 v5 v4 v3
- movq mm6, mm0 ; X X v2 v1 v0 v5 v4 v3
- psllq mm0, 24 ; v1 v0 v5 v4 v3 0 0 0
- pand mm7, const4 ; 0 0 0 0 0 v5 v4 v3
- psrlq mm6, 24 ; 0 0 0 X X v2 v1 v0
- por mm0, mm7 ; v1 v0 v5 v4 v3 v5 v4 v3
- movq mm5, mm6 ; 0 0 0 X X v2 v1 v0
- psllq mm6, 8 ; 0 0 X X v2 v1 v0 0
- movq [edi], mm0 ; move quad to memory
- psrlq mm5, 16 ; 0 0 0 0 0 X X v2
- pand mm5, const6 ; 0 0 0 0 0 0 0 v2
- por mm6, mm5 ; 0 0 X X v2 v1 v0 v2
- movd [edi+8], mm6 ; move double to memory
- sub esi, 6
- sub edi, 12
- sub ecx, 2
- jnz loop_pass4
- EMMS
- }
- }
-
- sptr -= width_mmx*3;
- dp -= width_mmx*6;
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
-
- png_memcpy(v, sptr, 3);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, 3);
- dp -= 3;
- }
- sptr -= 3;
- }
- }
- } /* end of pixel_bytes == 3 */
-
- else if (pixel_bytes == 1)
- {
- if (((pass == 0) || (pass == 1)) && width)
- {
- int width_mmx = ((width >> 2) << 2);
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub edi, 31
- sub esi, 3
-loop1_pass0:
- movd mm0, [esi] ; X X X X v0 v1 v2 v3
- movq mm1, mm0 ; X X X X v0 v1 v2 v3
- punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- movq mm2, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
- movq mm3, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
- punpckldq mm0, mm0 ; v3 v3 v3 v3 v3 v3 v3 v3
- punpckhdq mm3, mm3 ; v2 v2 v2 v2 v2 v2 v2 v2
- movq [edi], mm0 ; move to memory v3
- punpckhwd mm2, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1
- movq [edi+8], mm3 ; move to memory v2
- movq mm4, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1
- punpckldq mm2, mm2 ; v1 v1 v1 v1 v1 v1 v1 v1
- punpckhdq mm4, mm4 ; v0 v0 v0 v0 v0 v0 v0 v0
- movq [edi+16], mm2 ; move to memory v1
- movq [edi+24], mm4 ; move to memory v0
- sub esi, 4
- sub edi, 32
- sub ecx, 4
- jnz loop1_pass0
- EMMS
- }
- }
-
- sptr -= width_mmx;
- dp -= width_mmx*8;
- for (i = width; i; i--)
- {
- int j;
-
- /* I simplified this part in version 1.0.4e
- * here and in several other instances where
- * pixel_bytes == 1 -- GR-P
- *
- * Original code:
- *
- * png_byte v[8];
- * png_memcpy(v, sptr, pixel_bytes);
- * for (j = 0; j < png_pass_inc[pass]; j++)
- * {
- * png_memcpy(dp, v, pixel_bytes);
- * dp -= pixel_bytes;
- * }
- * sptr -= pixel_bytes;
- *
- * Replacement code is in the next three lines:
- */
-
- for (j = 0; j < png_pass_inc[pass]; j++)
- *dp-- = *sptr;
- sptr--;
- }
- }
- else if (((pass == 2) || (pass == 3)) && width)
- {
- int width_mmx = ((width >> 2) << 2);
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub edi, 15
- sub esi, 3
-loop1_pass2:
- movd mm0, [esi] ; X X X X v0 v1 v2 v3
- punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3
- punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3
- punpckhwd mm1, mm1 ; v0 v0 v0 v0 v1 v1 v1 v1
- movq [edi], mm0 ; move to memory v2 and v3
- sub esi, 4
- movq [edi+8], mm1 ; move to memory v1 and v0
- sub edi, 16
- sub ecx, 4
- jnz loop1_pass2
- EMMS
- }
- }
-
- sptr -= width_mmx;
- dp -= width_mmx*4;
- for (i = width; i; i--)
- {
- int j;
-
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp-- = *sptr;
- }
- sptr --;
- }
- }
- else if (width) /* && ((pass == 4) || (pass == 5))) */
- {
- int width_mmx = ((width >> 3) << 3);
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub edi, 15
- sub esi, 7
-loop1_pass4:
- movq mm0, [esi] ; v0 v1 v2 v3 v4 v5 v6 v7
- movq mm1, mm0 ; v0 v1 v2 v3 v4 v5 v6 v7
- punpcklbw mm0, mm0 ; v4 v4 v5 v5 v6 v6 v7 v7
- /*movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 */
- punpckhbw mm1, mm1 ;v0 v0 v1 v1 v2 v2 v3 v3
- movq [edi+8], mm1 ; move to memory v0 v1 v2 and v3
- sub esi, 8
- movq [edi], mm0 ; move to memory v4 v5 v6 and v7
- /*sub esi, 4 */
- sub edi, 16
- sub ecx, 8
- jnz loop1_pass4
- EMMS
- }
- }
-
- sptr -= width_mmx;
- dp -= width_mmx*2;
- for (i = width; i; i--)
- {
- int j;
-
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- *dp-- = *sptr;
- }
- sptr --;
- }
- }
- } /* end of pixel_bytes == 1 */
-
- else if (pixel_bytes == 2)
- {
- if (((pass == 0) || (pass == 1)) && width)
- {
- int width_mmx = ((width >> 1) << 1);
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 2
- sub edi, 30
-loop2_pass0:
- movd mm0, [esi] ; X X X X v1 v0 v3 v2
- punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2
- punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0
- movq [edi], mm0
- movq [edi + 8], mm0
- movq [edi + 16], mm1
- movq [edi + 24], mm1
- sub esi, 4
- sub edi, 32
- sub ecx, 2
- jnz loop2_pass0
- EMMS
- }
- }
-
- sptr -= (width_mmx*2 - 2); /* sign fixed */
- dp -= (width_mmx*16 - 2); /* sign fixed */
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 2;
- png_memcpy(v, sptr, 2);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 2;
- png_memcpy(dp, v, 2);
- }
- }
- }
- else if (((pass == 2) || (pass == 3)) && width)
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 2
- sub edi, 14
-loop2_pass2:
- movd mm0, [esi] ; X X X X v1 v0 v3 v2
- punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2
- punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0
- movq [edi], mm0
- sub esi, 4
- movq [edi + 8], mm1
- /*sub esi, 4 */
- sub edi, 16
- sub ecx, 2
- jnz loop2_pass2
- EMMS
- }
- }
-
- sptr -= (width_mmx*2 - 2); /* sign fixed */
- dp -= (width_mmx*8 - 2); /* sign fixed */
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 2;
- png_memcpy(v, sptr, 2);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 2;
- png_memcpy(dp, v, 2);
- }
- }
- }
- else if (width) /* pass == 4 or 5 */
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 2
- sub edi, 6
-loop2_pass4:
- movd mm0, [esi] ; X X X X v1 v0 v3 v2
- punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2
- sub esi, 4
- movq [edi], mm0
- sub edi, 8
- sub ecx, 2
- jnz loop2_pass4
- EMMS
- }
- }
-
- sptr -= (width_mmx*2 - 2); /* sign fixed */
- dp -= (width_mmx*4 - 2); /* sign fixed */
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 2;
- png_memcpy(v, sptr, 2);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 2;
- png_memcpy(dp, v, 2);
- }
- }
- }
- } /* end of pixel_bytes == 2 */
-
- else if (pixel_bytes == 4)
- {
- if (((pass == 0) || (pass == 1)) && width)
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 4
- sub edi, 60
-loop4_pass0:
- movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
- movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
- punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
- punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
- movq [edi], mm0
- movq [edi + 8], mm0
- movq [edi + 16], mm0
- movq [edi + 24], mm0
- movq [edi+32], mm1
- movq [edi + 40], mm1
- movq [edi+ 48], mm1
- sub esi, 8
- movq [edi + 56], mm1
- sub edi, 64
- sub ecx, 2
- jnz loop4_pass0
- EMMS
- }
- }
-
- sptr -= (width_mmx*4 - 4); /* sign fixed */
- dp -= (width_mmx*32 - 4); /* sign fixed */
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 4;
- png_memcpy(v, sptr, 4);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 4;
- png_memcpy(dp, v, 4);
- }
- }
- }
- else if (((pass == 2) || (pass == 3)) && width)
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 4
- sub edi, 28
-loop4_pass2:
- movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
- movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
- punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
- punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
- movq [edi], mm0
- movq [edi + 8], mm0
- movq [edi+16], mm1
- movq [edi + 24], mm1
- sub esi, 8
- sub edi, 32
- sub ecx, 2
- jnz loop4_pass2
- EMMS
- }
- }
-
- sptr -= (width_mmx*4 - 4); /* sign fixed */
- dp -= (width_mmx*16 - 4); /* sign fixed */
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 4;
- png_memcpy(v, sptr, 4);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 4;
- png_memcpy(dp, v, 4);
- }
- }
- }
- else if (width) /* pass == 4 or 5 */
- {
- int width_mmx = ((width >> 1) << 1) ;
- width -= width_mmx;
- if (width_mmx)
- {
- _asm
- {
- mov esi, sptr
- mov edi, dp
- mov ecx, width_mmx
- sub esi, 4
- sub edi, 12
-loop4_pass4:
- movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4
- movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4
- punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4
- punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0
- movq [edi], mm0
- sub esi, 8
- movq [edi + 8], mm1
- sub edi, 16
- sub ecx, 2
- jnz loop4_pass4
- EMMS
- }
- }
-
- sptr -= (width_mmx*4 - 4); /* sign fixed */
- dp -= (width_mmx*8 - 4); /* sign fixed */
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- sptr -= 4;
- png_memcpy(v, sptr, 4);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- dp -= 4;
- png_memcpy(dp, v, 4);
- }
- }
- }
-
- } /* end of pixel_bytes == 4 */
-
- else if (pixel_bytes == 6)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, 6);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, 6);
- dp -= 6;
- }
- sptr -= 6;
- }
- } /* end of pixel_bytes == 6 */
-
- else
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr-= pixel_bytes;
- }
- }
- } /* end of mmx_supported */
-
- else /* MMX not supported: use modified C code - takes advantage
- * of inlining of memcpy for a constant */
- {
- if (pixel_bytes == 1)
- {
- for (i = width; i; i--)
- {
- int j;
- for (j = 0; j < png_pass_inc[pass]; j++)
- *dp-- = *sptr;
- sptr--;
- }
- }
- else if (pixel_bytes == 3)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- else if (pixel_bytes == 2)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- else if (pixel_bytes == 4)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- else if (pixel_bytes == 6)
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
- else
- {
- for (i = width; i; i--)
- {
- png_byte v[8];
- int j;
- png_memcpy(v, sptr, pixel_bytes);
- for (j = 0; j < png_pass_inc[pass]; j++)
- {
- png_memcpy(dp, v, pixel_bytes);
- dp -= pixel_bytes;
- }
- sptr -= pixel_bytes;
- }
- }
-
- } /* end of MMX not supported */
- break;
- }
- } /* end switch (row_info->pixel_depth) */
-
- row_info->width = final_width;
- row_info->rowbytes = ((final_width *
- (png_uint_32)row_info->pixel_depth + 7) >> 3);
- }
-
-}
-
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
-
-
-/* These variables are utilized in the functions below. They are declared */
-/* globally here to ensure alignment on 8-byte boundaries. */
-
-union uAll {
- __int64 use;
- double align;
-} LBCarryMask = {0x0101010101010101},
- HBClearMask = {0x7f7f7f7f7f7f7f7f},
- ActiveMask, ActiveMask2, ActiveMaskEnd, ShiftBpp, ShiftRem;
-
-
-/* Optimized code for PNG Average filter decoder */
-void /* PRIVATE */
-png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row
- , png_bytep prev_row)
-{
- int bpp;
- png_uint_32 FullLength;
- png_uint_32 MMXLength;
- /*png_uint_32 len; */
- int diff;
-
- bpp = (row_info->pixel_depth + 7) >> 3; /* Get # bytes per pixel */
- FullLength = row_info->rowbytes; /* # of bytes to filter */
- _asm {
- /* Init address pointers and offset */
- mov edi, row /* edi ==> Avg(x) */
- xor ebx, ebx /* ebx ==> x */
- mov edx, edi
- mov esi, prev_row /* esi ==> Prior(x) */
- sub edx, bpp /* edx ==> Raw(x-bpp) */
-
- xor eax, eax
- /* Compute the Raw value for the first bpp bytes */
- /* Raw(x) = Avg(x) + (Prior(x)/2) */
-davgrlp:
- mov al, [esi + ebx] /* Load al with Prior(x) */
- inc ebx
- shr al, 1 /* divide by 2 */
- add al, [edi+ebx-1] /* Add Avg(x); -1 to offset inc ebx */
- cmp ebx, bpp
- mov [edi+ebx-1], al /* Write back Raw(x); */
- /* mov does not affect flags; -1 to offset inc ebx */
- jb davgrlp
- /* get # of bytes to alignment */
- mov diff, edi /* take start of row */
- add diff, ebx /* add bpp */
- add diff, 0xf /* add 7 + 8 to incr past alignment boundary */
- and diff, 0xfffffff8 /* mask to alignment boundary */
- sub diff, edi /* subtract from start ==> value ebx at alignment */
- jz davggo
- /* fix alignment */
- /* Compute the Raw value for the bytes upto the alignment boundary */
- /* Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) */
- xor ecx, ecx
-davglp1:
- xor eax, eax
- mov cl, [esi + ebx] /* load cl with Prior(x) */
- mov al, [edx + ebx] /* load al with Raw(x-bpp) */
- add ax, cx
- inc ebx
- shr ax, 1 /* divide by 2 */
- add al, [edi+ebx-1] /* Add Avg(x); -1 to offset inc ebx */
- cmp ebx, diff /* Check if at alignment boundary */
- mov [edi+ebx-1], al /* Write back Raw(x); */
- /* mov does not affect flags; -1 to offset inc ebx */
- jb davglp1 /* Repeat until at alignment boundary */
-davggo:
- mov eax, FullLength
- mov ecx, eax
- sub eax, ebx /* subtract alignment fix */
- and eax, 0x00000007 /* calc bytes over mult of 8 */
- sub ecx, eax /* drop over bytes from original length */
- mov MMXLength, ecx
- } /* end _asm block */
- /* Now do the math for the rest of the row */
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000000000ffffff;
- ShiftBpp.use = 24; /* == 3 * 8 */
- ShiftRem.use = 40; /* == 64 - 24 */
- _asm {
- /* Re-init address pointers and offset */
- movq mm7, ActiveMask
- mov ebx, diff /* ebx ==> x = offset to alignment boundary */
- movq mm5, LBCarryMask
- mov edi, row /* edi ==> Avg(x) */
- movq mm4, HBClearMask
- mov esi, prev_row /* esi ==> Prior(x) */
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm2, [edi + ebx - 8] /* Load previous aligned 8 bytes */
- /* (we correct position in loop below) */
-davg3lp:
- movq mm0, [edi + ebx] /* Load mm0 with Avg(x) */
- /* Add (Prev_row/2) to Average */
- movq mm3, mm5
- psrlq mm2, ShiftRem /* Correct position Raw(x-bpp) data */
- movq mm1, [esi + ebx] /* Load mm1 with Prior(x) */
- movq mm6, mm7
- pand mm3, mm1 /* get lsb for each prev_row byte */
- psrlq mm1, 1 /* divide prev_row bytes by 2 */
- pand mm1, mm4 /* clear invalid bit 7 of each byte */
- paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
- /* Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry */
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm6 /* Leave only Active Group 1 bytes to add to Avg */
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
- /* byte */
- /* Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry */
- psllq mm6, ShiftBpp /* shift the mm6 mask to cover bytes 3-5 */
- movq mm2, mm0 /* mov updated Raws to mm2 */
- psllq mm2, ShiftBpp /* shift data to position correctly */
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
- /* byte */
-
- /* Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry */
- psllq mm6, ShiftBpp /* shift the mm6 mask to cover the last two */
- /* bytes */
- movq mm2, mm0 /* mov updated Raws to mm2 */
- psllq mm2, ShiftBpp /* shift data to position correctly */
- /* Data only needs to be shifted once here to */
- /* get the correct x-bpp offset. */
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
- add ebx, 8
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
- /* byte */
-
- /* Now ready to write back to memory */
- movq [edi + ebx - 8], mm0
- /* Move updated Raw(x) to use as Raw(x-bpp) for next loop */
- cmp ebx, MMXLength
- movq mm2, mm0 /* mov updated Raw(x) to mm2 */
- jb davg3lp
- } /* end _asm block */
- }
- break;
-
- case 6:
- case 4:
- case 7:
- case 5:
- {
- ActiveMask.use = 0xffffffffffffffff; /* use shift below to clear */
- /* appropriate inactive bytes */
- ShiftBpp.use = bpp << 3;
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm {
- movq mm4, HBClearMask
- /* Re-init address pointers and offset */
- mov ebx, diff /* ebx ==> x = offset to alignment boundary */
- /* Load ActiveMask and clear all bytes except for 1st active group */
- movq mm7, ActiveMask
- mov edi, row /* edi ==> Avg(x) */
- psrlq mm7, ShiftRem
- mov esi, prev_row /* esi ==> Prior(x) */
- movq mm6, mm7
- movq mm5, LBCarryMask
- psllq mm6, ShiftBpp /* Create mask for 2nd active group */
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm2, [edi + ebx - 8] /* Load previous aligned 8 bytes */
- /* (we correct position in loop below) */
-davg4lp:
- movq mm0, [edi + ebx]
- psrlq mm2, ShiftRem /* shift data to position correctly */
- movq mm1, [esi + ebx]
- /* Add (Prev_row/2) to Average */
- movq mm3, mm5
- pand mm3, mm1 /* get lsb for each prev_row byte */
- psrlq mm1, 1 /* divide prev_row bytes by 2 */
- pand mm1, mm4 /* clear invalid bit 7 of each byte */
- paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
- /* Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry */
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm7 /* Leave only Active Group 1 bytes to add to Avg */
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
- /* byte */
- /* Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry */
- movq mm2, mm0 /* mov updated Raws to mm2 */
- psllq mm2, ShiftBpp /* shift data to position correctly */
- add ebx, 8
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active */
- /* byte */
- cmp ebx, MMXLength
- /* Now ready to write back to memory */
- movq [edi + ebx - 8], mm0
- /* Prep Raw(x-bpp) for next loop */
- movq mm2, mm0 /* mov updated Raws to mm2 */
- jb davg4lp
- } /* end _asm block */
- }
- break;
- case 2:
- {
- ActiveMask.use = 0x000000000000ffff;
- ShiftBpp.use = 16; /* == 2 * 8 [BUGFIX] */
- ShiftRem.use = 48; /* == 64 - 16 [BUGFIX] */
- _asm {
- /* Load ActiveMask */
- movq mm7, ActiveMask
- /* Re-init address pointers and offset */
- mov ebx, diff /* ebx ==> x = offset to alignment boundary */
- movq mm5, LBCarryMask
- mov edi, row /* edi ==> Avg(x) */
- movq mm4, HBClearMask
- mov esi, prev_row /* esi ==> Prior(x) */
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm2, [edi + ebx - 8] /* Load previous aligned 8 bytes */
- /* (we correct position in loop below) */
-davg2lp:
- movq mm0, [edi + ebx]
- psrlq mm2, ShiftRem /* shift data to position correctly [BUGFIX] */
- movq mm1, [esi + ebx]
- /* Add (Prev_row/2) to Average */
- movq mm3, mm5
- pand mm3, mm1 /* get lsb for each prev_row byte */
- psrlq mm1, 1 /* divide prev_row bytes by 2 */
- pand mm1, mm4 /* clear invalid bit 7 of each byte */
- movq mm6, mm7
- paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
- /* Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry */
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm6 /* Leave only Active Group 1 bytes to add to Avg */
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active byte */
- /* Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry */
- psllq mm6, ShiftBpp /* shift the mm6 mask to cover bytes 2 & 3 */
- movq mm2, mm0 /* mov updated Raws to mm2 */
- psllq mm2, ShiftBpp /* shift data to position correctly */
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active byte */
-
- /* Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry */
- psllq mm6, ShiftBpp /* shift the mm6 mask to cover bytes 4 & 5 */
- movq mm2, mm0 /* mov updated Raws to mm2 */
- psllq mm2, ShiftBpp /* shift data to position correctly */
- /* Data only needs to be shifted once here to */
- /* get the correct x-bpp offset. */
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active byte */
-
- /* Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry */
- psllq mm6, ShiftBpp /* shift the mm6 mask to cover bytes 6 & 7 */
- movq mm2, mm0 /* mov updated Raws to mm2 */
- psllq mm2, ShiftBpp /* shift data to position correctly */
- /* Data only needs to be shifted once here to */
- /* get the correct x-bpp offset. */
- add ebx, 8
- movq mm1, mm3 /* now use mm1 for getting LBCarrys */
- pand mm1, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 (Only valid for active group) */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm2, mm1 /* add LBCarrys to (Raw(x-bpp)/2) for each byte */
- pand mm2, mm6 /* Leave only Active Group 2 bytes to add to Avg */
- paddb mm0, mm2 /* add (Raw/2) + LBCarrys to Avg for each Active byte */
-
- cmp ebx, MMXLength
- /* Now ready to write back to memory */
- movq [edi + ebx - 8], mm0
- /* Prep Raw(x-bpp) for next loop */
- movq mm2, mm0 /* mov updated Raws to mm2 */
- jb davg2lp
- } /* end _asm block */
- }
- break;
-
- case 1: /* bpp == 1 */
- {
- _asm {
- /* Re-init address pointers and offset */
- mov ebx, diff /* ebx ==> x = offset to alignment boundary */
- mov edi, row /* edi ==> Avg(x) */
- cmp ebx, FullLength /* Test if offset at end of array */
- jnb davg1end
- /* Do Paeth decode for remaining bytes */
- mov esi, prev_row /* esi ==> Prior(x) */
- mov edx, edi
- xor ecx, ecx /* zero ecx before using cl & cx in loop below */
- sub edx, bpp /* edx ==> Raw(x-bpp) */
-davg1lp:
- /* Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) */
- xor eax, eax
- mov cl, [esi + ebx] /* load cl with Prior(x) */
- mov al, [edx + ebx] /* load al with Raw(x-bpp) */
- add ax, cx
- inc ebx
- shr ax, 1 /* divide by 2 */
- add al, [edi+ebx-1] /* Add Avg(x); -1 to offset inc ebx */
- cmp ebx, FullLength /* Check if at end of array */
- mov [edi+ebx-1], al /* Write back Raw(x); */
- /* mov does not affect flags; -1 to offset inc ebx */
- jb davg1lp
-davg1end:
- } /* end _asm block */
- }
- return;
-
- case 8: /* bpp == 8 */
- {
- _asm {
- /* Re-init address pointers and offset */
- mov ebx, diff /* ebx ==> x = offset to alignment boundary */
- movq mm5, LBCarryMask
- mov edi, row /* edi ==> Avg(x) */
- movq mm4, HBClearMask
- mov esi, prev_row /* esi ==> Prior(x) */
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm2, [edi + ebx - 8] /* Load previous aligned 8 bytes */
- /* (NO NEED to correct position in loop below) */
-davg8lp:
- movq mm0, [edi + ebx]
- movq mm3, mm5
- movq mm1, [esi + ebx]
- add ebx, 8
- pand mm3, mm1 /* get lsb for each prev_row byte */
- psrlq mm1, 1 /* divide prev_row bytes by 2 */
- pand mm3, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm1, mm4 /* clear invalid bit 7 of each byte */
- paddb mm0, mm3 /* add LBCarrys to Avg for each byte */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
- paddb mm0, mm2 /* add (Raw/2) to Avg for each byte */
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm0
- movq mm2, mm0 /* reuse as Raw(x-bpp) */
- jb davg8lp
- } /* end _asm block */
- }
- break;
- default: /* bpp greater than 8 */
- {
- _asm {
- movq mm5, LBCarryMask
- /* Re-init address pointers and offset */
- mov ebx, diff /* ebx ==> x = offset to alignment boundary */
- mov edi, row /* edi ==> Avg(x) */
- movq mm4, HBClearMask
- mov edx, edi
- mov esi, prev_row /* esi ==> Prior(x) */
- sub edx, bpp /* edx ==> Raw(x-bpp) */
-davgAlp:
- movq mm0, [edi + ebx]
- movq mm3, mm5
- movq mm1, [esi + ebx]
- pand mm3, mm1 /* get lsb for each prev_row byte */
- movq mm2, [edx + ebx]
- psrlq mm1, 1 /* divide prev_row bytes by 2 */
- pand mm3, mm2 /* get LBCarrys for each byte where both */
- /* lsb's were == 1 */
- psrlq mm2, 1 /* divide raw bytes by 2 */
- pand mm1, mm4 /* clear invalid bit 7 of each byte */
- paddb mm0, mm3 /* add LBCarrys to Avg for each byte */
- pand mm2, mm4 /* clear invalid bit 7 of each byte */
- paddb mm0, mm1 /* add (Prev_row/2) to Avg for each byte */
- add ebx, 8
- paddb mm0, mm2 /* add (Raw/2) to Avg for each byte */
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm0
- jb davgAlp
- } /* end _asm block */
- }
- break;
- } /* end switch ( bpp ) */
-
- _asm {
- /* MMX acceleration complete now do clean-up */
- /* Check if any remaining bytes left to decode */
- mov ebx, MMXLength /* ebx ==> x = offset bytes remaining after MMX */
- mov edi, row /* edi ==> Avg(x) */
- cmp ebx, FullLength /* Test if offset at end of array */
- jnb davgend
- /* Do Paeth decode for remaining bytes */
- mov esi, prev_row /* esi ==> Prior(x) */
- mov edx, edi
- xor ecx, ecx /* zero ecx before using cl & cx in loop below */
- sub edx, bpp /* edx ==> Raw(x-bpp) */
-davglp2:
- /* Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) */
- xor eax, eax
- mov cl, [esi + ebx] /* load cl with Prior(x) */
- mov al, [edx + ebx] /* load al with Raw(x-bpp) */
- add ax, cx
- inc ebx
- shr ax, 1 /* divide by 2 */
- add al, [edi+ebx-1] /* Add Avg(x); -1 to offset inc ebx */
- cmp ebx, FullLength /* Check if at end of array */
- mov [edi+ebx-1], al /* Write back Raw(x); */
- /* mov does not affect flags; -1 to offset inc ebx */
- jb davglp2
-davgend:
- emms /* End MMX instructions; prep for possible FP instrs. */
- } /* end _asm block */
-}
-
-/* Optimized code for PNG Paeth filter decoder */
-void /* PRIVATE */
-png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
- png_bytep prev_row)
-{
- png_uint_32 FullLength;
- png_uint_32 MMXLength;
- /*png_uint_32 len; */
- int bpp;
- int diff;
- /*int ptemp; */
- int patemp, pbtemp, pctemp;
-
- bpp = (row_info->pixel_depth + 7) >> 3; /* Get # bytes per pixel */
- FullLength = row_info->rowbytes; /* # of bytes to filter */
- _asm
- {
- xor ebx, ebx /* ebx ==> x offset */
- mov edi, row
- xor edx, edx /* edx ==> x-bpp offset */
- mov esi, prev_row
- xor eax, eax
-
- /* Compute the Raw value for the first bpp bytes */
- /* Note: the formula works out to be always */
- /* Paeth(x) = Raw(x) + Prior(x) where x < bpp */
-dpthrlp:
- mov al, [edi + ebx]
- add al, [esi + ebx]
- inc ebx
- cmp ebx, bpp
- mov [edi + ebx - 1], al
- jb dpthrlp
- /* get # of bytes to alignment */
- mov diff, edi /* take start of row */
- add diff, ebx /* add bpp */
- xor ecx, ecx
- add diff, 0xf /* add 7 + 8 to incr past alignment boundary */
- and diff, 0xfffffff8 /* mask to alignment boundary */
- sub diff, edi /* subtract from start ==> value ebx at alignment */
- jz dpthgo
- /* fix alignment */
-dpthlp1:
- xor eax, eax
- /* pav = p - a = (a + b - c) - a = b - c */
- mov al, [esi + ebx] /* load Prior(x) into al */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- sub eax, ecx /* subtract Prior(x-bpp) */
- mov patemp, eax /* Save pav for later use */
- xor eax, eax
- /* pbv = p - b = (a + b - c) - b = a - c */
- mov al, [edi + edx] /* load Raw(x-bpp) into al */
- sub eax, ecx /* subtract Prior(x-bpp) */
- mov ecx, eax
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- add eax, patemp /* pcv = pav + pbv */
- /* pc = abs(pcv) */
- test eax, 0x80000000
- jz dpthpca
- neg eax /* reverse sign of neg values */
-dpthpca:
- mov pctemp, eax /* save pc for later use */
- /* pb = abs(pbv) */
- test ecx, 0x80000000
- jz dpthpba
- neg ecx /* reverse sign of neg values */
-dpthpba:
- mov pbtemp, ecx /* save pb for later use */
- /* pa = abs(pav) */
- mov eax, patemp
- test eax, 0x80000000
- jz dpthpaa
- neg eax /* reverse sign of neg values */
-dpthpaa:
- mov patemp, eax /* save pa for later use */
- /* test if pa <= pb */
- cmp eax, ecx
- jna dpthabb
- /* pa > pb; now test if pb <= pc */
- cmp ecx, pctemp
- jna dpthbbc
- /* pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- jmp dpthpaeth
-dpthbbc:
- /* pb <= pc; Raw(x) = Paeth(x) + Prior(x) */
- mov cl, [esi + ebx] /* load Prior(x) into cl */
- jmp dpthpaeth
-dpthabb:
- /* pa <= pb; now test if pa <= pc */
- cmp eax, pctemp
- jna dpthabc
- /* pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- jmp dpthpaeth
-dpthabc:
- /* pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) */
- mov cl, [edi + edx] /* load Raw(x-bpp) into cl */
-dpthpaeth:
- inc ebx
- inc edx
- /* Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 */
- add [edi + ebx - 1], cl
- cmp ebx, diff
- jb dpthlp1
-dpthgo:
- mov ecx, FullLength
- mov eax, ecx
- sub eax, ebx /* subtract alignment fix */
- and eax, 0x00000007 /* calc bytes over mult of 8 */
- sub ecx, eax /* drop over bytes from original length */
- mov MMXLength, ecx
- } /* end _asm block */
- /* Now do the math for the rest of the row */
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000000000ffffff;
- ActiveMaskEnd.use = 0xffff000000000000;
- ShiftBpp.use = 24; /* == bpp(3) * 8 */
- ShiftRem.use = 40; /* == 64 - 24 */
- _asm
- {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm1, [edi+ebx-8]
-dpth3lp:
- psrlq mm1, ShiftRem /* shift last 3 bytes to 1st 3 bytes */
- movq mm2, [esi + ebx] /* load b=Prior(x) */
- punpcklbw mm1, mm0 /* Unpack High bytes of a */
- movq mm3, [esi+ebx-8] /* Prep c=Prior(x-bpp) bytes */
- punpcklbw mm2, mm0 /* Unpack High bytes of b */
- psrlq mm3, ShiftRem /* shift last 3 bytes to 1st 3 bytes */
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- punpcklbw mm3, mm0 /* Unpack High bytes of c */
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- movq mm6, mm4
- psubw mm5, mm3
-
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
- paddw mm6, mm5
- pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
- pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
- psubw mm4, mm0
- pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm5, mm7
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx] /* load c=Prior(x-bpp) */
- pand mm7, ActiveMask
- movq mm2, mm3 /* load b=Prior(x) step 1 */
- paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
- punpcklbw mm3, mm0 /* Unpack High bytes of c */
- movq [edi + ebx], mm7 /* write back updated value */
- movq mm1, mm7 /* Now mm1 will be used as Raw(x-bpp) */
- /* Now do Paeth for 2nd set of bytes (3-5) */
- psrlq mm2, ShiftBpp /* load b=Prior(x) step 2 */
- punpcklbw mm1, mm0 /* Unpack High bytes of a */
- pxor mm7, mm7
- punpcklbw mm2, mm0 /* Unpack High bytes of b */
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- psubw mm5, mm3
- psubw mm4, mm3
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = */
- /* pav + pbv = pbv + pav */
- movq mm6, mm5
- paddw mm6, mm4
-
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm5 /* Create mask pbv bytes < 0 */
- pcmpgtw mm7, mm4 /* Create mask pav bytes < 0 */
- pand mm0, mm5 /* Only pbv bytes < 0 in mm0 */
- pand mm7, mm4 /* Only pav bytes < 0 in mm7 */
- psubw mm5, mm0
- psubw mm4, mm7
- psubw mm5, mm0
- psubw mm4, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- movq mm2, [esi + ebx] /* load b=Prior(x) */
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, mm2 /* load c=Prior(x-bpp) step 1 */
- pand mm7, ActiveMask
- punpckhbw mm2, mm0 /* Unpack High bytes of b */
- psllq mm7, ShiftBpp /* Shift bytes to 2nd group of 3 bytes */
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
- psllq mm3, ShiftBpp /* load c=Prior(x-bpp) step 2 */
- movq [edi + ebx], mm7 /* write back updated value */
- movq mm1, mm7
- punpckhbw mm3, mm0 /* Unpack High bytes of c */
- psllq mm1, ShiftBpp /* Shift bytes */
- /* Now mm1 will be used as Raw(x-bpp) */
- /* Now do Paeth for 3rd, and final, set of bytes (6-7) */
- pxor mm7, mm7
- punpckhbw mm1, mm0 /* Unpack High bytes of a */
- psubw mm4, mm3
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- movq mm6, mm4
- psubw mm5, mm3
- pxor mm0, mm0
- paddw mm6, mm5
-
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
- pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
- pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
- pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
- psubw mm4, mm0
- psubw mm5, mm7
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- pandn mm0, mm1
- pandn mm7, mm4
- paddw mm0, mm2
- paddw mm7, mm5
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm1, mm1
- packuswb mm1, mm7
- /* Step ebx to next set of 8 bytes and repeat loop til done */
- add ebx, 8
- pand mm1, ActiveMaskEnd
- paddb mm1, [edi + ebx - 8] /* add Paeth predictor with Raw(x) */
-
- cmp ebx, MMXLength
- pxor mm0, mm0 /* pxor does not affect flags */
- movq [edi + ebx - 8], mm1 /* write back updated value */
- /* mm1 will be used as Raw(x-bpp) next loop */
- /* mm3 ready to be used as Prior(x-bpp) next loop */
- jb dpth3lp
- } /* end _asm block */
- }
- break;
-
- case 6:
- case 7:
- case 5:
- {
- ActiveMask.use = 0x00000000ffffffff;
- ActiveMask2.use = 0xffffffff00000000;
- ShiftBpp.use = bpp << 3; /* == bpp * 8 */
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm
- {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm1, [edi+ebx-8]
- pxor mm0, mm0
-dpth6lp:
- /* Must shift to position Raw(x-bpp) data */
- psrlq mm1, ShiftRem
- /* Do first set of 4 bytes */
- movq mm3, [esi+ebx-8] /* read c=Prior(x-bpp) bytes */
- punpcklbw mm1, mm0 /* Unpack Low bytes of a */
- movq mm2, [esi + ebx] /* load b=Prior(x) */
- punpcklbw mm2, mm0 /* Unpack Low bytes of b */
- /* Must shift to position Prior(x-bpp) data */
- psrlq mm3, ShiftRem
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- punpcklbw mm3, mm0 /* Unpack Low bytes of c */
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- movq mm6, mm4
- psubw mm5, mm3
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
- paddw mm6, mm5
- pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
- pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
- psubw mm4, mm0
- pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm5, mm7
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx - 8] /* load c=Prior(x-bpp) */
- pand mm7, ActiveMask
- psrlq mm3, ShiftRem
- movq mm2, [esi + ebx] /* load b=Prior(x) step 1 */
- paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
- movq mm6, mm2
- movq [edi + ebx], mm7 /* write back updated value */
- movq mm1, [edi+ebx-8]
- psllq mm6, ShiftBpp
- movq mm5, mm7
- psrlq mm1, ShiftRem
- por mm3, mm6
- psllq mm5, ShiftBpp
- punpckhbw mm3, mm0 /* Unpack High bytes of c */
- por mm1, mm5
- /* Do second set of 4 bytes */
- punpckhbw mm2, mm0 /* Unpack High bytes of b */
- punpckhbw mm1, mm0 /* Unpack High bytes of a */
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- movq mm6, mm4
- psubw mm5, mm3
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
- paddw mm6, mm5
- pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
- pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
- psubw mm4, mm0
- pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm5, mm7
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- /* Step ex to next set of 8 bytes and repeat loop til done */
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] /* add Paeth predictor with Raw(x) */
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 /* write back updated value */
- /* mm1 will be used as Raw(x-bpp) next loop */
- jb dpth6lp
- } /* end _asm block */
- }
- break;
-
- case 4:
- {
- ActiveMask.use = 0x00000000ffffffff;
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm1, [edi+ebx-8] /* Only time should need to read */
- /* a=Raw(x-bpp) bytes */
-dpth4lp:
- /* Do first set of 4 bytes */
- movq mm3, [esi+ebx-8] /* read c=Prior(x-bpp) bytes */
- punpckhbw mm1, mm0 /* Unpack Low bytes of a */
- movq mm2, [esi + ebx] /* load b=Prior(x) */
- punpcklbw mm2, mm0 /* Unpack High bytes of b */
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- punpckhbw mm3, mm0 /* Unpack High bytes of c */
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- movq mm6, mm4
- psubw mm5, mm3
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
- paddw mm6, mm5
- pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
- pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
- psubw mm4, mm0
- pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm5, mm7
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi + ebx] /* load c=Prior(x-bpp) */
- pand mm7, ActiveMask
- movq mm2, mm3 /* load b=Prior(x) step 1 */
- paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
- punpcklbw mm3, mm0 /* Unpack High bytes of c */
- movq [edi + ebx], mm7 /* write back updated value */
- movq mm1, mm7 /* Now mm1 will be used as Raw(x-bpp) */
- /* Do second set of 4 bytes */
- punpckhbw mm2, mm0 /* Unpack Low bytes of b */
- punpcklbw mm1, mm0 /* Unpack Low bytes of a */
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- movq mm6, mm4
- psubw mm5, mm3
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
- paddw mm6, mm5
- pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
- pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
- psubw mm4, mm0
- pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm5, mm7
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- /* Step ex to next set of 8 bytes and repeat loop til done */
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] /* add Paeth predictor with Raw(x) */
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 /* write back updated value */
- /* mm1 will be used as Raw(x-bpp) next loop */
- jb dpth4lp
- } /* end _asm block */
- }
- break;
- case 8: /* bpp == 8 */
- {
- ActiveMask.use = 0x00000000ffffffff;
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, prev_row
- pxor mm0, mm0
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm1, [edi+ebx-8] /* Only time should need to read */
- /* a=Raw(x-bpp) bytes */
-dpth8lp:
- /* Do first set of 4 bytes */
- movq mm3, [esi+ebx-8] /* read c=Prior(x-bpp) bytes */
- punpcklbw mm1, mm0 /* Unpack Low bytes of a */
- movq mm2, [esi + ebx] /* load b=Prior(x) */
- punpcklbw mm2, mm0 /* Unpack Low bytes of b */
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- punpcklbw mm3, mm0 /* Unpack Low bytes of c */
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- movq mm6, mm4
- psubw mm5, mm3
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
- paddw mm6, mm5
- pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
- pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
- psubw mm4, mm0
- pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm5, mm7
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- paddw mm7, mm3
- pxor mm0, mm0
- packuswb mm7, mm1
- movq mm3, [esi+ebx-8] /* read c=Prior(x-bpp) bytes */
- pand mm7, ActiveMask
- movq mm2, [esi + ebx] /* load b=Prior(x) */
- paddb mm7, [edi + ebx] /* add Paeth predictor with Raw(x) */
- punpckhbw mm3, mm0 /* Unpack High bytes of c */
- movq [edi + ebx], mm7 /* write back updated value */
- movq mm1, [edi+ebx-8] /* read a=Raw(x-bpp) bytes */
-
- /* Do second set of 4 bytes */
- punpckhbw mm2, mm0 /* Unpack High bytes of b */
- punpckhbw mm1, mm0 /* Unpack High bytes of a */
- /* pav = p - a = (a + b - c) - a = b - c */
- movq mm4, mm2
- /* pbv = p - b = (a + b - c) - b = a - c */
- movq mm5, mm1
- psubw mm4, mm3
- pxor mm7, mm7
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- movq mm6, mm4
- psubw mm5, mm3
- /* pa = abs(p-a) = abs(pav) */
- /* pb = abs(p-b) = abs(pbv) */
- /* pc = abs(p-c) = abs(pcv) */
- pcmpgtw mm0, mm4 /* Create mask pav bytes < 0 */
- paddw mm6, mm5
- pand mm0, mm4 /* Only pav bytes < 0 in mm7 */
- pcmpgtw mm7, mm5 /* Create mask pbv bytes < 0 */
- psubw mm4, mm0
- pand mm7, mm5 /* Only pbv bytes < 0 in mm0 */
- psubw mm4, mm0
- psubw mm5, mm7
- pxor mm0, mm0
- pcmpgtw mm0, mm6 /* Create mask pcv bytes < 0 */
- pand mm0, mm6 /* Only pav bytes < 0 in mm7 */
- psubw mm5, mm7
- psubw mm6, mm0
- /* test pa <= pb */
- movq mm7, mm4
- psubw mm6, mm0
- pcmpgtw mm7, mm5 /* pa > pb? */
- movq mm0, mm7
- /* use mm7 mask to merge pa & pb */
- pand mm5, mm7
- /* use mm0 mask copy to merge a & b */
- pand mm2, mm0
- pandn mm7, mm4
- pandn mm0, mm1
- paddw mm7, mm5
- paddw mm0, mm2
- /* test ((pa <= pb)? pa:pb) <= pc */
- pcmpgtw mm7, mm6 /* pab > pc? */
- pxor mm1, mm1
- pand mm3, mm7
- pandn mm7, mm0
- pxor mm1, mm1
- paddw mm7, mm3
- pxor mm0, mm0
- /* Step ex to next set of 8 bytes and repeat loop til done */
- add ebx, 8
- packuswb mm1, mm7
- paddb mm1, [edi + ebx - 8] /* add Paeth predictor with Raw(x) */
- cmp ebx, MMXLength
- movq [edi + ebx - 8], mm1 /* write back updated value */
- /* mm1 will be used as Raw(x-bpp) next loop */
- jb dpth8lp
- } /* end _asm block */
- }
- break;
-
- case 1: /* bpp = 1 */
- case 2: /* bpp = 2 */
- default: /* bpp > 8 */
- {
- _asm {
- mov ebx, diff
- cmp ebx, FullLength
- jnb dpthdend
- mov edi, row
- mov esi, prev_row
- /* Do Paeth decode for remaining bytes */
- mov edx, ebx
- xor ecx, ecx /* zero ecx before using cl & cx in loop below */
- sub edx, bpp /* Set edx = ebx - bpp */
-dpthdlp:
- xor eax, eax
- /* pav = p - a = (a + b - c) - a = b - c */
- mov al, [esi + ebx] /* load Prior(x) into al */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- sub eax, ecx /* subtract Prior(x-bpp) */
- mov patemp, eax /* Save pav for later use */
- xor eax, eax
- /* pbv = p - b = (a + b - c) - b = a - c */
- mov al, [edi + edx] /* load Raw(x-bpp) into al */
- sub eax, ecx /* subtract Prior(x-bpp) */
- mov ecx, eax
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- add eax, patemp /* pcv = pav + pbv */
- /* pc = abs(pcv) */
- test eax, 0x80000000
- jz dpthdpca
- neg eax /* reverse sign of neg values */
-dpthdpca:
- mov pctemp, eax /* save pc for later use */
- /* pb = abs(pbv) */
- test ecx, 0x80000000
- jz dpthdpba
- neg ecx /* reverse sign of neg values */
-dpthdpba:
- mov pbtemp, ecx /* save pb for later use */
- /* pa = abs(pav) */
- mov eax, patemp
- test eax, 0x80000000
- jz dpthdpaa
- neg eax /* reverse sign of neg values */
-dpthdpaa:
- mov patemp, eax /* save pa for later use */
- /* test if pa <= pb */
- cmp eax, ecx
- jna dpthdabb
- /* pa > pb; now test if pb <= pc */
- cmp ecx, pctemp
- jna dpthdbbc
- /* pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- jmp dpthdpaeth
-dpthdbbc:
- /* pb <= pc; Raw(x) = Paeth(x) + Prior(x) */
- mov cl, [esi + ebx] /* load Prior(x) into cl */
- jmp dpthdpaeth
-dpthdabb:
- /* pa <= pb; now test if pa <= pc */
- cmp eax, pctemp
- jna dpthdabc
- /* pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- jmp dpthdpaeth
-dpthdabc:
- /* pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) */
- mov cl, [edi + edx] /* load Raw(x-bpp) into cl */
-dpthdpaeth:
- inc ebx
- inc edx
- /* Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 */
- add [edi + ebx - 1], cl
- cmp ebx, FullLength
- jb dpthdlp
-dpthdend:
- } /* end _asm block */
- }
- return; /* No need to go further with this one */
- } /* end switch ( bpp ) */
- _asm
- {
- /* MMX acceleration complete now do clean-up */
- /* Check if any remaining bytes left to decode */
- mov ebx, MMXLength
- cmp ebx, FullLength
- jnb dpthend
- mov edi, row
- mov esi, prev_row
- /* Do Paeth decode for remaining bytes */
- mov edx, ebx
- xor ecx, ecx /* zero ecx before using cl & cx in loop below */
- sub edx, bpp /* Set edx = ebx - bpp */
-dpthlp2:
- xor eax, eax
- /* pav = p - a = (a + b - c) - a = b - c */
- mov al, [esi + ebx] /* load Prior(x) into al */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- sub eax, ecx /* subtract Prior(x-bpp) */
- mov patemp, eax /* Save pav for later use */
- xor eax, eax
- /* pbv = p - b = (a + b - c) - b = a - c */
- mov al, [edi + edx] /* load Raw(x-bpp) into al */
- sub eax, ecx /* subtract Prior(x-bpp) */
- mov ecx, eax
- /* pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv */
- add eax, patemp /* pcv = pav + pbv */
- /* pc = abs(pcv) */
- test eax, 0x80000000
- jz dpthpca2
- neg eax /* reverse sign of neg values */
-dpthpca2:
- mov pctemp, eax /* save pc for later use */
- /* pb = abs(pbv) */
- test ecx, 0x80000000
- jz dpthpba2
- neg ecx /* reverse sign of neg values */
-dpthpba2:
- mov pbtemp, ecx /* save pb for later use */
- /* pa = abs(pav) */
- mov eax, patemp
- test eax, 0x80000000
- jz dpthpaa2
- neg eax /* reverse sign of neg values */
-dpthpaa2:
- mov patemp, eax /* save pa for later use */
- /* test if pa <= pb */
- cmp eax, ecx
- jna dpthabb2
- /* pa > pb; now test if pb <= pc */
- cmp ecx, pctemp
- jna dpthbbc2
- /* pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- jmp dpthpaeth2
-dpthbbc2:
- /* pb <= pc; Raw(x) = Paeth(x) + Prior(x) */
- mov cl, [esi + ebx] /* load Prior(x) into cl */
- jmp dpthpaeth2
-dpthabb2:
- /* pa <= pb; now test if pa <= pc */
- cmp eax, pctemp
- jna dpthabc2
- /* pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) */
- mov cl, [esi + edx] /* load Prior(x-bpp) into cl */
- jmp dpthpaeth2
-dpthabc2:
- /* pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) */
- mov cl, [edi + edx] /* load Raw(x-bpp) into cl */
-dpthpaeth2:
- inc ebx
- inc edx
- /* Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 */
- add [edi + ebx - 1], cl
- cmp ebx, FullLength
- jb dpthlp2
-dpthend:
- emms /* End MMX instructions; prep for possible FP instrs. */
- } /* end _asm block */
-}
-
-/* Optimized code for PNG Sub filter decoder */
-void /* PRIVATE */
-png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
-{
- /*int test; */
- int bpp;
- png_uint_32 FullLength;
- png_uint_32 MMXLength;
- int diff;
-
- bpp = (row_info->pixel_depth + 7) >> 3; /* Get # bytes per pixel */
- FullLength = row_info->rowbytes - bpp; /* # of bytes to filter */
- _asm {
- mov edi, row
- mov esi, edi /* lp = row */
- add edi, bpp /* rp = row + bpp */
- xor eax, eax
- /* get # of bytes to alignment */
- mov diff, edi /* take start of row */
- add diff, 0xf /* add 7 + 8 to incr past */
- /* alignment boundary */
- xor ebx, ebx
- and diff, 0xfffffff8 /* mask to alignment boundary */
- sub diff, edi /* subtract from start ==> value */
- /* ebx at alignment */
- jz dsubgo
- /* fix alignment */
-dsublp1:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, diff
- jb dsublp1
-dsubgo:
- mov ecx, FullLength
- mov edx, ecx
- sub edx, ebx /* subtract alignment fix */
- and edx, 0x00000007 /* calc bytes over mult of 8 */
- sub ecx, edx /* drop over bytes from length */
- mov MMXLength, ecx
- } /* end _asm block */
-
- /* Now do the math for the rest of the row */
- switch ( bpp )
- {
- case 3:
- {
- ActiveMask.use = 0x0000ffffff000000;
- ShiftBpp.use = 24; /* == 3 * 8 */
- ShiftRem.use = 40; /* == 64 - 24 */
- _asm {
- mov edi, row
- movq mm7, ActiveMask /* Load ActiveMask for 2nd active byte group */
- mov esi, edi /* lp = row */
- add edi, bpp /* rp = row + bpp */
- movq mm6, mm7
- mov ebx, diff
- psllq mm6, ShiftBpp /* Move mask in mm6 to cover 3rd active */
- /* byte group */
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm1, [edi+ebx-8]
-dsub3lp:
- psrlq mm1, ShiftRem /* Shift data for adding 1st bpp bytes */
- /* no need for mask; shift clears inactive bytes */
- /* Add 1st active group */
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- /* Add 2nd active group */
- movq mm1, mm0 /* mov updated Raws to mm1 */
- psllq mm1, ShiftBpp /* shift data to position correctly */
- pand mm1, mm7 /* mask to use only 2nd active group */
- paddb mm0, mm1
- /* Add 3rd active group */
- movq mm1, mm0 /* mov updated Raws to mm1 */
- psllq mm1, ShiftBpp /* shift data to position correctly */
- pand mm1, mm6 /* mask to use only 3rd active group */
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 /* Write updated Raws back to array */
- /* Prep for doing 1st add at top of loop */
- movq mm1, mm0
- jb dsub3lp
- } /* end _asm block */
- }
- break;
-
- case 1:
- {
- /* Placed here just in case this is a duplicate of the */
- /* non-MMX code for the SUB filter in png_read_filter_row below */
- //
- /* png_bytep rp; */
- /* png_bytep lp; */
- /* png_uint_32 i; */
- /* bpp = (row_info->pixel_depth + 7) >> 3; */
- /* for (i = (png_uint_32)bpp, rp = row + bpp, lp = row; */
- /* i < row_info->rowbytes; i++, rp++, lp++) */
- /* { */
- /* *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff); */
- /* } */
- _asm {
- mov ebx, diff
- mov edi, row
- cmp ebx, FullLength
- jnb dsub1end
- mov esi, edi /* lp = row */
- xor eax, eax
- add edi, bpp /* rp = row + bpp */
-dsub1lp:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, FullLength
- jb dsub1lp
-dsub1end:
- } /* end _asm block */
- }
- return;
-
- case 6:
- case 7:
- case 4:
- case 5:
- {
- ShiftBpp.use = bpp << 3;
- ShiftRem.use = 64 - ShiftBpp.use;
- _asm {
- mov edi, row
- mov ebx, diff
- mov esi, edi /* lp = row */
- add edi, bpp /* rp = row + bpp */
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm1, [edi+ebx-8]
-dsub4lp:
- psrlq mm1, ShiftRem /* Shift data for adding 1st bpp bytes */
- /* no need for mask; shift clears inactive bytes */
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- /* Add 2nd active group */
- movq mm1, mm0 /* mov updated Raws to mm1 */
- psllq mm1, ShiftBpp /* shift data to position correctly */
- /* there is no need for any mask */
- /* since shift clears inactive bits/bytes */
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0
- movq mm1, mm0 /* Prep for doing 1st add at top of loop */
- jb dsub4lp
- } /* end _asm block */
- }
- break;
-
- case 2:
- {
- ActiveMask.use = 0x00000000ffff0000;
- ShiftBpp.use = 16; /* == 2 * 8 */
- ShiftRem.use = 48; /* == 64 - 16 */
- _asm {
- movq mm7, ActiveMask /* Load ActiveMask for 2nd active byte group */
- mov ebx, diff
- movq mm6, mm7
- mov edi, row
- psllq mm6, ShiftBpp /* Move mask in mm6 to cover 3rd active */
- /* byte group */
- mov esi, edi /* lp = row */
- movq mm5, mm6
- add edi, bpp /* rp = row + bpp */
- psllq mm5, ShiftBpp /* Move mask in mm5 to cover 4th active */
- /* byte group */
- /* PRIME the pump (load the first Raw(x-bpp) data set */
- movq mm1, [edi+ebx-8]
-dsub2lp:
- /* Add 1st active group */
- psrlq mm1, ShiftRem /* Shift data for adding 1st bpp bytes */
- /* no need for mask; shift clears inactive */
- /* bytes */
- movq mm0, [edi+ebx]
- paddb mm0, mm1
- /* Add 2nd active group */
- movq mm1, mm0 /* mov updated Raws to mm1 */
- psllq mm1, ShiftBpp /* shift data to position correctly */
- pand mm1, mm7 /* mask to use only 2nd active group */
- paddb mm0, mm1
- /* Add 3rd active group */
- movq mm1, mm0 /* mov updated Raws to mm1 */
- psllq mm1, ShiftBpp /* shift data to position correctly */
- pand mm1, mm6 /* mask to use only 3rd active group */
- paddb mm0, mm1
- /* Add 4th active group */
- movq mm1, mm0 /* mov updated Raws to mm1 */
- psllq mm1, ShiftBpp /* shift data to position correctly */
- pand mm1, mm5 /* mask to use only 4th active group */
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 /* Write updated Raws back to array */
- movq mm1, mm0 /* Prep for doing 1st add at top of loop */
- jb dsub2lp
- } /* end _asm block */
- }
- break;
- case 8:
- {
- _asm {
- mov edi, row
- mov ebx, diff
- mov esi, edi /* lp = row */
- add edi, bpp /* rp = row + bpp */
- mov ecx, MMXLength
- movq mm7, [edi+ebx-8] /* PRIME the pump (load the first */
- /* Raw(x-bpp) data set */
- and ecx, 0x0000003f /* calc bytes over mult of 64 */
-dsub8lp:
- movq mm0, [edi+ebx] /* Load Sub(x) for 1st 8 bytes */
- paddb mm0, mm7
- movq mm1, [edi+ebx+8] /* Load Sub(x) for 2nd 8 bytes */
- movq [edi+ebx], mm0 /* Write Raw(x) for 1st 8 bytes */
- /* Now mm0 will be used as Raw(x-bpp) for */
- /* the 2nd group of 8 bytes. This will be */
- /* repeated for each group of 8 bytes with */
- /* the 8th group being used as the Raw(x-bpp) */
- /* for the 1st group of the next loop. */
- paddb mm1, mm0
- movq mm2, [edi+ebx+16] /* Load Sub(x) for 3rd 8 bytes */
- movq [edi+ebx+8], mm1 /* Write Raw(x) for 2nd 8 bytes */
- paddb mm2, mm1
- movq mm3, [edi+ebx+24] /* Load Sub(x) for 4th 8 bytes */
- movq [edi+ebx+16], mm2 /* Write Raw(x) for 3rd 8 bytes */
- paddb mm3, mm2
- movq mm4, [edi+ebx+32] /* Load Sub(x) for 5th 8 bytes */
- movq [edi+ebx+24], mm3 /* Write Raw(x) for 4th 8 bytes */
- paddb mm4, mm3
- movq mm5, [edi+ebx+40] /* Load Sub(x) for 6th 8 bytes */
- movq [edi+ebx+32], mm4 /* Write Raw(x) for 5th 8 bytes */
- paddb mm5, mm4
- movq mm6, [edi+ebx+48] /* Load Sub(x) for 7th 8 bytes */
- movq [edi+ebx+40], mm5 /* Write Raw(x) for 6th 8 bytes */
- paddb mm6, mm5
- movq mm7, [edi+ebx+56] /* Load Sub(x) for 8th 8 bytes */
- movq [edi+ebx+48], mm6 /* Write Raw(x) for 7th 8 bytes */
- add ebx, 64
- paddb mm7, mm6
- cmp ebx, ecx
- movq [edi+ebx-8], mm7 /* Write Raw(x) for 8th 8 bytes */
- jb dsub8lp
- cmp ebx, MMXLength
- jnb dsub8lt8
-dsub8lpA:
- movq mm0, [edi+ebx]
- add ebx, 8
- paddb mm0, mm7
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 /* use -8 to offset early add to ebx */
- movq mm7, mm0 /* Move calculated Raw(x) data to mm1 to */
- /* be the new Raw(x-bpp) for the next loop */
- jb dsub8lpA
-dsub8lt8:
- } /* end _asm block */
- }
- break;
-
- default: /* bpp greater than 8 bytes */
- {
- _asm {
- mov ebx, diff
- mov edi, row
- mov esi, edi /* lp = row */
- add edi, bpp /* rp = row + bpp */
-dsubAlp:
- movq mm0, [edi+ebx]
- movq mm1, [esi+ebx]
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, MMXLength
- movq [edi+ebx-8], mm0 /* mov does not affect flags; -8 to offset */
- /* add ebx */
- jb dsubAlp
- } /* end _asm block */
- }
- break;
-
- } /* end switch ( bpp ) */
-
- _asm {
- mov ebx, MMXLength
- mov edi, row
- cmp ebx, FullLength
- jnb dsubend
- mov esi, edi /* lp = row */
- xor eax, eax
- add edi, bpp /* rp = row + bpp */
-dsublp2:
- mov al, [esi+ebx]
- add [edi+ebx], al
- inc ebx
- cmp ebx, FullLength
- jb dsublp2
-dsubend:
- emms /* End MMX instructions; prep for possible FP instrs. */
- } /* end _asm block */
-}
-
-/* Optimized code for PNG Up filter decoder */
-void /* PRIVATE */
-png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
- png_bytep prev_row)
-{
- png_uint_32 len;
- len = row_info->rowbytes; /* # of bytes to filter */
- _asm {
- mov edi, row
- /* get # of bytes to alignment */
- mov ecx, edi
- xor ebx, ebx
- add ecx, 0x7
- xor eax, eax
- and ecx, 0xfffffff8
- mov esi, prev_row
- sub ecx, edi
- jz dupgo
- /* fix alignment */
-duplp1:
- mov al, [edi+ebx]
- add al, [esi+ebx]
- inc ebx
- cmp ebx, ecx
- mov [edi + ebx-1], al /* mov does not affect flags; -1 to offset inc ebx */
- jb duplp1
-dupgo:
- mov ecx, len
- mov edx, ecx
- sub edx, ebx /* subtract alignment fix */
- and edx, 0x0000003f /* calc bytes over mult of 64 */
- sub ecx, edx /* drop over bytes from length */
- /* Unrolled loop - use all MMX registers and interleave to reduce */
- /* number of branch instructions (loops) and reduce partial stalls */
-duploop:
- movq mm1, [esi+ebx]
- movq mm0, [edi+ebx]
- movq mm3, [esi+ebx+8]
- paddb mm0, mm1
- movq mm2, [edi+ebx+8]
- movq [edi+ebx], mm0
- paddb mm2, mm3
- movq mm5, [esi+ebx+16]
- movq [edi+ebx+8], mm2
- movq mm4, [edi+ebx+16]
- movq mm7, [esi+ebx+24]
- paddb mm4, mm5
- movq mm6, [edi+ebx+24]
- movq [edi+ebx+16], mm4
- paddb mm6, mm7
- movq mm1, [esi+ebx+32]
- movq [edi+ebx+24], mm6
- movq mm0, [edi+ebx+32]
- movq mm3, [esi+ebx+40]
- paddb mm0, mm1
- movq mm2, [edi+ebx+40]
- movq [edi+ebx+32], mm0
- paddb mm2, mm3
- movq mm5, [esi+ebx+48]
- movq [edi+ebx+40], mm2
- movq mm4, [edi+ebx+48]
- movq mm7, [esi+ebx+56]
- paddb mm4, mm5
- movq mm6, [edi+ebx+56]
- movq [edi+ebx+48], mm4
- add ebx, 64
- paddb mm6, mm7
- cmp ebx, ecx
- movq [edi+ebx-8], mm6 /* (+56)movq does not affect flags; */
- /* -8 to offset add ebx */
- jb duploop
-
- cmp edx, 0 /* Test for bytes over mult of 64 */
- jz dupend
-
-
- /* 2 lines added by lcreeve@netins.net */
- /* (mail 11 Jul 98 in png-implement list) */
- cmp edx, 8 /*test for less than 8 bytes */
- jb duplt8
-
-
- add ecx, edx
- and edx, 0x00000007 /* calc bytes over mult of 8 */
- sub ecx, edx /* drop over bytes from length */
- jz duplt8
- /* Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously */
-duplpA:
- movq mm1, [esi+ebx]
- movq mm0, [edi+ebx]
- add ebx, 8
- paddb mm0, mm1
- cmp ebx, ecx
- movq [edi+ebx-8], mm0 /* movq does not affect flags; -8 to offset add ebx */
- jb duplpA
- cmp edx, 0 /* Test for bytes over mult of 8 */
- jz dupend
-duplt8:
- xor eax, eax
- add ecx, edx /* move over byte count into counter */
- /* Loop using x86 registers to update remaining bytes */
-duplp2:
- mov al, [edi + ebx]
- add al, [esi + ebx]
- inc ebx
- cmp ebx, ecx
- mov [edi + ebx-1], al /* mov does not affect flags; -1 to offset inc ebx */
- jb duplp2
-dupend:
- /* Conversion of filtered row completed */
- emms /* End MMX instructions; prep for possible FP instrs. */
- } /* end _asm block */
-}
-
-
-/* Optimized png_read_filter_row routines */
-void /* PRIVATE */
-png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
- row, png_bytep prev_row, int filter)
-{
-#ifdef PNG_DEBUG
- char filnm[10];
-#endif
-
- if (mmx_supported == 2) {
- /* this should have happened in png_init_mmx_flags() already */
- png_warning(png_ptr, "asm_flags may not have been initialized");
- png_mmx_support();
- }
-
-#ifdef PNG_DEBUG
- png_debug(1, "in png_read_filter_row\n");
- switch (filter)
- {
- case 0: sprintf(filnm, "none");
- break;
- case 1: sprintf(filnm, "sub-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "MMX" : "x86");
- break;
- case 2: sprintf(filnm, "up-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "MMX" : "x86");
- break;
- case 3: sprintf(filnm, "avg-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "MMX" : "x86");
- break;
- case 4: sprintf(filnm, "Paeth-%s",
- (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "MMX":"x86");
- break;
- default: sprintf(filnm, "unknw");
- break;
- }
- png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm);
- png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth,
- (int)((row_info->pixel_depth + 7) >> 3));
- png_debug1(0,"len=%8d, ", row_info->rowbytes);
-#endif /* PNG_DEBUG */
-
- switch (filter)
- {
- case PNG_FILTER_VALUE_NONE:
- break;
-
- case PNG_FILTER_VALUE_SUB:
- {
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- {
- png_read_filter_row_mmx_sub(row_info, row);
- }
- else
- {
- png_uint_32 i;
- png_uint_32 istop = row_info->rowbytes;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_bytep rp = row + bpp;
- png_bytep lp = row;
-
- for (i = bpp; i < istop; i++)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
- rp++;
- }
- }
- break;
- }
-
- case PNG_FILTER_VALUE_UP:
- {
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- {
- png_read_filter_row_mmx_up(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_uint_32 istop = row_info->rowbytes;
- png_bytep rp = row;
- png_bytep pp = prev_row;
-
- for (i = 0; i < istop; ++i)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
- rp++;
- }
- }
- break;
- }
-
- case PNG_FILTER_VALUE_AVG:
- {
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- {
- png_read_filter_row_mmx_avg(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_bytep rp = row;
- png_bytep pp = prev_row;
- png_bytep lp = row;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_uint_32 istop = row_info->rowbytes - bpp;
-
- for (i = 0; i < bpp; i++)
- {
- *rp = (png_byte)(((int)(*rp) +
- ((int)(*pp++) >> 1)) & 0xff);
- rp++;
- }
-
- for (i = 0; i < istop; i++)
- {
- *rp = (png_byte)(((int)(*rp) +
- ((int)(*pp++ + *lp++) >> 1)) & 0xff);
- rp++;
- }
- }
- break;
- }
-
- case PNG_FILTER_VALUE_PAETH:
- {
- if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) &&
- (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
- (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
- {
- png_read_filter_row_mmx_paeth(row_info, row, prev_row);
- }
- else
- {
- png_uint_32 i;
- png_bytep rp = row;
- png_bytep pp = prev_row;
- png_bytep lp = row;
- png_bytep cp = prev_row;
- png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
- png_uint_32 istop=row_info->rowbytes - bpp;
-
- for (i = 0; i < bpp; i++)
- {
- *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
- rp++;
- }
-
- for (i = 0; i < istop; i++) /* use leftover rp,pp */
- {
- int a, b, c, pa, pb, pc, p;
-
- a = *lp++;
- b = *pp++;
- c = *cp++;
-
- p = b - c;
- pc = a - c;
-
-#ifdef PNG_USE_ABS
- pa = abs(p);
- pb = abs(pc);
- pc = abs(p + pc);
-#else
- pa = p < 0 ? -p : p;
- pb = pc < 0 ? -pc : pc;
- pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-#endif
-
- /*
- if (pa <= pb && pa <= pc)
- p = a;
- else if (pb <= pc)
- p = b;
- else
- p = c;
- */
-
- p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
-
- *rp = (png_byte)(((int)(*rp) + p) & 0xff);
- rp++;
- }
- }
- break;
- }
-
- default:
- png_warning(png_ptr, "Ignoring bad row filter type");
- *row=0;
- break;
- }
-}
-
-#endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */