Imported from libpng-1.0.4e.tar
diff --git a/ANNOUNCE b/ANNOUNCE
index f839384..32fa33f 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,5 +1,5 @@
 
-Libpng 1.0.4d - October 6, 1999
+Libpng 1.0.4e - October 10, 1999
 
 This is not intended to be a public release.  It will be replaced
 within a few weeks by a public version or by another test version.
@@ -80,9 +80,13 @@
     a helpful compiler error if an old png.h is found in the search path.
 version 1.0.4c October 1, 1999
   Changed type of png_user_transform_depth|channels from int to png_byte.
-version 1.0.4d [October 6, 1999]
+version 1.0.4e [October 10, 1999]
   Changed 0.45 to 0.45455 in png_set_sRGB()
   Removed unused PLTE entries from pngnow.png
+  Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly.
+version 1.0.4e [October 10, 1999]
+  Fixed sign error in pngvcrd.c (Greg Roelofs)
+  Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P)
 
 Send comments/corrections/commendations to
 png-implement@ccrc.wustl.edu or to randeg@alum.rpi.edu
diff --git a/CHANGES b/CHANGES
index faf94e3..691f337 100644
--- a/CHANGES
+++ b/CHANGES
@@ -459,7 +459,11 @@
 version 1.0.4c [October 1, 1999]
   Added a "png_check_version" function in png.c and pngtest.c that will generate
     a helpful compiler error if an old png.h is found in the search path.
-version 1.0.4d [October 6, 1999]
   Changed type of png_user_transform_depth|channels from int to png_byte.
+version 1.0.4d [October 6, 1999]
   Changed 0.45 to 0.45455 in png_set_sRGB()
   Removed unused PLTE entries from pngnow.png
+  Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly.
+version 1.0.4e [October 10, 1999]
+  Fixed sign error in pngvcrd.c (Greg Roelofs)
+  Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P)
diff --git a/INSTALL b/INSTALL
index b67764e..328430f 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,5 +1,5 @@
 
-Installing libpng version 1.0.4d - October 6, 1999
+Installing libpng version 1.0.4e - October 10, 1999
 
 Before installing libpng, you must first install zlib.  zlib
 can usually be found wherever you got libpng.  zlib can be
@@ -10,7 +10,7 @@
 version of zlib that's installed.
 
 You can rename the directories that you downloaded (they
-might be called "libpng-1.0.4d" or "lpng103" and "zlib-1.1.3"
+might be called "libpng-1.0.4e" or "lpng103" and "zlib-1.1.3"
 or "zlib113") so that you have directories called "zlib" and "libpng".
 
 Your directory structure should look like this:
@@ -47,8 +47,8 @@
  makefile.hpux    =>  HPUX (10.20 and 11.00) makefile
  makefile.sgi     =>  Silicon Graphics IRIX makefile
  makefile.sunos   =>  Sun makefile
- makefile.solaris =>  Solaris 2.X makefile (gcc, creates libpng.so.2.1.0.4d)
- makefile.linux   =>  Linux/ELF makefile (gcc, creates libpng.so.2.1.0.4d)
+ makefile.solaris =>  Solaris 2.X makefile (gcc, creates libpng.so.2.1.0.4e)
+ makefile.linux   =>  Linux/ELF makefile (gcc, creates libpng.so.2.1.0.4e)
  makefile.sco     =>  For SCO OSr5  ELF and Unixware 7 with Native cc
  makefile.mips    =>  MIPS makefile
  makefile.acorn   =>  Acorn makefile
diff --git a/LICENSE b/LICENSE
index e85524d..359888e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -5,7 +5,7 @@
 Copyright (c) 1996, 1997 Andreas Dilger
 (libpng versions 0.90, December 1996, through 0.96, May 1997)
 Copyright (c) 1998, 1999 Glenn Randers-Pehrson
-(libpng versions 0.97, January 1998, through 1.0.4d, October 6, 1999)
+(libpng versions 0.97, January 1998, through 1.0.4e, October 10, 1999)
 
 For the purposes of this copyright and license, "Contributing Authors"
 is defined as the following set of individuals:
@@ -56,4 +56,4 @@
 
 Glenn Randers-Pehrson
 randeg@alum.rpi.edu
-October 6, 1999
+October 10, 1999
diff --git a/README b/README
index db3ac07..68f898e 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-README for libpng 1.0.4d - October 6, 1999 (shared library 2.1)
+README for libpng 1.0.4e - October 10, 1999 (shared library 2.1)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
@@ -163,9 +163,9 @@
        makefile.sgi     =>  Silicon Graphics IRIX makefile
        makefile.sunos   =>  Sun makefile
        makefile.solaris =>  Solaris 2.X makefile
-                            (gcc, creates libpng.so.2.1.0.4d)
+                            (gcc, creates libpng.so.2.1.0.4e)
        makefile.linux   =>  Linux/ELF makefile
-                            (gcc, creates libpng.so.2.1.0.4d)
+                            (gcc, creates libpng.so.2.1.0.4e)
        makefile.sco     =>  For SCO OSr5  ELF and Unixware 7 with Native cc
        makefile.mips    =>  MIPS makefile
        makefile.acorn   =>  Acorn makefile
diff --git a/Y2KINFO b/Y2KINFO
index cdbaabf..ba7be80 100644
--- a/Y2KINFO
+++ b/Y2KINFO
@@ -1,13 +1,13 @@
    Y2K compliance in libpng:
    =========================
       
-      October 6, 1999
+      October 10, 1999
       
       Since the PNG Development group is an ad-hoc body, we can't make
       an official declaration.
       
       This is your unofficial assurance that libpng from version 0.71 and
-      upward through 1.0.4d are Y2K compliant.  It is my belief that earlier
+      upward through 1.0.4e are Y2K compliant.  It is my belief that earlier
       versions were also Y2K compliant.
       
       Libpng only has three year fields.  One is a 2-byte unsigned integer
diff --git a/libpng.3 b/libpng.3
index e9669ba..7f9cf97 100644
--- a/libpng.3
+++ b/libpng.3
@@ -1,6 +1,6 @@
-.TH LIBPNG 3 "October 6, 1999"
+.TH LIBPNG 3 "October 10, 1999"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.0.4d - October 6, 1999
+libpng \- Portable Network Graphics (PNG) Reference Library 1.0.4e - October 10, 1999
 .SH SYNOPSIS
 \fI\fB
 
@@ -617,7 +617,7 @@
 .SH LIBPNG.TXT
 libpng.txt - A description on how to use and modify libpng
 
- libpng version 1.0.4d - October 6, 1999
+ libpng version 1.0.4e - October 10, 1999
  Updated and distributed by Glenn Randers-Pehrson
  <randeg@alum.rpi.edu>
  Copyright (c) 1998, 1999 Glenn Randers-Pehrson
@@ -2675,13 +2675,13 @@
 
 .SH VII. Y2K Compliance in libpng
 
-October 6, 1999
+October 10, 1999
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.0.4d are Y2K compliant.  It is my belief that earlier
+upward through 1.0.4e are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has three year fields.  One is a 2-byte unsigned integer that
@@ -2807,7 +2807,7 @@
 
 Thanks to Frank J. T. Wojcik for helping with the documentation.
   
-Libpng version 1.0.4d - October 6, 1999:
+Libpng version 1.0.4e - October 10, 1999:
 Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
 Currently maintained by Glenn Randers-Pehrson (randeg@alum.rpi.edu).
 
@@ -2822,7 +2822,7 @@
 Copyright (c) 1996, 1997 Andreas Dilger
 (libpng versions 0.90, December 1996, through 0.96, May 1997)
 Copyright (c) 1998, 1999 Glenn Randers-Pehrson
-(libpng versions 0.97, January 1998, through 1.0.4d, October 6, 1999)
+(libpng versions 0.97, January 1998, through 1.0.4e, October 10, 1999)
 
 For the purposes of this copyright and license, "Contributing Authors"
 is defined as the following set of individuals:
diff --git a/libpng.txt b/libpng.txt
index 1628878..b81c1b4 100644
--- a/libpng.txt
+++ b/libpng.txt
@@ -1,6 +1,6 @@
 libpng.txt - A description on how to use and modify libpng
 
- libpng version 1.0.4d - October 6, 1999
+ libpng version 1.0.4e - October 10, 1999
  Updated and distributed by Glenn Randers-Pehrson
  <randeg@alum.rpi.edu>
  Copyright (c) 1998, 1999 Glenn Randers-Pehrson
@@ -2058,13 +2058,13 @@
 
 VII. Y2K Compliance in libpng
 
-October 6, 1999
+October 10, 1999
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.0.4d are Y2K compliant.  It is my belief that earlier
+upward through 1.0.4e are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has three year fields.  One is a 2-byte unsigned integer that
diff --git a/libpngpf.3 b/libpngpf.3
index def345c..57345eb 100644
--- a/libpngpf.3
+++ b/libpngpf.3
@@ -1,6 +1,6 @@
-.TH LIBPNGPF 3 October 6, 1999
+.TH LIBPNGPF 3 October 10, 1999
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.0.4d - October 6, 1999
+libpng \- Portable Network Graphics (PNG) Reference Library 1.0.4e - October 10, 1999
 (private functions)
 .SH SYNOPSIS
 \fB#include <png.h>\fP
diff --git a/png.5 b/png.5
index be84fb8..3cd6ff1 100644
--- a/png.5
+++ b/png.5
@@ -1,4 +1,4 @@
-.TH PNG 5 "October 6, 1999"
+.TH PNG 5 "October 10, 1999"
 .SH NAME
 png \- Portable Network Graphics (PNG) format
 .SH DESCRIPTION
diff --git a/png.c b/png.c
index dfcc680..e2eeb3b 100644
--- a/png.c
+++ b/png.c
@@ -1,7 +1,7 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * libpng version 1.0.4d - October 6, 1999
+ * libpng version 1.0.4e - October 10, 1999
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
  * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
@@ -16,7 +16,7 @@
  * string defined in png.h.
  */
 
-char png_libpng_ver[12] = "1.0.4d";
+char png_libpng_ver[12] = "1.0.4e";
 
 /* Place to hold the signature string for a PNG file. */
 png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
@@ -352,7 +352,7 @@
 {
    if(png_ptr == NULL)
      /* silence compiler warning about unused png_ptr */ ;
-   return("\n libpng version 1.0.4d - October 6, 1999\n\
+   return("\n libpng version 1.0.4e - October 10, 1999\n\
    Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.\n\
    Copyright (c) 1996, 1997 Andreas Dilger\n\
    Copyright (c) 1998, 1999 Glenn Randers-Pehrson\n");
@@ -361,8 +361,8 @@
 /* Generate a compiler error if there is an old png.h in the search path. */
 void
 png_check_version
-   (version_1_0_4d png_h_is_not_version_1_0_4d)
+   (version_1_0_4e png_h_is_not_version_1_0_4e)
 {
-   if(png_h_is_not_version_1_0_4d == NULL)
+   if(png_h_is_not_version_1_0_4e == NULL)
      /* silence compiler warning about unused parameter */ ;
 }
diff --git a/png.h b/png.h
index 07ea6d6..bd86eef 100644
--- a/png.h
+++ b/png.h
@@ -1,7 +1,7 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.0.4d - October 6, 1999
+ * libpng version 1.0.4e - October 10, 1999
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
  * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
@@ -9,19 +9,19 @@
  * Authors and maintainers:
  *  libpng versions 0.71, May 1995, through 0.89c, May 1996: Guy Schalnat
  *  libpng versions 0.90, December 1996, through 0.96, May 1997: Andreas Dilger
- *  libpng versions 0.97, January 1998, through 1.0.4d - October 6, 1999: Glenn
+ *  libpng versions 0.97, January 1998, through 1.0.4e - October 10, 1999: Glenn
  *  See also "Contributing Authors", below.
  *
  * Y2K compliance in libpng:
  * =========================
  *    
- *    October 6, 1999
+ *    October 10, 1999
  *    
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *    
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.0.4d are Y2K compliant.  It is my belief that earlier
+ *    upward through 1.0.4e are Y2K compliant.  It is my belief that earlier
  *    versions were also Y2K compliant.
  *    
  *    Libpng only has three year fields.  One is a 2-byte unsigned integer
@@ -95,7 +95,7 @@
  *    1.0.3                    1.0.3    10003  2.1.0.3
  *    1.0.3a-d                 1.0.3a-d 10004  2.1.0.3a-d
  *    1.0.4                    1.0.4    10004  2.1.0.4
- *    1.0.4a-c                 1.0.4a-c 10005  2.1.0.4a-c
+ *    1.0.4a-e                 1.0.4a-e 10005  2.1.0.4a-e
  *    1.0.5                    1.0.5    10005  2.1.0.5
  *
  *    Henceforth the source version will match the shared-library minor
@@ -117,7 +117,7 @@
  * Copyright (c) 1996, 1997 Andreas Dilger
  * (libpng versions 0.90, December 1996, through 0.96, May 1997)
  * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
- * (libpng versions 0.97, January 1998, through 1.0.4d, October 6, 1999)
+ * (libpng versions 0.97, January 1998, through 1.0.4e, October 10, 1999)
  *
  * For the purposes of this copyright and license, "Contributing Authors"
  * is defined as the following set of individuals:
@@ -208,7 +208,7 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.0.4d"
+#define PNG_LIBPNG_VER_STRING "1.0.4e"
 
 /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
  * We must not include leading zeros.
@@ -806,9 +806,9 @@
 };
 
 /* This prevents a compiler error in png_get_copyright() in png.c if png.c
-and png.h are both at * version 1.0.4d
+and png.h are both at * version 1.0.4e
  */
-typedef png_structp version_1_0_4d;
+typedef png_structp version_1_0_4e;
 
 typedef png_struct FAR * FAR * png_structpp;
 
@@ -1629,7 +1629,7 @@
 {
    if(png_ptr == NULL)
      /* silence compiler warning about unused png_ptr */ ;
-   return("\n libpng version 1.0.4d - October 6, 1999 (header)\n");
+   return("\n libpng version 1.0.4e - October 10, 1999 (header)\n");
 }
 #endif
 
diff --git a/pngasmrd.h b/pngasmrd.h
index 27b747c..02c3282 100644
--- a/pngasmrd.h
+++ b/pngasmrd.h
@@ -1,6 +1,6 @@
 /* pngasmrd.h - assembler version of utilities to read a PNG file
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1999 Glenn Randers-Pehrson
  *
@@ -21,7 +21,7 @@
 /* Set this in the makefile for gcc on Pentium, not in pngconf.h */
 #ifdef PNG_USE_PNGGCCRD
 /* Platform must be Pentium.  Makefile must assemble and load pnggccrd.c
- * (not available in libpng 1.0.4d).
+ * (not available in libpng 1.0.4e).
  * MMX will be detected at run time and used if present.
  */
 #define PNG_HAVE_ASSEMBLER_COMBINE_ROW
diff --git a/pngconf.h b/pngconf.h
index 63749eb..c81bb41 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -1,7 +1,7 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngerror.c b/pngerror.c
index b7446d3..9f0fcda 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -1,7 +1,7 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngget.c b/pngget.c
index 7a850e4..d786a72 100644
--- a/pngget.c
+++ b/pngget.c
@@ -1,7 +1,7 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngmem.c b/pngmem.c
index 2f5ecd2..307c901 100644
--- a/pngmem.c
+++ b/pngmem.c
@@ -1,7 +1,7 @@
 
 /* pngmem.c - stub functions for memory allocation
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngnow.png b/pngnow.png
index 2172b49..6a1f497 100644
--- a/pngnow.png
+++ b/pngnow.png
Binary files differ
diff --git a/pngpread.c b/pngpread.c
index c66b8ad..7e6be06 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -1,7 +1,7 @@
 
 /* pngpread.c - read a png file in push mode
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngread.c b/pngread.c
index 733689e..8c08c48 100644
--- a/pngread.c
+++ b/pngread.c
@@ -1,7 +1,7 @@
 
 /* pngread.c - read a PNG file
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
@@ -465,10 +465,8 @@
    png_ptr->row_info.channels = png_ptr->channels;
    png_ptr->row_info.bit_depth = png_ptr->bit_depth;
    png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
-   {
-      png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
-         (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
-   }
+   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
+      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
 
    png_read_filter_row(png_ptr, &(png_ptr->row_info),
       png_ptr->row_buf + 1, png_ptr->prev_row + 1,
@@ -531,7 +529,7 @@
  * not called png_set_interlace_handling(), the display_row buffer will
  * be ignored, so pass NULL to it.
  *
- * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.4d.
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.4e.
  */
 
 void
@@ -580,7 +578,7 @@
  * only call this function once.  If you desire to have an image for
  * each pass of a interlaced image, use png_read_rows() instead.
  *
- * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.4d.
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.4e.
  */
 void
 png_read_image(png_structp png_ptr, png_bytepp image)
diff --git a/pngrio.c b/pngrio.c
index 056d87d..28c709c 100644
--- a/pngrio.c
+++ b/pngrio.c
@@ -1,7 +1,7 @@
 
 /* pngrio.c - functions for data input
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngrtran.c b/pngrtran.c
index 4f94155..2a44f81 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -1,7 +1,7 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngrutil.c b/pngrutil.c
index bd98317..ce982ef 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -1,7 +1,7 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngset.c b/pngset.c
index 751a592..037333b 100644
--- a/pngset.c
+++ b/pngset.c
@@ -1,7 +1,7 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngtest.c b/pngtest.c
index 7267fdb..3796c63 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -1,7 +1,7 @@
 
 /* pngtest.c - a simple test program to test libpng
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
@@ -1172,7 +1172,7 @@
 /* Generate a compiler error if there is an old png.h in the search path. */
 void
 png_check_pngtest_version
-   (version_1_0_4d png_h_is_not_version_1_0_4d)
+   (version_1_0_4e png_h_is_not_version_1_0_4e)
 {
-   if(png_h_is_not_version_1_0_4d == NULL) return;
+   if(png_h_is_not_version_1_0_4e == NULL) return;
 }
diff --git a/pngtrans.c b/pngtrans.c
index 9313d47..cbe13c3 100644
--- a/pngtrans.c
+++ b/pngtrans.c
@@ -1,7 +1,7 @@
 
 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngvcrd.c b/pngvcrd.c
index b159171..d26b72f 100644
--- a/pngvcrd.c
+++ b/pngvcrd.c
@@ -1,3824 +1,3826 @@
-/* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file

- *

- * For Intel x86 CPU and Microsoft Visual C++ compiler

- *

- * libpng 1.0.4d - October 6, 1999

- * For conditions of distribution and use, see copyright notice in png.h

- * Copyright (c) 1998, Intel Corporation

- * Copyright (c) 1998, 1999 Glenn Randers-Pehrson

- *

- * Contributed by Nirav Chhatrapati, Intel Corporation, 1998

- * Interface to libpng contributed by Gilles Vollant, 1999

- *

- */

-

-#define PNG_INTERNAL

-#include "png.h"

-

-#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)

-

-static int mmx_supported=2;

-

-void

-png_read_filter_row_c(png_structp png_ptr, png_row_infop row_info,

-   png_bytep row, png_bytep prev_row, int filter);

-

-static int mmxsupport()

-{

-  int mmx_supported_local = 0;

-

-  _asm {

-    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

-    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

-

-  }

-

-  //mmx_supported_local=0; // test code for force don't support MMX

-  //printf("MMX : %u (1=MMX supported)\n",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

-png_combine_row(png_structp png_ptr, png_bytep row, int mask)

-{

-#ifdef DISABLE_PNGVCRD_COMBINE

-   int save_mmx_supported = mmx_supported;

-#endif

-

-   png_debug(1,"in png_combine_row_asm\n");

-

-#ifdef DISABLE_PNGVCRD_COMBINE

-   if ((png_ptr->transformations & PNG_INTERLACE) && png_ptr->pass != 6)

-       mmx_supported = 0;

-   else

-#endif

-       if (mmx_supported == 2)

-           mmx_supported = mmxsupport();

-

-   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 (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 (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 (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 (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 (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) */

-

-#ifdef DISABLE_PNGVCRD_COMBINE

-   mmx_supported = save_mmx_supported;

-#endif

-

-} /* end png_combine_row() */

-

-

-#if defined(PNG_READ_INTERLACING_SUPPORTED)

-

-void

-png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,

-   png_uint_32 transformations)

-{

-#ifdef DISABLE_PNGVCRD_INTERLACE

-   int save_mmx_supported = mmx_supported;

-#endif

-

-   png_debug(1,"in png_do_read_interlace\n");

-

-#ifdef DISABLE_PNGVCRD_INTERLACE

-   /* 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 is now fixed, and the code

-    * appears to work completely correctly, so it is enabled by default.

-    */

-   if (1)  /* all passes caused a heap problem in the old code */

-      mmx_supported = 0;

-   else

-#endif

-       if (mmx_supported == 2)

-           mmx_supported = mmxsupport();

-

-   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;

-            __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

-

-            if (mmx_supported) // use MMX routine if machine supports it

-            {

-               if (pixel_bytes == 3)

-               {

-                  if ((pass == 0) || (pass == 1))

-                  {

-                     _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))

-                  {

-                     _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 ((pass == 4) || (pass == 5)) */

-                  {

-                     int width_mmx = ((width >> 1) << 1) - 8;

-                     width -= width_mmx;

-                     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, 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 pixel_bytes == 3 */

-

-               else if (pixel_bytes == 1)

-               {

-                  if ((pass == 0) || (pass == 1))

-                  {

-                     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--)

-                     {

-                        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 ((pass == 2) || (pass == 3))

-                  {

-                     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--)

-                     {

-                        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 ((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--)

-                     {

-                        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 pixel_bytes == 1 */

-

-               else if (pixel_bytes == 2)

-               {

-                  if ((pass == 0) || (pass == 1))

-                  {

-                     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 -= pixel_bytes;

-                        png_memcpy(v, sptr, pixel_bytes);

-                        for (j = 0; j < png_pass_inc[pass]; j++)

-                        {

-                           dp -= pixel_bytes;

-                           png_memcpy(dp, v, pixel_bytes);

-                        }

-                     }

-                  }

-

-                  else if ((pass == 2) || (pass == 3))

-                  {

-                     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 -= pixel_bytes;

-                        png_memcpy(v, sptr, pixel_bytes);

-                        for (j = 0; j < png_pass_inc[pass]; j++)

-                        {

-                           dp -= pixel_bytes;

-                           png_memcpy(dp, v, pixel_bytes);

-                        }

-                     }

-                  }

-

-                  else // 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 -= pixel_bytes;

-                        png_memcpy(v, sptr, pixel_bytes);

-                        for (j = 0; j < png_pass_inc[pass]; j++)

-                        {

-                           dp -= pixel_bytes;

-                           png_memcpy(dp, v, pixel_bytes);

-                        }

-                     }

-                  }

-               } /* end of pixel_bytes == 2 */

-

-               else if (pixel_bytes == 4)

-               {

-                  if ((pass == 0) || (pass == 1))

-                  {

-                     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 -= pixel_bytes;

-                        png_memcpy(v, sptr, pixel_bytes);

-                        for (j = 0; j < png_pass_inc[pass]; j++)

-                        {

-                           dp -= pixel_bytes;

-                           png_memcpy(dp, v, pixel_bytes);

-                        }

-                     }

-                  }

-

-                  else if ((pass == 2) || (pass == 3))

-                  {

-                     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 -= pixel_bytes;

-                        png_memcpy(v, sptr, pixel_bytes);

-                        for (j = 0; j < png_pass_inc[pass]; j++)

-                        {

-                           dp -= pixel_bytes;

-                           png_memcpy(dp, v, pixel_bytes);

-                        }

-                     }

-                  }

-

-                  else // 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 -= pixel_bytes;

-                        png_memcpy(v, sptr, pixel_bytes);

-                        for (j = 0; j < png_pass_inc[pass]; j++)

-                        {

-                           dp -= pixel_bytes;

-                           png_memcpy(dp, v, pixel_bytes);

-                        }

-                     }

-                  }

-

-               } /* 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, 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 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--)

-                  {

-                     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 == 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);

-   }

-

-#ifdef DISABLE_PNGVCRD_INTERLACE

-   mmx_supported = save_mmx_supported;

-#endif

-}

-

-#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

-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 = 24;   // == 3 * 8

-         ShiftRem.use = 40;   // == 64 - 24

-         _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]

-            psllq 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

-            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

-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

-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 above

-         //

-         //         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

-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

-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[6];

-#endif

-   #define UseMMX (1)

-

-   if (mmx_supported == 2)

-       mmx_supported = mmxsupport();

-

-   if (!mmx_supported)

-   {

-       png_read_filter_row_c(png_ptr, row_info, row, prev_row, filter);

-       return ;

-   }

-

-#ifdef PNG_DEBUG

-   png_debug(1, "in png_read_filter_row\n");

-   png_debug1(0,"%s, ", (UseMMX?"MMX":"x86"));

-   switch (filter)

-   {

-      case 0: sprintf(filnm, "None ");

-         break;

-      case 1: sprintf(filnm, "Sub  ");

-         break;

-      case 2: sprintf(filnm, "Up   ");

-         break;

-      case 3: sprintf(filnm, "Avg  ");

-         break;

-      case 4: sprintf(filnm, "Paeth");

-         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

-

-   switch (filter)

-   {

-      case PNG_FILTER_VALUE_NONE:

-         break;

-      case PNG_FILTER_VALUE_SUB:

-      {

-         if ( UseMMX && (row_info->pixel_depth > 8) &&

-            (row_info->rowbytes >= 128) )

-         {

-            png_read_filter_row_mmx_sub(row_info, row);

-         }  //end if UseMMX

-         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++;

-            }

-         }  //end !UseMMX

-         break;

-      }

-      case PNG_FILTER_VALUE_UP:

-      {

-         if ( UseMMX && (row_info->pixel_depth > 8) &&

-             (row_info->rowbytes >= 128) )

-         {

-            png_read_filter_row_mmx_up(row_info, row, prev_row);

-         }  //end if UseMMX

-         else

-         {

-            png_bytep rp;

-            png_bytep pp;

-            png_uint_32 i;

-            for (i = 0, rp = row, pp = prev_row;

-               i < row_info->rowbytes; i++, rp++, pp++)

-            {

-                  *rp = (png_byte)(((int)(*rp) + (int)(*pp)) & 0xff);

-            }

-         }  //end !UseMMX

-         break;

-      }

-      case PNG_FILTER_VALUE_AVG:

-      {

-         if ( UseMMX && (row_info->pixel_depth > 8) &&

-             (row_info->rowbytes >= 128) )

-         {

-            png_read_filter_row_mmx_avg(row_info, row, prev_row);

-         }  //end if UseMMX

-         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++;

-            }

-         }  //end !UseMMX

-         break;

-      }

-      case PNG_FILTER_VALUE_PAETH:

-      {

-         if ( UseMMX && (row_info->pixel_depth > 8) &&

-             (row_info->rowbytes >= 128) )

-         {

-            png_read_filter_row_mmx_paeth(row_info, row, prev_row);

-         }  //end if UseMMX

-         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++;

-            }

-         }  //end !UseMMX

-         break;

-      }

-      default:

-         png_error(png_ptr, "Bad adaptive filter type");

-         break;

-   }

-}

-#endif

+/* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file
+ *
+ * For Intel x86 CPU and Microsoft Visual C++ compiler
+ *
+ * libpng 1.0.4e - October 10, 1999
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998, Intel Corporation
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+ *
+ * Contributed by Nirav Chhatrapati, Intel Corporation, 1998
+ * Interface to libpng contributed by Gilles Vollant, 1999
+ *
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)
+
+static int mmx_supported=2;
+
+void
+png_read_filter_row_c(png_structp png_ptr, png_row_infop row_info,
+   png_bytep row, png_bytep prev_row, int filter);
+
+static int mmxsupport()
+{
+  int mmx_supported_local = 0;
+  _asm {
+    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
+    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
+
+  }
+
+  //mmx_supported_local=0; // test code for force don't support MMX
+  //printf("MMX : %u (1=MMX supported)\n",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
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+#ifdef DISABLE_PNGVCRD_COMBINE
+   int save_mmx_supported = mmx_supported;
+#endif
+
+   png_debug(1,"in png_combine_row_asm\n");
+
+#ifdef DISABLE_PNGVCRD_COMBINE
+   if ((png_ptr->transformations & PNG_INTERLACE) && png_ptr->pass != 6)
+       mmx_supported = 0;
+   else
+#endif
+       if (mmx_supported == 2)
+           mmx_supported = mmxsupport();
+
+   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 (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 (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 (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 (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 (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) */
+
+#ifdef DISABLE_PNGVCRD_COMBINE
+   mmx_supported = save_mmx_supported;
+#endif
+
+} /* end png_combine_row() */
+
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+
+void
+png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
+   png_uint_32 transformations)
+{
+#ifdef DISABLE_PNGVCRD_INTERLACE
+   int save_mmx_supported = mmx_supported;
+#endif
+
+   png_debug(1,"in png_do_read_interlace\n");
+
+#ifdef DISABLE_PNGVCRD_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,
+    * and the code appears to work completely correctly, so it is enabled
+    * by default.
+    */
+   if (1)  /* all passes caused a heap problem in the old code */
+      mmx_supported = 0;
+   else
+#endif
+       if (mmx_supported == 2)
+           mmx_supported = mmxsupport();
+
+   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;
+            __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
+
+            if (mmx_supported) // use MMX routine if machine supports it
+            {
+               if (pixel_bytes == 3)
+               {
+                  if ((pass == 0) || (pass == 1))
+                  {
+                     _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))
+                  {
+                     _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 ((pass == 4) || (pass == 5)) */
+                  {
+                     int width_mmx = ((width >> 1) << 1) - 8;
+                     width -= width_mmx;
+                     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, 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 pixel_bytes == 3 */
+
+               else if (pixel_bytes == 1)
+               {
+                  if ((pass == 0) || (pass == 1))
+                  {
+                     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))
+                  {
+                     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 ((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))
+                  {
+                     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 -= pixel_bytes;
+                        png_memcpy(v, sptr, pixel_bytes);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= pixel_bytes;
+                           png_memcpy(dp, v, pixel_bytes);
+                        }
+                     }
+                  }
+
+                  else if ((pass == 2) || (pass == 3))
+                  {
+                     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 -= pixel_bytes;
+                        png_memcpy(v, sptr, pixel_bytes);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= pixel_bytes;
+                           png_memcpy(dp, v, pixel_bytes);
+                        }
+                     }
+                  }
+
+                  else // 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 -= pixel_bytes;
+                        png_memcpy(v, sptr, pixel_bytes);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= pixel_bytes;
+                           png_memcpy(dp, v, pixel_bytes);
+                        }
+                     }
+                  }
+               } /* end of pixel_bytes == 2 */
+
+               else if (pixel_bytes == 4)
+               {
+                  if ((pass == 0) || (pass == 1))
+                  {
+                     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 -= pixel_bytes;
+                        png_memcpy(v, sptr, pixel_bytes);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= pixel_bytes;
+                           png_memcpy(dp, v, pixel_bytes);
+                        }
+                     }
+                  }
+
+                  else if ((pass == 2) || (pass == 3))
+                  {
+                     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 -= pixel_bytes;
+                        png_memcpy(v, sptr, pixel_bytes);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= pixel_bytes;
+                           png_memcpy(dp, v, pixel_bytes);
+                        }
+                     }
+                  }
+
+                  else // 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 -= pixel_bytes;
+                        png_memcpy(v, sptr, pixel_bytes);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= pixel_bytes;
+                           png_memcpy(dp, v, pixel_bytes);
+                        }
+                     }
+                  }
+
+               } /* 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, 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 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);
+   }
+
+#ifdef DISABLE_PNGVCRD_INTERLACE
+   mmx_supported = save_mmx_supported;
+#endif
+}
+
+#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
+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 = 24;   // == 3 * 8
+         ShiftRem.use = 40;   // == 64 - 24
+         _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]
+            psllq 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
+            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
+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
+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 above
+         //
+         //         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
+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
+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[6];
+#endif
+   #define UseMMX (1)
+
+   if (mmx_supported == 2)
+       mmx_supported = mmxsupport();
+
+   if (!mmx_supported)
+   {
+       png_read_filter_row_c(png_ptr, row_info, row, prev_row, filter);
+       return ;
+   }
+
+#ifdef PNG_DEBUG
+   png_debug(1, "in png_read_filter_row\n");
+   png_debug1(0,"%s, ", (UseMMX?"MMX":"x86"));
+   switch (filter)
+   {
+      case 0: sprintf(filnm, "None ");
+         break;
+      case 1: sprintf(filnm, "Sub  ");
+         break;
+      case 2: sprintf(filnm, "Up   ");
+         break;
+      case 3: sprintf(filnm, "Avg  ");
+         break;
+      case 4: sprintf(filnm, "Paeth");
+         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
+
+   switch (filter)
+   {
+      case PNG_FILTER_VALUE_NONE:
+         break;
+      case PNG_FILTER_VALUE_SUB:
+      {
+         if ( UseMMX && (row_info->pixel_depth > 8) &&
+            (row_info->rowbytes >= 128) )
+         {
+            png_read_filter_row_mmx_sub(row_info, row);
+         }  //end if UseMMX
+         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++;
+            }
+         }  //end !UseMMX
+         break;
+      }
+      case PNG_FILTER_VALUE_UP:
+      {
+         if ( UseMMX && (row_info->pixel_depth > 8) &&
+             (row_info->rowbytes >= 128) )
+         {
+            png_read_filter_row_mmx_up(row_info, row, prev_row);
+         }  //end if UseMMX
+         else
+         {
+            png_bytep rp;
+            png_bytep pp;
+            png_uint_32 i;
+            for (i = 0, rp = row, pp = prev_row;
+               i < row_info->rowbytes; i++, rp++, pp++)
+            {
+                  *rp = (png_byte)(((int)(*rp) + (int)(*pp)) & 0xff);
+            }
+         }  //end !UseMMX
+         break;
+      }
+      case PNG_FILTER_VALUE_AVG:
+      {
+         if ( UseMMX && (row_info->pixel_depth > 8) &&
+             (row_info->rowbytes >= 128) )
+         {
+            png_read_filter_row_mmx_avg(row_info, row, prev_row);
+         }  //end if UseMMX
+         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++;
+            }
+         }  //end !UseMMX
+         break;
+      }
+      case PNG_FILTER_VALUE_PAETH:
+      {
+         if ( UseMMX && (row_info->pixel_depth > 8) &&
+             (row_info->rowbytes >= 128) )
+         {
+            png_read_filter_row_mmx_paeth(row_info, row, prev_row);
+         }  //end if UseMMX
+         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++;
+            }
+         }  //end !UseMMX
+         break;
+      }
+      default:
+         png_error(png_ptr, "Bad adaptive filter type");
+         break;
+   }
+}
+#endif
diff --git a/pngwio.c b/pngwio.c
index 13a35b2..5c2f0c2 100644
--- a/pngwio.c
+++ b/pngwio.c
@@ -1,7 +1,7 @@
 
 /* pngwio.c - functions for data output
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngwrite.c b/pngwrite.c
index 33ac2a7..f8f654b 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -1,7 +1,7 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngwtran.c b/pngwtran.c
index bdedf5b..e85b428 100644
--- a/pngwtran.c
+++ b/pngwtran.c
@@ -1,7 +1,7 @@
 
 /* pngwtran.c - transforms the data in a row for PNG writers
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/pngwutil.c b/pngwutil.c
index f3ff2e9..2582547 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -1,7 +1,7 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * libpng 1.0.4d - October 6, 1999
+ * libpng 1.0.4e - October 10, 1999
  * For conditions of distribution and use, see copyright notice in png.h
  * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  * Copyright (c) 1996, 1997 Andreas Dilger
diff --git a/scripts/makefile.beos b/scripts/makefile.beos
index dbebbe0..b91051e 100644
--- a/scripts/makefile.beos
+++ b/scripts/makefile.beos
@@ -31,7 +31,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.4d
+PNGMIN = 1.0.4e
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 # where make install puts libpng.a, libpng.so*, and png.h
diff --git a/scripts/makefile.dec b/scripts/makefile.dec
index 9cfaf7e..93bde55 100644
--- a/scripts/makefile.dec
+++ b/scripts/makefile.dec
@@ -14,7 +14,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.4d
+PNGMIN = 1.0.4e
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 CC=cc
diff --git a/scripts/makefile.linux b/scripts/makefile.linux
index 79c824b..8d04e64 100644
--- a/scripts/makefile.linux
+++ b/scripts/makefile.linux
@@ -34,7 +34,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.4d
+PNGMIN = 1.0.4e
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 INCPATH=$(prefix)/include
diff --git a/scripts/makefile.sco b/scripts/makefile.sco
index 7f6b81a..c292b6f 100644
--- a/scripts/makefile.sco
+++ b/scripts/makefile.sco
@@ -25,7 +25,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.4d
+PNGMIN = 1.0.4e
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 INCPATH=$(prefix)/include
diff --git a/scripts/makefile.solaris b/scripts/makefile.solaris
index 005f259..ab9969a 100644
--- a/scripts/makefile.solaris
+++ b/scripts/makefile.solaris
@@ -36,7 +36,7 @@
 # read libpng.txt or png.h to see why PNGMAJ is 2.  You should not
 # have to change it.
 PNGMAJ = 2
-PNGMIN = 1.0.4d
+PNGMIN = 1.0.4e
 PNGVER = $(PNGMAJ).$(PNGMIN)
 
 INCPATH=$(prefix)/include
diff --git a/scripts/pngdef.pas b/scripts/pngdef.pas
index 995ddaf..67784f6 100644
--- a/scripts/pngdef.pas
+++ b/scripts/pngdef.pas
@@ -3,7 +3,7 @@
 interface
 
 const
-  PNG_LIBPNG_VER_STRING = '1.0.4d';
+  PNG_LIBPNG_VER_STRING = '1.0.4e';
   PNG_LIBPNG_VER        =  10005;
 
 type