OSDN Git Service

This commit was generated by cvs2svn to compensate for changes in r104181,
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Sep 2005 17:04:02 +0000 (17:04 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Sep 2005 17:04:02 +0000 (17:04 +0000)
which included commits to RCS files with non-trunk default branches.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@104182 138bc75d-0d04-0410-961f-82ee72b054a4

45 files changed:
zlib/as400/compile.clp
zlib/as400/readme.txt
zlib/as400/zlib.inc
zlib/contrib/ada/mtest.adb
zlib/contrib/ada/read.adb
zlib/contrib/ada/readme.txt
zlib/contrib/ada/zlib-streams.adb
zlib/contrib/ada/zlib-streams.ads
zlib/contrib/ada/zlib-thin.adb
zlib/contrib/ada/zlib-thin.ads
zlib/contrib/ada/zlib.adb
zlib/contrib/ada/zlib.ads
zlib/contrib/ada/zlib.gpr
zlib/contrib/delphi/ZLib.pas
zlib/contrib/infback9/infback9.c
zlib/contrib/infback9/infback9.h
zlib/contrib/infback9/inftree9.c
zlib/contrib/infback9/inftree9.h
zlib/contrib/inflate86/inffas86.c
zlib/contrib/inflate86/inffast.S
zlib/contrib/masm686/match.asm
zlib/contrib/masmx86/gvmat32.asm
zlib/contrib/masmx86/gvmat32c.c
zlib/contrib/masmx86/inffas32.asm
zlib/contrib/masmx86/mkasm.bat
zlib/contrib/minizip/crypt.h
zlib/contrib/minizip/ioapi.c
zlib/contrib/minizip/ioapi.h
zlib/contrib/minizip/iowin32.c
zlib/contrib/minizip/iowin32.h
zlib/contrib/pascal/zlibpas.pas
zlib/contrib/puff/puff.c
zlib/contrib/testzlib/testzlib.c
zlib/contrib/vstudio/readme.txt
zlib/contrib/vstudio/vc7/miniunz.vcproj
zlib/contrib/vstudio/vc7/minizip.vcproj
zlib/contrib/vstudio/vc7/zlib.rc
zlib/contrib/vstudio/vc7/zlibstat.vcproj
zlib/contrib/vstudio/vc7/zlibvc.sln
zlib/contrib/vstudio/vc7/zlibvc.vcproj
zlib/old/Makefile.riscos
zlib/old/README
zlib/qnx/package.qpg
zlib/win32/DLL_FAQ.txt
zlib/win32/zlib1.rc

index dcd2421..8554951 100644 (file)
                                  &MODLIB/INFTREES    &MODLIB/TREES       +
                                  &MODLIB/UNCOMPR     &MODLIB/ZUTIL)      +
                           SRCFILE(&SRCLIB/&CTLFILE) SRCMBR(BNDSRC) +
-                          TEXT('ZLIB 1.2.1') TGTRLS(V4R4M0)
+                          TEXT('ZLIB 1.2.3') TGTRLS(V4R4M0)
 
              ENDPGM
index eef7cb2..beae13f 100644 (file)
@@ -1,4 +1,4 @@
-        ZLIB version 1.2.1 for AS400 installation instructions
+        ZLIB version 1.2.3 for AS400 installation instructions
 
 I) From an AS400 *SAVF file:
 
index 03c6cf0..7bbfb7e 100644 (file)
@@ -1,7 +1,7 @@
       *  ZLIB.INC - Interface to the general purpose compression library
       *
       *  ILE RPG400 version by Patrick Monnerat, DATASPHERE.
-      *  Version 1.2.1
+      *  Version 1.2.3
       *
       *
       *  WARNING:
       *                               Constants
       **************************************************************************
       *
-     D ZLIB_VERSION    C                   '1.2.1'                            Header's version
-     D ZLIB_VERNUM     C                   X'1210'
+      *  Versioning information.
+      *
+     D ZLIB_VERSION    C                   '1.2.3'
+     D ZLIB_VERNUM     C                   X'1230'
+      *
+      *  Other equates.
       *
      D Z_NO_FLUSH      C                   0
      D Z_SYNC_FLUSH    C                   2
index 91a96cd..c4dfd08 100644 (file)
@@ -5,10 +5,10 @@
 --                                                            --
 --  Open source license information is in the zlib.ads file.  --
 ----------------------------------------------------------------
---  Continuous test for ZLib multithreading. If the test is fail
---  Wou should provide thread safe allocation routines for the Z_Stream.
+--  Continuous test for ZLib multithreading. If the test would fail
+--  we should provide thread safe allocation routines for the Z_Stream.
 --
---  $Id: mtest.adb,v 1.2 2003/08/12 12:11:05 vagul Exp $
+--  $Id: mtest.adb,v 1.4 2004/07/23 07:49:54 vagul Exp $
 
 with ZLib;
 with Ada.Streams;
@@ -148,6 +148,9 @@ procedure MTest is
 
    pragma Unreferenced (Test);
 
+   Dummy : Character;
+
 begin
-   null;
+   Ada.Text_IO.Get_Immediate (Dummy);
+   Stop := True;
 end MTest;
index 184ea00..1f2efbf 100644 (file)
@@ -6,7 +6,7 @@
 --  Open source license information is in the zlib.ads file.  --
 ----------------------------------------------------------------
 
---  $Id: read.adb,v 1.7 2003/08/12 12:12:35 vagul Exp $
+--  $Id: read.adb,v 1.8 2004/05/31 10:53:40 vagul Exp $
 
 --  Test/demo program for the generic read interface.
 
@@ -68,7 +68,11 @@ procedure Read is
    --  ZLib.Read
    --  reading data from the File_In.
 
-   procedure Read is new ZLib.Read (Read, Read_Buffer, Read_First, Read_Last);
+   procedure Read is new ZLib.Read
+                           (Read,
+                            Read_Buffer,
+                            Rest_First => Read_First,
+                            Rest_Last  => Read_Last);
 
    ----------
    -- Read --
@@ -103,6 +107,7 @@ procedure Read is
       Pack_Size := 0;
       Offset := 1;
       Read_First := Read_Buffer'Last + 1;
+      Read_Last  := Read_Buffer'Last;
    end Reset;
 
 begin
index ad02c22..ce4d2ca 100644 (file)
@@ -1,23 +1,34 @@
-
-                       ZLib for Ada thick binding (ZLib.Ada)
-                       Release 1.2
+                        ZLib for Ada thick binding (ZLib.Ada)
+                        Release 1.3
 
 ZLib.Ada is a thick binding interface to the popular ZLib data
 compression library, available at http://www.gzip.org/zlib/.
 It provides Ada-style access to the ZLib C library.
 
 
-       Here are the main changes since ZLib.Ada 1.1:
+        Here are the main changes since ZLib.Ada 1.2:
+
+- Attension: ZLib.Read generic routine have a initialization requirement
+  for Read_Last parameter now. It is a bit incompartible with previous version,
+  but extends functionality, we could use new parameters Allow_Read_Some and
+  Flush now.
+
+- Added Is_Open routines to ZLib and ZLib.Streams packages.
 
-- The default header type has a name "Default" now. Auto is used only for
-  automatic GZip/ZLib header detection.
+- Add pragma Assert to check Stream_Element is 8 bit.
 
-- Added test for multitasking mtest.adb.
+- Fix extraction to buffer with exact known decompressed size. Error reported by
+  Steve Sangwine.
 
-- Added GNAT project file zlib.gpr.
+- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits
+  computers. Patch provided by Pascal Obry.
 
+- Add Status_Error exception definition.
 
-       How to build ZLib.Ada under GNAT
+- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit.
+
+
+        How to build ZLib.Ada under GNAT
 
 You should have the ZLib library already build on your computer, before
 building ZLib.Ada. Make the directory of ZLib.Ada sources current and
@@ -30,7 +41,7 @@ Or use the GNAT project file build for GNAT 3.15 or later:
   gnatmake -Pzlib.gpr -L<directory where libz.a is>
 
 
-       How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2
+        How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2
 
 1. Make a project with all *.ads and *.adb files from the distribution.
 2. Build the libz.a library from the ZLib C sources.
@@ -40,7 +51,7 @@ Or use the GNAT project file build for GNAT 3.15 or later:
 6. Build the executable using test.adb as a main procedure.
 
 
-       How to use ZLib.Ada
+        How to use ZLib.Ada
 
 The source files test.adb and read.adb are small demo programs that show
 the main functionality of ZLib.Ada.
@@ -50,3 +61,5 @@ The routines from the package specifications are commented.
 
 Homepage: http://zlib-ada.sourceforge.net/
 Author: Dmitriy Anisimkov <anisimkov@yahoo.com>
+
+Contributors: Pascal Obry <pascal@obry.org>, Steve Sangwine <sjs@essex.ac.uk>
index d213b5c..b6497ba 100644 (file)
@@ -6,7 +6,7 @@
 --  Open source license information is in the zlib.ads file.  --
 ----------------------------------------------------------------
 
---  $Id: zlib-streams.adb,v 1.9 2003/08/12 13:15:31 vagul Exp $
+--  $Id: zlib-streams.adb,v 1.10 2004/05/31 10:53:40 vagul Exp $
 
 with Ada.Unchecked_Deallocation;
 
@@ -90,6 +90,7 @@ package body ZLib.Streams is
 
          Stream.Buffer     := new Buffer_Subtype;
          Stream.Rest_First := Stream.Buffer'Last + 1;
+         Stream.Rest_Last  := Stream.Buffer'Last;
       end if;
    end Create;
 
@@ -113,6 +114,15 @@ package body ZLib.Streams is
       end loop;
    end Flush;
 
+   -------------
+   -- Is_Open --
+   -------------
+
+   function Is_Open (Stream : Stream_Type) return Boolean is
+   begin
+      return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer);
+   end Is_Open;
+
    ----------
    -- Read --
    ----------
index 1d5e904..f0193c6 100644 (file)
@@ -6,7 +6,7 @@
 --  Open source license information is in the zlib.ads file.  --
 ----------------------------------------------------------------
 
---  $Id: zlib-streams.ads,v 1.11 2003/08/12 13:15:31 vagul Exp $
+--  $Id: zlib-streams.ads,v 1.12 2004/05/31 10:53:40 vagul Exp $
 
 package ZLib.Streams is
 
@@ -77,6 +77,8 @@ package ZLib.Streams is
    --  !!! When the Need_Header is False ZLib-Ada is using undocumented
    --  ZLib 1.1.4 functionality to do not create/wait for ZLib headers.
 
+   function Is_Open (Stream : Stream_Type) return Boolean;
+
    procedure Close (Stream : in out Stream_Type);
 
 private
index 163bd5b..0ca4a71 100644 (file)
@@ -6,12 +6,11 @@
 --  Open source license information is in the zlib.ads file.  --
 ----------------------------------------------------------------
 
---  $Id: zlib-thin.adb,v 1.6 2003/01/21 15:26:37 vagul Exp $
+--  $Id: zlib-thin.adb,v 1.8 2003/12/14 18:27:31 vagul Exp $
 
 package body ZLib.Thin is
 
-   ZLIB_VERSION : constant Chars_Ptr :=
-      Interfaces.C.Strings.New_String ("1.1.4");
+   ZLIB_VERSION  : constant Chars_Ptr := zlibVersion;
 
    Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit;
 
@@ -38,14 +37,6 @@ package body ZLib.Thin is
    ------------------
 
    function Deflate_Init
-     (strm  : in Z_Streamp;
-      level : in Int := Z_DEFAULT_COMPRESSION)
-      return  Int is
-   begin
-      return deflateInit (strm, level, ZLIB_VERSION, Z_Stream_Size);
-   end Deflate_Init;
-
-   function Deflate_Init
      (strm       : Z_Streamp;
       level      : Int;
       method     : Int;
@@ -69,16 +60,15 @@ package body ZLib.Thin is
    -- Inflate_Init --
    ------------------
 
-   function Inflate_Init (strm : Z_Streamp) return Int is
-   begin
-      return inflateInit (strm, ZLIB_VERSION, Z_Stream_Size);
-   end Inflate_Init;
-
    function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is
    begin
       return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size);
    end Inflate_Init;
 
+   ------------------------
+   -- Last_Error_Message --
+   ------------------------
+
    function Last_Error_Message (Strm : in Z_Stream) return String is
       use Interfaces.C.Strings;
    begin
@@ -89,54 +79,28 @@ package body ZLib.Thin is
       end if;
    end Last_Error_Message;
 
-   -------------
-   -- Need_In --
-   -------------
-
-   function Need_In (strm : Z_Stream) return Boolean is
-   begin
-      return strm.Avail_In = 0;
-   end Need_In;
-
-   --------------
-   -- Need_Out --
-   --------------
-
-   function Need_Out (strm : Z_Stream) return Boolean is
-   begin
-      return strm.Avail_Out = 0;
-   end Need_Out;
-
    ------------
    -- Set_In --
    ------------
 
    procedure Set_In
      (Strm   : in out Z_Stream;
-      Buffer : in Byte_Access;
-      Size   : in UInt) is
+      Buffer : in     Voidp;
+      Size   : in     UInt) is
    begin
       Strm.Next_In  := Buffer;
       Strm.Avail_In := Size;
    end Set_In;
 
-   procedure Set_In
-     (Strm   : in out Z_Stream;
-      Buffer : in Voidp;
-      Size   : in UInt) is
-   begin
-      Set_In (Strm, Bytes.To_Pointer (Buffer), Size);
-   end Set_In;
-
    ------------------
    -- Set_Mem_Func --
    ------------------
 
    procedure Set_Mem_Func
      (Strm   : in out Z_Stream;
-      Opaque : in Voidp;
-      Alloc  : in alloc_func;
-      Free   : in free_func) is
+      Opaque : in     Voidp;
+      Alloc  : in     alloc_func;
+      Free   : in     free_func) is
    begin
       Strm.opaque := Opaque;
       Strm.zalloc := Alloc;
@@ -149,21 +113,13 @@ package body ZLib.Thin is
 
    procedure Set_Out
      (Strm   : in out Z_Stream;
-      Buffer : in Byte_Access;
-      Size   : in UInt) is
+      Buffer : in     Voidp;
+      Size   : in     UInt) is
    begin
       Strm.Next_Out  := Buffer;
       Strm.Avail_Out := Size;
    end Set_Out;
 
-   procedure Set_Out
-     (Strm   : in out Z_Stream;
-      Buffer : in Voidp;
-      Size   : in UInt) is
-   begin
-      Set_Out (Strm, Bytes.To_Pointer (Buffer), Size);
-   end Set_Out;
-
    --------------
    -- Total_In --
    --------------
index c227374..d4407eb 100644 (file)
@@ -6,10 +6,11 @@
 --  Open source license information is in the zlib.ads file.  --
 ----------------------------------------------------------------
 
---  $Id: zlib-thin.ads,v 1.8 2003/08/12 13:16:51 vagul Exp $
+--  $Id: zlib-thin.ads,v 1.11 2004/07/23 06:33:11 vagul Exp $
 
 with Interfaces.C.Strings;
-with System.Address_To_Access_Conversions;
+
+with System;
 
 private package ZLib.Thin is
 
@@ -36,18 +37,18 @@ private package ZLib.Thin is
                                                 --  zconf.h:216
    type Int is new Interfaces.C.int;
 
-   type ULong is new Interfaces.C.unsigned;     --  32 bits or more
-                                                --  zconf.h:217
+   type ULong is new Interfaces.C.unsigned_long;     --  32 bits or more
+                                                     --  zconf.h:217
    subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr;
 
    type ULong_Access is access ULong;
    type Int_Access is access Int;
-   subtype Voidp is System.Address;            --  zconf.h:232
 
-   package Bytes is new System.Address_To_Access_Conversions (Byte);
+   subtype Voidp is System.Address;            --  zconf.h:232
 
-   subtype Byte_Access is Bytes.Object_Pointer;
+   subtype Byte_Access is Voidp;
 
+   Nul : constant Voidp := System.Null_Address;
    --  end from zconf
 
    Z_NO_FLUSH : constant := 8#0000#;   --  zlib.h:125
@@ -251,12 +252,6 @@ private package ZLib.Thin is
       stream_size : Int)
       return        Int;
 
-   function Deflate_Init
-     (strm  : in Z_Streamp;
-      level : in Int := Z_DEFAULT_COMPRESSION)
-      return  Int;
-   pragma Inline (Deflate_Init);
-
    function deflateInit2
      (strm        : Z_Streamp;
       level       : Int;
@@ -284,9 +279,6 @@ private package ZLib.Thin is
       stream_size : Int)
       return        Int;
 
-   function Inflate_Init (strm : Z_Streamp) return Int;
-   pragma Inline (Inflate_Init);
-
    function inflateInit2
      (strm        : in Z_Streamp;
       windowBits  : in Int;
@@ -318,20 +310,6 @@ private package ZLib.Thin is
    --  has dropped to zero. The application must initialize zalloc, zfree and
    --  opaque before calling the init function.
 
-   function Need_In (strm : in Z_Stream) return Boolean;
-   --  return true when we do not need to setup Next_In and Avail_In fields.
-   pragma Inline (Need_In);
-
-   function Need_Out (strm : in Z_Stream) return Boolean;
-   --  return true when we do not need to setup Next_Out and Avail_Out field.
-   pragma Inline (Need_Out);
-
-   procedure Set_In
-     (Strm   : in out Z_Stream;
-      Buffer : in Byte_Access;
-      Size   : in UInt);
-   pragma Inline (Set_In);
-
    procedure Set_In
      (Strm   : in out Z_Stream;
       Buffer : in Voidp;
@@ -340,12 +318,6 @@ private package ZLib.Thin is
 
    procedure Set_Out
      (Strm   : in out Z_Stream;
-      Buffer : in Byte_Access;
-      Size   : in UInt);
-   pragma Inline (Set_Out);
-
-   procedure Set_Out
-     (Strm   : in out Z_Stream;
       Buffer : in Voidp;
       Size   : in UInt);
    pragma Inline (Set_Out);
@@ -388,19 +360,13 @@ private package ZLib.Thin is
 
    function zlibCompileFlags return ULong;
 
-   function deflatePrime
-     (strm     : Z_Streamp;
-      bits     : Int;
-      value    : Int)
-      return     Int;
-
 private
 
    type Z_Stream is record            -- zlib.h:68
-      Next_In   : Byte_Access;        -- next input byte
+      Next_In   : Voidp      := Nul;  -- next input byte
       Avail_In  : UInt       := 0;    -- number of bytes available at next_in
       Total_In  : ULong      := 0;    -- total nb of input bytes read so far
-      Next_Out  : Byte_Access;        -- next output byte should be put there
+      Next_Out  : Voidp      := Nul;  -- next output byte should be put there
       Avail_Out : UInt       := 0;    -- remaining free space at next_out
       Total_Out : ULong      := 0;    -- total nb of bytes output so far
       msg       : Chars_Ptr;          -- last error message, NULL if no error
@@ -460,14 +426,13 @@ private
    pragma Import (C, inflateSyncPoint, "inflateSyncPoint");
    pragma Import (C, get_crc_table, "get_crc_table");
 
-   --  added in zlib 1.2.1:
+   --  since zlib 1.2.0:
 
    pragma Import (C, inflateCopy, "inflateCopy");
    pragma Import (C, compressBound, "compressBound");
    pragma Import (C, deflateBound, "deflateBound");
    pragma Import (C, gzungetc, "gzungetc");
    pragma Import (C, zlibCompileFlags, "zlibCompileFlags");
-   pragma Import (C, deflatePrime, "deflatePrime");
 
    pragma Import (C, inflateBackInit, "inflateBackInit_");
 
index 93bf885..8b6fd68 100644 (file)
@@ -1,12 +1,12 @@
 ----------------------------------------------------------------
 --  ZLib for Ada thick binding.                               --
 --                                                            --
---  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
+--  Copyright (C) 2002-2004 Dmitriy Anisimkov                 --
 --                                                            --
 --  Open source license information is in the zlib.ads file.  --
 ----------------------------------------------------------------
 
---  $Id: zlib.adb,v 1.19 2003/07/13 16:02:19 vagul Exp $
+--  $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $
 
 with Ada.Exceptions;
 with Ada.Unchecked_Conversion;
@@ -34,7 +34,7 @@ package body ZLib is
        VERSION_ERROR);
 
    type Flate_Step_Function is access
-     function (Strm : Thin.Z_Streamp; flush : Thin.Int) return Thin.Int;
+     function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int;
    pragma Convention (C, Flate_Step_Function);
 
    type Flate_End_Function is access
@@ -82,13 +82,13 @@ package body ZLib is
    Flush_Finish : constant array (Boolean) of Flush_Mode
      := (True => Finish, False => No_Flush);
 
-   procedure Raise_Error (Stream : Z_Stream);
+   procedure Raise_Error (Stream : in Z_Stream);
    pragma Inline (Raise_Error);
 
-   procedure Raise_Error (Message : String);
+   procedure Raise_Error (Message : in String);
    pragma Inline (Raise_Error);
 
-   procedure Check_Error (Stream : Z_Stream; Code : Thin.Int);
+   procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int);
 
    procedure Free is new Ada.Unchecked_Deallocation
       (Z_Stream, Z_Stream_Access);
@@ -118,7 +118,7 @@ package body ZLib is
    -- Check_Error --
    -----------------
 
-   procedure Check_Error (Stream : Z_Stream; Code : Thin.Int) is
+   procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is
       use type Thin.Int;
    begin
       if Code /= Thin.Z_OK then
@@ -138,10 +138,11 @@ package body ZLib is
    is
       Code : Thin.Int;
    begin
-      Code := Flate (Filter.Compression).Done
-          (To_Thin_Access (Filter.Strm));
+      if not Ignore_Error and then not Is_Open (Filter) then
+         raise Status_Error;
+      end if;
 
-      Filter.Opened := False;
+      Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm));
 
       if Ignore_Error or else Code = Thin.Z_OK then
          Free (Filter.Strm);
@@ -154,7 +155,7 @@ package body ZLib is
             Ada.Exceptions.Raise_Exception
                (ZLib_Error'Identity,
                 Return_Code_Enum'Image (Return_Code (Code))
-                & ": " & Error_Message);
+                  & ": " & Error_Message);
          end;
       end if;
    end Close;
@@ -170,10 +171,9 @@ package body ZLib is
    is
       use Thin;
    begin
-      return Unsigned_32 (crc32
-        (ULong (CRC),
-         Bytes.To_Pointer (Data'Address),
-         Data'Length));
+      return Unsigned_32 (crc32 (ULong (CRC),
+                                 Data'Address,
+                                 Data'Length));
    end CRC32;
 
    procedure CRC32
@@ -192,13 +192,17 @@ package body ZLib is
       Level        : in     Compression_Level  := Default_Compression;
       Strategy     : in     Strategy_Type      := Default_Strategy;
       Method       : in     Compression_Method := Deflated;
-      Window_Bits  : in     Window_Bits_Type   := 15;
-      Memory_Level : in     Memory_Level_Type  := 8;
+      Window_Bits  : in     Window_Bits_Type   := Default_Window_Bits;
+      Memory_Level : in     Memory_Level_Type  := Default_Memory_Level;
       Header       : in     Header_Type        := Default)
    is
       use type Thin.Int;
       Win_Bits : Thin.Int := Thin.Int (Window_Bits);
    begin
+      if Is_Open (Filter) then
+         raise Status_Error;
+      end if;
+
       --  We allow ZLib to make header only in case of default header type.
       --  Otherwise we would either do header by ourselfs, or do not do
       --  header at all.
@@ -216,10 +220,9 @@ package body ZLib is
          Filter.Offset := Simple_GZip_Header'Last + 1;
       end if;
 
-      Filter.Strm := new Z_Stream;
+      Filter.Strm        := new Z_Stream;
       Filter.Compression := True;
       Filter.Stream_End  := False;
-      Filter.Opened      := True;
       Filter.Header      := Header;
 
       if Thin.Deflate_Init
@@ -255,18 +258,18 @@ package body ZLib is
    -----------------------
 
    procedure Generic_Translate
-     (Filter : in out ZLib.Filter_Type;
-      In_Buffer_Size  : Integer := Default_Buffer_Size;
-      Out_Buffer_Size : Integer := Default_Buffer_Size)
+     (Filter          : in out ZLib.Filter_Type;
+      In_Buffer_Size  : in     Integer := Default_Buffer_Size;
+      Out_Buffer_Size : in     Integer := Default_Buffer_Size)
    is
-      In_Buffer : Stream_Element_Array
-         (1 .. Stream_Element_Offset (In_Buffer_Size));
+      In_Buffer  : Stream_Element_Array
+                     (1 .. Stream_Element_Offset (In_Buffer_Size));
       Out_Buffer : Stream_Element_Array
-        (1 .. Stream_Element_Offset (Out_Buffer_Size));
-      Last : Stream_Element_Offset;
-      In_Last : Stream_Element_Offset;
-      In_First : Stream_Element_Offset;
-      Out_Last : Stream_Element_Offset;
+                     (1 .. Stream_Element_Offset (Out_Buffer_Size));
+      Last       : Stream_Element_Offset;
+      In_Last    : Stream_Element_Offset;
+      In_First   : Stream_Element_Offset;
+      Out_Last   : Stream_Element_Offset;
    begin
       Main : loop
          Data_In (In_Buffer, Last);
@@ -275,18 +278,21 @@ package body ZLib is
 
          loop
             Translate
-              (Filter,
-               In_Buffer (In_First .. Last),
-               In_Last,
-               Out_Buffer,
-               Out_Last,
-               Flush_Finish (Last < In_Buffer'First));
+              (Filter   => Filter,
+               In_Data  => In_Buffer (In_First .. Last),
+               In_Last  => In_Last,
+               Out_Data => Out_Buffer,
+               Out_Last => Out_Last,
+               Flush    => Flush_Finish (Last < In_Buffer'First));
 
-            Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last));
+            if Out_Buffer'First <= Out_Last then
+               Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last));
+            end if;
 
             exit Main when Stream_End (Filter);
 
             --  The end of in buffer.
+
             exit when In_Last = Last;
 
             In_First := In_Last + 1;
@@ -301,7 +307,7 @@ package body ZLib is
 
    procedure Inflate_Init
      (Filter      : in out Filter_Type;
-      Window_Bits : in     Window_Bits_Type := 15;
+      Window_Bits : in     Window_Bits_Type := Default_Window_Bits;
       Header      : in     Header_Type      := Default)
    is
       use type Thin.Int;
@@ -320,6 +326,10 @@ package body ZLib is
       end Check_Version;
 
    begin
+      if Is_Open (Filter) then
+         raise Status_Error;
+      end if;
+
       case Header is
          when None =>
             Check_Version;
@@ -344,10 +354,9 @@ package body ZLib is
          when Default => null;
       end case;
 
-      Filter.Strm := new Z_Stream;
+      Filter.Strm        := new Z_Stream;
       Filter.Compression := False;
       Filter.Stream_End  := False;
-      Filter.Opened      := True;
       Filter.Header      := Header;
 
       if Thin.Inflate_Init
@@ -357,16 +366,25 @@ package body ZLib is
       end if;
    end Inflate_Init;
 
+   -------------
+   -- Is_Open --
+   -------------
+
+   function Is_Open (Filter : in Filter_Type) return Boolean is
+   begin
+      return Filter.Strm /= null;
+   end Is_Open;
+
    -----------------
    -- Raise_Error --
    -----------------
 
-   procedure Raise_Error (Message : String) is
+   procedure Raise_Error (Message : in String) is
    begin
       Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message);
    end Raise_Error;
 
-   procedure Raise_Error (Stream : Z_Stream) is
+   procedure Raise_Error (Stream : in Z_Stream) is
    begin
       Raise_Error (Last_Error_Message (Stream));
    end Raise_Error;
@@ -378,21 +396,29 @@ package body ZLib is
    procedure Read
      (Filter : in out Filter_Type;
       Item   :    out Ada.Streams.Stream_Element_Array;
-      Last   :    out Ada.Streams.Stream_Element_Offset)
+      Last   :    out Ada.Streams.Stream_Element_Offset;
+      Flush  : in     Flush_Mode := No_Flush)
    is
       In_Last    : Stream_Element_Offset;
       Item_First : Ada.Streams.Stream_Element_Offset := Item'First;
+      V_Flush    : Flush_Mode := Flush;
 
    begin
       pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1);
+      pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last);
 
       loop
-         if Rest_First > Buffer'Last then
+         if Rest_Last = Buffer'First - 1 then
+            V_Flush := Finish;
+
+         elsif Rest_First > Rest_Last then
             Read (Buffer, Rest_Last);
             Rest_First := Buffer'First;
-         end if;
 
-         pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last);
+            if Rest_Last < Buffer'First then
+               V_Flush := Finish;
+            end if;
+         end if;
 
          Translate
            (Filter   => Filter,
@@ -400,11 +426,13 @@ package body ZLib is
             In_Last  => In_Last,
             Out_Data => Item (Item_First .. Item'Last),
             Out_Last => Last,
-            Flush    => Flush_Finish (Rest_Last < Rest_First));
+            Flush    => V_Flush);
 
          Rest_First := In_Last + 1;
 
-         exit when Last = Item'Last or else Stream_End (Filter);
+         exit when Stream_End (Filter)
+           or else Last = Item'Last
+           or else (Last >= Item'First and then Allow_Read_Some);
 
          Item_First := Last + 1;
       end loop;
@@ -489,11 +517,11 @@ package body ZLib is
       Code : Thin.Int;
 
    begin
-      if Filter.Opened = False then
-         raise ZLib_Error;
+      if not Is_Open (Filter) then
+         raise Status_Error;
       end if;
 
-      if Out_Data'Length = 0 then
+      if Out_Data'Length = 0 and then In_Data'Length = 0 then
          raise Constraint_Error;
       end if;
 
@@ -514,7 +542,6 @@ package body ZLib is
          - Stream_Element_Offset (Avail_In (Filter.Strm.all));
       Out_Last := Out_Data'Last
          - Stream_Element_Offset (Avail_Out (Filter.Strm.all));
-
    end Translate_Auto;
 
    --------------------
@@ -529,7 +556,7 @@ package body ZLib is
       Out_Last  :    out Ada.Streams.Stream_Element_Offset;
       Flush     : in     Flush_Mode)
    is
-      Out_First  : Stream_Element_Offset;
+      Out_First : Stream_Element_Offset;
 
       procedure Add_Data (Data : in Stream_Element_Array);
       --  Add data to stream from the Filter.Offset till necessary,
@@ -596,7 +623,7 @@ package body ZLib is
          Add_Data (Simple_GZip_Header);
 
          Translate_Auto
-           (Filter => Filter,
+           (Filter   => Filter,
             In_Data  => In_Data,
             In_Last  => In_Last,
             Out_Data => Out_Data (Out_First .. Out_Data'Last),
@@ -604,7 +631,6 @@ package body ZLib is
             Flush    => Flush);
 
          CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last));
-
       end if;
 
       if Filter.Stream_End and then Out_Last <= Out_Data'Last then
@@ -642,10 +668,11 @@ package body ZLib is
    procedure Write
      (Filter : in out Filter_Type;
       Item   : in     Ada.Streams.Stream_Element_Array;
-      Flush  : in     Flush_Mode)
+      Flush  : in     Flush_Mode := No_Flush)
    is
-      Buffer : Stream_Element_Array (1 .. Buffer_Size);
-      In_Last, Out_Last : Stream_Element_Offset;
+      Buffer   : Stream_Element_Array (1 .. Buffer_Size);
+      In_Last  : Stream_Element_Offset;
+      Out_Last : Stream_Element_Offset;
       In_First : Stream_Element_Offset := Item'First;
    begin
       if Item'Length = 0 and Flush = No_Flush then
@@ -654,7 +681,7 @@ package body ZLib is
 
       loop
          Translate
-           (Filter => Filter,
+           (Filter   => Filter,
             In_Data  => Item (In_First .. Item'Last),
             In_Last  => In_Last,
             Out_Data => Buffer,
index b72e4d2..79ffc40 100644 (file)
@@ -1,7 +1,7 @@
 ------------------------------------------------------------------------------
 --                      ZLib for Ada thick binding.                         --
 --                                                                          --
---              Copyright (C) 2002-2003 Dmitriy Anisimkov                   --
+--              Copyright (C) 2002-2004 Dmitriy Anisimkov                   --
 --                                                                          --
 --  This library is free software; you can redistribute it and/or modify    --
 --  it under the terms of the GNU General Public License as published by    --
@@ -25,7 +25,7 @@
 --  covered by the  GNU Public License.                                     --
 ------------------------------------------------------------------------------
 
---  $Id: zlib.ads,v 1.17 2003/08/12 13:19:07 vagul Exp $
+--  $Id: zlib.ads,v 1.26 2004/09/06 06:53:19 vagul Exp $
 
 with Ada.Streams;
 
@@ -33,7 +33,8 @@ with Interfaces;
 
 package ZLib is
 
-   ZLib_Error : exception;
+   ZLib_Error   : exception;
+   Status_Error : exception;
 
    type Compression_Level is new Integer range -1 .. 9;
 
@@ -55,12 +56,15 @@ package ZLib is
 
    subtype Count is Ada.Streams.Stream_Element_Count;
 
+   Default_Memory_Level : constant Memory_Level_Type := 8;
+   Default_Window_Bits  : constant Window_Bits_Type  := 15;
+
    ----------------------------------
    -- Compression method constants --
    ----------------------------------
 
    Deflated : constant Compression_Method;
-   --  Only one method allowed in this ZLib version.
+   --  Only one method allowed in this ZLib version
 
    ---------------------------------
    -- Compression level constants --
@@ -79,21 +83,29 @@ package ZLib is
    --  Regular way for compression, no flush
 
    Partial_Flush : constant Flush_Mode;
-   --  will be removed, use Z_SYNC_FLUSH instead
+   --  Will be removed, use Z_SYNC_FLUSH instead
 
    Sync_Flush    : constant Flush_Mode;
-   --  all pending output is flushed to the output buffer and the output
+   --  All pending output is flushed to the output buffer and the output
    --  is aligned on a byte boundary, so that the decompressor can get all
    --  input data available so far. (In particular avail_in is zero after the
    --  call if enough output space has been provided  before the call.)
    --  Flushing may degrade compression for some compression algorithms and so
    --  it should be used only when necessary.
 
+   Block_Flush   : constant Flush_Mode;
+   --  Z_BLOCK requests that inflate() stop
+   --  if and when it get to the next deflate block boundary. When decoding the
+   --  zlib or gzip format, this will cause inflate() to return immediately
+   --  after the header and before the first block. When doing a raw inflate,
+   --  inflate() will go ahead and process the first block, and will return
+   --  when it gets to the end of that block, or when it runs out of data.
+
    Full_Flush    : constant Flush_Mode;
-   --  all output is flushed as with SYNC_FLUSH, and the compression state
+   --  All output is flushed as with SYNC_FLUSH, and the compression state
    --  is reset so that decompression can restart from this point if previous
    --  compressed data has been damaged or if random access is desired. Using
-   --  FULL_FLUSH too often can seriously degrade the compression.
+   --  Full_Flush too often can seriously degrade the compression.
 
    Finish        : constant Flush_Mode;
    --  Just for tell the compressor that input data is complete.
@@ -111,7 +123,7 @@ package ZLib is
 
    Default_Buffer_Size : constant := 4096;
 
-   type Filter_Type is limited private;
+   type Filter_Type is tagged limited private;
    --  The filter is for compression and for decompression.
    --  The usage of the type is depend of its initialization.
 
@@ -124,8 +136,8 @@ package ZLib is
       Level        : in     Compression_Level  := Default_Compression;
       Strategy     : in     Strategy_Type      := Default_Strategy;
       Method       : in     Compression_Method := Deflated;
-      Window_Bits  : in     Window_Bits_Type   := 15;
-      Memory_Level : in     Memory_Level_Type  := 8;
+      Window_Bits  : in     Window_Bits_Type   := Default_Window_Bits;
+      Memory_Level : in     Memory_Level_Type  := Default_Memory_Level;
       Header       : in     Header_Type        := Default);
    --  Compressor initialization.
    --  When Header parameter is Auto or Default, then default zlib header
@@ -136,7 +148,7 @@ package ZLib is
 
    procedure Inflate_Init
      (Filter      : in out Filter_Type;
-      Window_Bits : in     Window_Bits_Type := 15;
+      Window_Bits : in     Window_Bits_Type := Default_Window_Bits;
       Header      : in     Header_Type      := Default);
    --  Decompressor initialization.
    --  Default header type mean that ZLib default header is expecting in the
@@ -146,10 +158,14 @@ package ZLib is
    --  input compressed stream.
    --  Auto header type mean that header type (GZip or Native) would be
    --  detected automatically in the input stream.
-   --  Note that header types parameter values None, GZip and Auto is
-   --  supporting for inflate routine only in ZLib versions 1.2.0.2 and later.
+   --  Note that header types parameter values None, GZip and Auto are
+   --  supported for inflate routine only in ZLib versions 1.2.0.2 and later.
    --  Deflate_Init is supporting all header types.
 
+   function Is_Open (Filter : in Filter_Type) return Boolean;
+   pragma Inline (Is_Open);
+   --  Is the filter opened for compression or decompression.
+
    procedure Close
      (Filter       : in out Filter_Type;
       Ignore_Error : in     Boolean := False);
@@ -167,31 +183,31 @@ package ZLib is
      (Filter          : in out Filter_Type;
       In_Buffer_Size  : in     Integer := Default_Buffer_Size;
       Out_Buffer_Size : in     Integer := Default_Buffer_Size);
-   --  Compressing/decompressing data arrived from Data_In routine
+   --  Compress/decompress data fetch from Data_In routine and pass the result
    --  to the Data_Out routine. User should provide Data_In and Data_Out
    --  for compression/decompression data flow.
-   --  Compression or decompression depend on initialization of Filter.
+   --  Compression or decompression depend on Filter initialization.
 
    function Total_In (Filter : in Filter_Type) return Count;
    pragma Inline (Total_In);
-   --  Return total number of input bytes read so far.
+   --  Returns total number of input bytes read so far
 
    function Total_Out (Filter : in Filter_Type) return Count;
    pragma Inline (Total_Out);
-   --  Return total number of bytes output so far.
+   --  Returns total number of bytes output so far
 
    function CRC32
      (CRC    : in Unsigned_32;
       Data   : in Ada.Streams.Stream_Element_Array)
       return Unsigned_32;
    pragma Inline (CRC32);
-   --  Calculate CRC32, it could be necessary for make gzip format.
+   --  Compute CRC32, it could be necessary for make gzip format
 
    procedure CRC32
      (CRC  : in out Unsigned_32;
       Data : in     Ada.Streams.Stream_Element_Array);
    pragma Inline (CRC32);
-   --  Calculate CRC32, it could be necessary for make gzip format.
+   --  Compute CRC32, it could be necessary for make gzip format
 
    -------------------------------------------------
    --  Below is more complex low level routines.  --
@@ -204,15 +220,11 @@ package ZLib is
       Out_Data  :    out Ada.Streams.Stream_Element_Array;
       Out_Last  :    out Ada.Streams.Stream_Element_Offset;
       Flush     : in     Flush_Mode);
-   --  Compressing/decompressing the datas from In_Data buffer to the
-   --  Out_Data buffer.
-   --  In_Data is incoming data portion,
-   --  In_Last is the index of last element from In_Data accepted by the
-   --  Filter.
-   --  Out_Data is the buffer for output data from the filter.
-   --  Out_Last is the last element of the received data from Filter.
-   --  To tell the filter that incoming data is complete put the
-   --  Flush parameter to FINISH.
+   --  Compress/decompress the In_Data buffer and place the result into
+   --  Out_Data. In_Last is the index of last element from In_Data accepted by
+   --  the Filter. Out_Last is the last element of the received data from
+   --  Filter. To tell the filter that incoming data are complete put the
+   --  Flush parameter to Finish.
 
    function Stream_End (Filter : in Filter_Type) return Boolean;
    pragma Inline (Stream_End);
@@ -239,10 +251,9 @@ package ZLib is
    procedure Write
      (Filter  : in out Filter_Type;
       Item    : in     Ada.Streams.Stream_Element_Array;
-      Flush   : in     Flush_Mode);
-   --  Compressing/Decompressing data from Item to the
-   --  generic parameter procedure Write.
-   --  Output buffer size could be set in Buffer_Size generic parameter.
+      Flush   : in     Flush_Mode := No_Flush);
+   --  Compress/Decompress data from Item to the generic parameter procedure
+   --  Write. Output buffer size could be set in Buffer_Size generic parameter.
 
    generic
       with procedure Read
@@ -257,33 +268,41 @@ package ZLib is
 
       Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset;
       --  Rest_First have to be initialized to Buffer'Last + 1
+      --  Rest_Last have to be initialized to Buffer'Last
       --  before usage.
 
+      Allow_Read_Some : in Boolean := False;
+      --  Is it allowed to return Last < Item'Last before end of data.
+
    procedure Read
      (Filter : in out Filter_Type;
       Item   :    out Ada.Streams.Stream_Element_Array;
-      Last   :    out Ada.Streams.Stream_Element_Offset);
-   --  Compressing/Decompressing data from generic parameter
-   --  procedure Read to the Item.
-   --  User should provide Buffer for the operation
-   --  and Rest_First variable first time initialized to the Buffer'Last + 1.
+      Last   :    out Ada.Streams.Stream_Element_Offset;
+      Flush  : in     Flush_Mode := No_Flush);
+   --  Compress/Decompress data from generic parameter procedure Read to the
+   --  Item. User should provide Buffer and initialized Rest_First, Rest_Last
+   --  indicators. If Allow_Read_Some is True, Read routines could return
+   --  Last < Item'Last only at end of stream.
 
 private
 
    use Ada.Streams;
 
-   type Flush_Mode is new Integer range 0 .. 4;
+   pragma Assert (Ada.Streams.Stream_Element'Size    =    8);
+   pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8);
+
+   type Flush_Mode is new Integer range 0 .. 5;
 
    type Compression_Method is new Integer range 8 .. 8;
 
    type Strategy_Type is new Integer range 0 .. 3;
 
    No_Flush      : constant Flush_Mode := 0;
+   Partial_Flush : constant Flush_Mode := 1;
    Sync_Flush    : constant Flush_Mode := 2;
    Full_Flush    : constant Flush_Mode := 3;
    Finish        : constant Flush_Mode := 4;
-   Partial_Flush : constant Flush_Mode := 1;
-   --  will be removed, use Z_SYNC_FLUSH instead
+   Block_Flush   : constant Flush_Mode := 5;
 
    Filtered         : constant Strategy_Type := 1;
    Huffman_Only     : constant Strategy_Type := 2;
@@ -296,7 +315,7 @@ private
 
    type Z_Stream_Access is access all Z_Stream;
 
-   type Filter_Type is record
+   type Filter_Type is tagged limited record
       Strm        : Z_Stream_Access;
       Compression : Boolean;
       Stream_End  : Boolean;
@@ -304,8 +323,6 @@ private
       CRC         : Unsigned_32;
       Offset      : Stream_Element_Offset;
       --  Offset for gzip header/footer output.
-
-      Opened      : Boolean := False;
    end record;
 
 end ZLib;
index 0f58985..296b22a 100644 (file)
@@ -3,10 +3,10 @@ project Zlib is
    for Languages use ("Ada");
    for Source_Dirs use (".");
    for Object_Dir use ".";
-   for Main use ("test.adb", "mtest.adb", "read.adb");
+   for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo");
 
    package Compiler is
-      for Default_Switches ("ada") use ("-gnatwbcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst");
+      for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst");
    end Compiler;
 
    package Linker is
@@ -18,4 +18,3 @@ project Zlib is
    end Builder;
 
 end Zlib;
-
index 61ffd08..3f2b8b4 100644 (file)
@@ -152,7 +152,7 @@ procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
   const OutBuf: Pointer; BufSize: Integer);
 
 const
-  zlib_version = '1.2.1';
+  zlib_version = '1.2.3';
 
 type
   EZlibError = class(Exception);
@@ -344,7 +344,7 @@ begin
     strm.avail_out := OutBytes;
     DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
     try
-      while DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END do
+      while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
       begin
         P := OutBuf;
         Inc(OutBytes, BufInc);
@@ -510,7 +510,7 @@ begin
         Result := Count - FZRec.avail_out;
         Exit;
       end;
-          FZRec.next_in := FBuffer;
+      FZRec.next_in := FBuffer;
       FStrmPos := FStrm.Position;
       Progress(Self);
     end;
index 34a95fc..f5ddde6 100644 (file)
@@ -430,6 +430,9 @@ void FAR *out_desc;
                 }
             }
 
+            /* handle error breaks in while */
+            if (mode == BAD) break;
+
             /* build code tables */
             state->next = state->codes;
             lencode = (code const FAR *)(state->next);
index 10bf58c..1073c0a 100644 (file)
  * zlib.h must be included before this header file.
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm,
                                     in_func in, void FAR *in_desc,
                                     out_func out, void FAR *out_desc));
@@ -27,3 +31,7 @@ ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm,
 #define inflateBack9Init(strm, window) \
         inflateBack9Init_((strm), (window), \
         ZLIB_VERSION, sizeof(z_stream))
+
+#ifdef __cplusplus
+}
+#endif
index fe76a1b..0993f75 100644 (file)
@@ -1,5 +1,5 @@
 /* inftree9.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 const char inflate9_copyright[] =
-   " inflate9 1.2.1 Copyright 1995-2003 Mark Adler ";
+   " inflate9 1.2.3 Copyright 1995-2005 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -64,7 +64,7 @@ unsigned short FAR *work;
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
         130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
-        133, 133, 133, 133, 144, 76, 66};
+        133, 133, 133, 133, 144, 201, 196};
     static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
         65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
@@ -128,7 +128,7 @@ unsigned short FAR *work;
         left -= count[len];
         if (left < 0) return -1;        /* over-subscribed */
     }
-    if (left > 0 && (type == CODES || (codes - count[0] != 1)))
+    if (left > 0 && (type == CODES || max != 1))
         return -1;                      /* incomplete set */
 
     /* generate offsets into symbol table for each length for sorting */
index 6a699a7..a268084 100644 (file)
@@ -36,12 +36,12 @@ typedef struct {
  */
 
 /* Maximum size of dynamic tree.  The maximum found in a long but non-
-   exhaustive search was 1004 code structures (850 for length/literals
-   and 154 for distances, the latter actually the result of an
+   exhaustive search was 1444 code structures (852 for length/literals
+   and 592 for distances, the latter actually the result of an
    exhaustive search).  The true maximum is not known, but the value
    below is more than safe. */
-#define ENOUGH 1440
-#define MAXD 154
+#define ENOUGH 2048
+#define MAXD 592
 
 /* Type of code to build for inftable() */
 typedef enum {
index 4534693..6da7635 100644 (file)
@@ -7,6 +7,15 @@
  * Copyright (C) 2003 Chris Anderson <christop@charm.net>
  * Please use the copyright conditions above.
  *
+ * Dec-29-2003 -- I added AMD64 inflate asm support.  This version is also
+ * slightly quicker on x86 systems because, instead of using rep movsb to copy
+ * data, it uses rep movsw, which moves data in 2-byte chunks instead of single
+ * bytes.  I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates
+ * from http://fedora.linux.duke.edu/fc1_x86_64
+ * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with
+ * 1GB ram.  The 64-bit version is about 4% faster than the 32-bit version,
+ * when decompressing mozilla-source-1.3.tar.gz.
+ *
  * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
  * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at
  * the moment.  I have successfully compiled and tested this code with gcc2.96,
@@ -65,33 +74,44 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 {
     struct inflate_state FAR *state;
     struct inffast_ar {
-      void *esp;                  /* esp save */
-      unsigned char FAR *in;      /* local strm->next_in */
-      unsigned char FAR *last;    /* while in < last, enough input available */
-      unsigned char FAR *out;     /* local strm->next_out */
-      unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
-      unsigned char FAR *end;     /* while out < end, enough space available */
-      unsigned wsize;             /* window size or zero if not using window */
-      unsigned write;             /* window write index */
-      unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
-      unsigned long hold;         /* local strm->hold */
-      unsigned bits;              /* local strm->bits */
-      code const FAR *lcode;      /* local strm->lencode */
-      code const FAR *dcode;      /* local strm->distcode */
-      unsigned lmask;             /* mask for first level of length codes */
-      unsigned dmask;             /* mask for first level of distance codes */
-      unsigned len;               /* match length, unused bytes */
-      unsigned dist;              /* match distance */
-      unsigned status;            /* this is set when state changes */
+/* 64   32                               x86  x86_64 */
+/* ar offset                              register */
+/*  0    0 */ void *esp;                /* esp save */
+/*  8    4 */ void *ebp;                /* ebp save */
+/* 16    8 */ unsigned char FAR *in;    /* esi rsi  local strm->next_in */
+/* 24   12 */ unsigned char FAR *last;  /*     r9   while in < last */
+/* 32   16 */ unsigned char FAR *out;   /* edi rdi  local strm->next_out */
+/* 40   20 */ unsigned char FAR *beg;   /*          inflate()'s init next_out */
+/* 48   24 */ unsigned char FAR *end;   /*     r10  while out < end */
+/* 56   28 */ unsigned char FAR *window;/*          size of window, wsize!=0 */
+/* 64   32 */ code const FAR *lcode;    /* ebp rbp  local strm->lencode */
+/* 72   36 */ code const FAR *dcode;    /*     r11  local strm->distcode */
+/* 80   40 */ unsigned long hold;       /* edx rdx  local strm->hold */
+/* 88   44 */ unsigned bits;            /* ebx rbx  local strm->bits */
+/* 92   48 */ unsigned wsize;           /*          window size */
+/* 96   52 */ unsigned write;           /*          window write index */
+/*100   56 */ unsigned lmask;           /*     r12  mask for lcode */
+/*104   60 */ unsigned dmask;           /*     r13  mask for dcode */
+/*108   64 */ unsigned len;             /*     r14  match length */
+/*112   68 */ unsigned dist;            /*     r15  match distance */
+/*116   72 */ unsigned status;          /*          set when state chng*/
     } ar;
 
+#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )
+#define PAD_AVAIL_IN 6
+#define PAD_AVAIL_OUT 258
+#else
+#define PAD_AVAIL_IN 5
+#define PAD_AVAIL_OUT 257
+#endif
+
     /* copy state to local variables */
     state = (struct inflate_state FAR *)strm->state;
     ar.in = strm->next_in;
-    ar.last = ar.in + (strm->avail_in - 5);
+    ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
     ar.out = strm->next_out;
     ar.beg = ar.out - (start - strm->avail_out);
-    ar.end = ar.out + (strm->avail_out - 257);
+    ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
     ar.wsize = state->wsize;
     ar.write = state->write;
     ar.window = state->window;
@@ -105,32 +125,368 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
     /* decode literals and length/distances until end-of-block or not enough
        input data or output space */
 
-    /* align in on 2 byte boundary */
-    if (((unsigned long)(void *)ar.in & 0x1) != 0) {
+    /* align in on 1/2 hold size boundary */
+    while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
         ar.hold += (unsigned long)*ar.in++ << ar.bits;
         ar.bits += 8;
     }
 
-#if defined( __GNUC__ ) || defined( __ICC )
+#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )
+    __asm__ __volatile__ (
+"        leaq    %0, %%rax\n"
+"        movq    %%rbp, 8(%%rax)\n"       /* save regs rbp and rsp */
+"        movq    %%rsp, (%%rax)\n"
+"        movq    %%rax, %%rsp\n"          /* make rsp point to &ar */
+"        movq    16(%%rsp), %%rsi\n"      /* rsi  = in */
+"        movq    32(%%rsp), %%rdi\n"      /* rdi  = out */
+"        movq    24(%%rsp), %%r9\n"       /* r9   = last */
+"        movq    48(%%rsp), %%r10\n"      /* r10  = end */
+"        movq    64(%%rsp), %%rbp\n"      /* rbp  = lcode */
+"        movq    72(%%rsp), %%r11\n"      /* r11  = dcode */
+"        movq    80(%%rsp), %%rdx\n"      /* rdx  = hold */
+"        movl    88(%%rsp), %%ebx\n"      /* ebx  = bits */
+"        movl    100(%%rsp), %%r12d\n"    /* r12d = lmask */
+"        movl    104(%%rsp), %%r13d\n"    /* r13d = dmask */
+                                          /* r14d = len */
+                                          /* r15d = dist */
+"        cld\n"
+"        cmpq    %%rdi, %%r10\n"
+"        je      .L_one_time\n"           /* if only one decode left */
+"        cmpq    %%rsi, %%r9\n"
+"        je      .L_one_time\n"
+"        jmp     .L_do_loop\n"
+
+".L_one_time:\n"
+"        movq    %%r12, %%r8\n"           /* r8 = lmask */
+"        cmpb    $32, %%bl\n"
+"        ja      .L_get_length_code_one_time\n"
+
+"        lodsl\n"                         /* eax = *(uint *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $32, %%bl\n"             /* bits += 32 */
+"        shlq    %%cl, %%rax\n"
+"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
+"        jmp     .L_get_length_code_one_time\n"
+
+".align 32,0x90\n"
+".L_while_test:\n"
+"        cmpq    %%rdi, %%r10\n"
+"        jbe     .L_break_loop\n"
+"        cmpq    %%rsi, %%r9\n"
+"        jbe     .L_break_loop\n"
+
+".L_do_loop:\n"
+"        movq    %%r12, %%r8\n"           /* r8 = lmask */
+"        cmpb    $32, %%bl\n"
+"        ja      .L_get_length_code\n"    /* if (32 < bits) */
+
+"        lodsl\n"                         /* eax = *(uint *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $32, %%bl\n"             /* bits += 32 */
+"        shlq    %%cl, %%rax\n"
+"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
+
+".L_get_length_code:\n"
+"        andq    %%rdx, %%r8\n"            /* r8 &= hold */
+"        movl    (%%rbp,%%r8,4), %%eax\n"  /* eax = lcode[hold & lmask] */
+
+"        movb    %%ah, %%cl\n"            /* cl = this.bits */
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
+
+"        testb   %%al, %%al\n"
+"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
+
+"        movq    %%r12, %%r8\n"            /* r8 = lmask */
+"        shrl    $16, %%eax\n"            /* output this.val char */
+"        stosb\n"
+
+".L_get_length_code_one_time:\n"
+"        andq    %%rdx, %%r8\n"            /* r8 &= hold */
+"        movl    (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */
+
+".L_dolen:\n"
+"        movb    %%ah, %%cl\n"            /* cl = this.bits */
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
+
+"        testb   %%al, %%al\n"
+"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
+
+"        shrl    $16, %%eax\n"            /* output this.val char */
+"        stosb\n"
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_test_for_length_base:\n"
+"        movl    %%eax, %%r14d\n"         /* len = this */
+"        shrl    $16, %%r14d\n"           /* len = this.val */
+"        movb    %%al, %%cl\n"
+
+"        testb   $16, %%al\n"
+"        jz      .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */
+"        andb    $15, %%cl\n"             /* op &= 15 */
+"        jz      .L_decode_distance\n"    /* if (!op) */
+
+".L_add_bits_to_len:\n"
+"        subb    %%cl, %%bl\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        shrq    %%cl, %%rdx\n"
+"        addl    %%eax, %%r14d\n"         /* len += hold & mask[op] */
+
+".L_decode_distance:\n"
+"        movq    %%r13, %%r8\n"           /* r8 = dmask */
+"        cmpb    $32, %%bl\n"
+"        ja      .L_get_distance_code\n"  /* if (32 < bits) */
+
+"        lodsl\n"                         /* eax = *(uint *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $32, %%bl\n"             /* bits += 32 */
+"        shlq    %%cl, %%rax\n"
+"        orq     %%rax, %%rdx\n"          /* hold |= *((uint *)in)++ << bits */
+
+".L_get_distance_code:\n"
+"        andq    %%rdx, %%r8\n"           /* r8 &= hold */
+"        movl    (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */
+
+".L_dodist:\n"
+"        movl    %%eax, %%r15d\n"         /* dist = this */
+"        shrl    $16, %%r15d\n"           /* dist = this.val */
+"        movb    %%ah, %%cl\n"
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrq    %%cl, %%rdx\n"           /* hold >>= this.bits */
+"        movb    %%al, %%cl\n"            /* cl = this.op */
+
+"        testb   $16, %%al\n"             /* if ((op & 16) == 0) */
+"        jz      .L_test_for_second_level_dist\n"
+"        andb    $15, %%cl\n"             /* op &= 15 */
+"        jz      .L_check_dist_one\n"
+
+".L_add_bits_to_dist:\n"
+"        subb    %%cl, %%bl\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"                 /* (1 << op) - 1 */
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        shrq    %%cl, %%rdx\n"
+"        addl    %%eax, %%r15d\n"         /* dist += hold & ((1 << op) - 1) */
+
+".L_check_window:\n"
+"        movq    %%rsi, %%r8\n"           /* save in so from can use it's reg */
+"        movq    %%rdi, %%rax\n"
+"        subq    40(%%rsp), %%rax\n"      /* nbytes = out - beg */
+
+"        cmpl    %%r15d, %%eax\n"
+"        jb      .L_clip_window\n"        /* if (dist > nbytes) 4.2% */
+
+"        movl    %%r14d, %%ecx\n"         /* ecx = len */
+"        movq    %%rdi, %%rsi\n"
+"        subq    %%r15, %%rsi\n"          /* from = out - dist */
+
+"        sarl    %%ecx\n"
+"        jnc     .L_copy_two\n"           /* if len % 2 == 0 */
+
+"        rep     movsw\n"
+"        movb    (%%rsi), %%al\n"
+"        movb    %%al, (%%rdi)\n"
+"        incq    %%rdi\n"
+
+"        movq    %%r8, %%rsi\n"           /* move in back to %rsi, toss from */
+"        jmp     .L_while_test\n"
+
+".L_copy_two:\n"
+"        rep     movsw\n"
+"        movq    %%r8, %%rsi\n"           /* move in back to %rsi, toss from */
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_check_dist_one:\n"
+"        cmpl    $1, %%r15d\n"            /* if dist 1, is a memset */
+"        jne     .L_check_window\n"
+"        cmpq    %%rdi, 40(%%rsp)\n"      /* if out == beg, outside window */
+"        je      .L_check_window\n"
+
+"        movl    %%r14d, %%ecx\n"         /* ecx = len */
+"        movb    -1(%%rdi), %%al\n"
+"        movb    %%al, %%ah\n"
+
+"        sarl    %%ecx\n"
+"        jnc     .L_set_two\n"
+"        movb    %%al, (%%rdi)\n"
+"        incq    %%rdi\n"
+
+".L_set_two:\n"
+"        rep     stosw\n"
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
+".L_test_for_second_level_length:\n"
+"        testb   $64, %%al\n"
+"        jnz     .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */
+
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"         /* eax &= hold */
+"        addl    %%r14d, %%eax\n"        /* eax += len */
+"        movl    (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/
+"        jmp     .L_dolen\n"
+
+".align 32,0x90\n"
+".L_test_for_second_level_dist:\n"
+"        testb   $64, %%al\n"
+"        jnz     .L_invalid_distance_code\n" /* if ((op & 64) != 0) */
+
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"         /* eax &= hold */
+"        addl    %%r15d, %%eax\n"        /* eax += dist */
+"        movl    (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/
+"        jmp     .L_dodist\n"
+
+".align 32,0x90\n"
+".L_clip_window:\n"
+"        movl    %%eax, %%ecx\n"         /* ecx = nbytes */
+"        movl    92(%%rsp), %%eax\n"     /* eax = wsize, prepare for dist cmp */
+"        negl    %%ecx\n"                /* nbytes = -nbytes */
+
+"        cmpl    %%r15d, %%eax\n"
+"        jb      .L_invalid_distance_too_far\n" /* if (dist > wsize) */
+
+"        addl    %%r15d, %%ecx\n"         /* nbytes = dist - nbytes */
+"        cmpl    $0, 96(%%rsp)\n"
+"        jne     .L_wrap_around_window\n" /* if (write != 0) */
+
+"        movq    56(%%rsp), %%rsi\n"     /* from  = window */
+"        subl    %%ecx, %%eax\n"         /* eax  -= nbytes */
+"        addq    %%rax, %%rsi\n"         /* from += wsize - nbytes */
+
+"        movl    %%r14d, %%eax\n"        /* eax = len */
+"        cmpl    %%ecx, %%r14d\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* eax -= nbytes */
+"        rep     movsb\n"
+"        movq    %%rdi, %%rsi\n"
+"        subq    %%r15, %%rsi\n"         /* from = &out[ -dist ] */
+"        jmp     .L_do_copy\n"
+
+".align 32,0x90\n"
+".L_wrap_around_window:\n"
+"        movl    96(%%rsp), %%eax\n"     /* eax = write */
+"        cmpl    %%eax, %%ecx\n"
+"        jbe     .L_contiguous_in_window\n" /* if (write >= nbytes) */
+
+"        movl    92(%%rsp), %%esi\n"     /* from  = wsize */
+"        addq    56(%%rsp), %%rsi\n"     /* from += window */
+"        addq    %%rax, %%rsi\n"         /* from += write */
+"        subq    %%rcx, %%rsi\n"         /* from -= nbytes */
+"        subl    %%eax, %%ecx\n"         /* nbytes -= write */
+
+"        movl    %%r14d, %%eax\n"        /* eax = len */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movq    56(%%rsp), %%rsi\n"     /* from = window */
+"        movl    96(%%rsp), %%ecx\n"     /* nbytes = write */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movq    %%rdi, %%rsi\n"
+"        subq    %%r15, %%rsi\n"         /* from = out - dist */
+"        jmp     .L_do_copy\n"
+
+".align 32,0x90\n"
+".L_contiguous_in_window:\n"
+"        movq    56(%%rsp), %%rsi\n"     /* rsi = window */
+"        addq    %%rax, %%rsi\n"
+"        subq    %%rcx, %%rsi\n"         /* from += write - nbytes */
+
+"        movl    %%r14d, %%eax\n"        /* eax = len */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movq    %%rdi, %%rsi\n"
+"        subq    %%r15, %%rsi\n"         /* from = out - dist */
+"        jmp     .L_do_copy\n"           /* if (nbytes >= len) */
+
+".align 32,0x90\n"
+".L_do_copy:\n"
+"        movl    %%eax, %%ecx\n"         /* ecx = len */
+"        rep     movsb\n"
+
+"        movq    %%r8, %%rsi\n"          /* move in back to %esi, toss from */
+"        jmp     .L_while_test\n"
+
+".L_test_for_end_of_block:\n"
+"        testb   $32, %%al\n"
+"        jz      .L_invalid_literal_length_code\n"
+"        movl    $1, 116(%%rsp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_literal_length_code:\n"
+"        movl    $2, 116(%%rsp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_distance_code:\n"
+"        movl    $3, 116(%%rsp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_distance_too_far:\n"
+"        movl    $4, 116(%%rsp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_break_loop:\n"
+"        movl    $0, 116(%%rsp)\n"
+
+".L_break_loop_with_status:\n"
+/* put in, out, bits, and hold back into ar and pop esp */
+"        movq    %%rsi, 16(%%rsp)\n"     /* in */
+"        movq    %%rdi, 32(%%rsp)\n"     /* out */
+"        movl    %%ebx, 88(%%rsp)\n"     /* bits */
+"        movq    %%rdx, 80(%%rsp)\n"     /* hold */
+"        movq    (%%rsp), %%rax\n"       /* restore rbp and rsp */
+"        movq    8(%%rsp), %%rbp\n"
+"        movq    %%rax, %%rsp\n"
+          :
+          : "m" (ar)
+          : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
+            "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+    );
+#elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 )
     __asm__ __volatile__ (
 "        leal    %0, %%eax\n"
-"        pushf\n"
-"        pushl   %%ebp\n"
-"        movl    %%esp, (%%eax)\n"
+"        movl    %%esp, (%%eax)\n"        /* save esp, ebp */
+"        movl    %%ebp, 4(%%eax)\n"
 "        movl    %%eax, %%esp\n"
-"        movl    4(%%esp), %%esi\n"       /* esi = in */
-"        movl    12(%%esp), %%edi\n"      /* edi = out */
-"        movl    36(%%esp), %%edx\n"      /* edx = hold */
-"        movl    40(%%esp), %%ebx\n"      /* ebx = bits */
-"        movl    44(%%esp), %%ebp\n"      /* ebp = lcode */
+"        movl    8(%%esp), %%esi\n"       /* esi = in */
+"        movl    16(%%esp), %%edi\n"      /* edi = out */
+"        movl    40(%%esp), %%edx\n"      /* edx = hold */
+"        movl    44(%%esp), %%ebx\n"      /* ebx = bits */
+"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
 
 "        cld\n"
 "        jmp     .L_do_loop\n"
 
+".align 32,0x90\n"
 ".L_while_test:\n"
-"        cmpl    %%edi, 20(%%esp)\n"
+"        cmpl    %%edi, 24(%%esp)\n"      /* out < end */
 "        jbe     .L_break_loop\n"
-"        cmpl    %%esi, 8(%%esp)\n"
+"        cmpl    %%esi, 12(%%esp)\n"      /* in < last */
 "        jbe     .L_break_loop\n"
 
 ".L_do_loop:\n"
@@ -145,7 +501,7 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 "        orl     %%eax, %%edx\n"        /* hold |= *((ushort *)in)++ << bits */
 
 ".L_get_length_code:\n"
-"        movl    52(%%esp), %%eax\n"      /* eax = lmask */
+"        movl    56(%%esp), %%eax\n"      /* eax = lmask */
 "        andl    %%edx, %%eax\n"          /* eax &= hold */
 "        movl    (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */
 
@@ -161,10 +517,11 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 "        stosb\n"
 "        jmp     .L_while_test\n"
 
+".align 32,0x90\n"
 ".L_test_for_length_base:\n"
 "        movl    %%eax, %%ecx\n"          /* len = this */
 "        shrl    $16, %%ecx\n"            /* len = this.val */
-"        movl    %%ecx, 60(%%esp)\n"      /* len = this */
+"        movl    %%ecx, 64(%%esp)\n"      /* save len */
 "        movb    %%al, %%cl\n"
 
 "        testb   $16, %%al\n"
@@ -184,13 +541,14 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 "        movb    %%ch, %%cl\n"            /* move op back to ecx */
 
 ".L_add_bits_to_len:\n"
-"        movl    $1, %%eax\n"
+"        subb    %%cl, %%bl\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
 "        shll    %%cl, %%eax\n"
 "        decl    %%eax\n"
-"        subb    %%cl, %%bl\n"
 "        andl    %%edx, %%eax\n"          /* eax &= hold */
 "        shrl    %%cl, %%edx\n"
-"        addl    %%eax, 60(%%esp)\n"      /* len += hold & mask[op] */
+"        addl    %%eax, 64(%%esp)\n"      /* len += hold & mask[op] */
 
 ".L_decode_distance:\n"
 "        cmpb    $15, %%bl\n"
@@ -204,8 +562,8 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 "        orl     %%eax, %%edx\n"         /* hold |= *((ushort *)in)++ << bits */
 
 ".L_get_distance_code:\n"
-"        movl    56(%%esp), %%eax\n"      /* eax = dmask */
-"        movl    48(%%esp), %%ecx\n"      /* ecx = dcode */
+"        movl    60(%%esp), %%eax\n"      /* eax = dmask */
+"        movl    36(%%esp), %%ecx\n"      /* ecx = dcode */
 "        andl    %%edx, %%eax\n"          /* eax &= hold */
 "        movl    (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */
 
@@ -234,223 +592,228 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
 "        movb    %%ch, %%cl\n"            /* move op back to ecx */
 
 ".L_add_bits_to_dist:\n"
-"        movl    $1, %%eax\n"
+"        subb    %%cl, %%bl\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
 "        shll    %%cl, %%eax\n"
 "        decl    %%eax\n"                 /* (1 << op) - 1 */
-"        subb    %%cl, %%bl\n"
 "        andl    %%edx, %%eax\n"          /* eax &= hold */
 "        shrl    %%cl, %%edx\n"
 "        addl    %%eax, %%ebp\n"          /* dist += hold & ((1 << op) - 1) */
 
 ".L_check_window:\n"
-"        movl    %%esi, 4(%%esp)\n"       /* save in so from can use it's reg */
+"        movl    %%esi, 8(%%esp)\n"       /* save in so from can use it's reg */
 "        movl    %%edi, %%eax\n"
-"        subl    16(%%esp), %%eax\n"      /* nbytes = out - beg */
+"        subl    20(%%esp), %%eax\n"      /* nbytes = out - beg */
 
 "        cmpl    %%ebp, %%eax\n"
 "        jb      .L_clip_window\n"        /* if (dist > nbytes) 4.2% */
 
-"        movl    60(%%esp), %%ecx\n"
+"        movl    64(%%esp), %%ecx\n"      /* ecx = len */
 "        movl    %%edi, %%esi\n"
 "        subl    %%ebp, %%esi\n"          /* from = out - dist */
 
-"        subl    $3, %%ecx\n"             /* copy from to out */
+"        sarl    %%ecx\n"
+"        jnc     .L_copy_two\n"           /* if len % 2 == 0 */
+
+"        rep     movsw\n"
 "        movb    (%%esi), %%al\n"
 "        movb    %%al, (%%edi)\n"
-"        movb    1(%%esi), %%al\n"
-"        movb    2(%%esi), %%ah\n"
-"        addl    $3, %%esi\n"
-"        movb    %%al, 1(%%edi)\n"
-"        movb    %%ah, 2(%%edi)\n"
-"        addl    $3, %%edi\n"
-"        rep     movsb\n"
+"        incl    %%edi\n"
 
-"        movl    4(%%esp), %%esi\n"      /* move in back to %esi, toss from */
-"        movl    44(%%esp), %%ebp\n"     /* ebp = lcode */
+"        movl    8(%%esp), %%esi\n"       /* move in back to %esi, toss from */
+"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
 "        jmp     .L_while_test\n"
 
+".L_copy_two:\n"
+"        rep     movsw\n"
+"        movl    8(%%esp), %%esi\n"       /* move in back to %esi, toss from */
+"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
+"        jmp     .L_while_test\n"
+
+".align 32,0x90\n"
 ".L_check_dist_one:\n"
 "        cmpl    $1, %%ebp\n"            /* if dist 1, is a memset */
 "        jne     .L_check_window\n"
-"        cmpl    %%edi, 16(%%esp)\n"
-"        je      .L_check_window\n"
+"        cmpl    %%edi, 20(%%esp)\n"
+"        je      .L_check_window\n"      /* out == beg, if outside window */
+
+"        movl    64(%%esp), %%ecx\n"      /* ecx = len */
+"        movb    -1(%%edi), %%al\n"
+"        movb    %%al, %%ah\n"
+
+"        sarl    %%ecx\n"
+"        jnc     .L_set_two\n"
+"        movb    %%al, (%%edi)\n"
+"        incl    %%edi\n"
 
-"        decl    %%edi\n"
-"        movl    60(%%esp), %%ecx\n"
-"        movb    (%%edi), %%al\n"
-"        subl    $3, %%ecx\n"
-
-"        movb    %%al, 1(%%edi)\n"       /* memset out with from[-1] */
-"        movb    %%al, 2(%%edi)\n"
-"        movb    %%al, 3(%%edi)\n"
-"        addl    $4, %%edi\n"
-"        rep     stosb\n"
-"        movl    44(%%esp), %%ebp\n"      /* ebp = lcode */
+".L_set_two:\n"
+"        rep     stosw\n"
+"        movl    32(%%esp), %%ebp\n"      /* ebp = lcode */
 "        jmp     .L_while_test\n"
 
+".align 32,0x90\n"
 ".L_test_for_second_level_length:\n"
 "        testb   $64, %%al\n"
 "        jnz     .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */
 
-"        movl    $1, %%eax\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
 "        shll    %%cl, %%eax\n"
 "        decl    %%eax\n"
 "        andl    %%edx, %%eax\n"         /* eax &= hold */
-"        addl    60(%%esp), %%eax\n"     /* eax += this.val */
+"        addl    64(%%esp), %%eax\n"     /* eax += len */
 "        movl    (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/
 "        jmp     .L_dolen\n"
 
+".align 32,0x90\n"
 ".L_test_for_second_level_dist:\n"
 "        testb   $64, %%al\n"
 "        jnz     .L_invalid_distance_code\n" /* if ((op & 64) != 0) */
 
-"        movl    $1, %%eax\n"
+"        xorl    %%eax, %%eax\n"
+"        incl    %%eax\n"
 "        shll    %%cl, %%eax\n"
 "        decl    %%eax\n"
 "        andl    %%edx, %%eax\n"         /* eax &= hold */
-"        addl    %%ebp, %%eax\n"         /* eax += this.val */
-"        movl    48(%%esp), %%ecx\n"     /* ecx = dcode */
+"        addl    %%ebp, %%eax\n"         /* eax += dist */
+"        movl    36(%%esp), %%ecx\n"     /* ecx = dcode */
 "        movl    (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/
 "        jmp     .L_dodist\n"
 
+".align 32,0x90\n"
 ".L_clip_window:\n"
 "        movl    %%eax, %%ecx\n"
-"        movl    24(%%esp), %%eax\n"     /* prepare for dist compare */
+"        movl    48(%%esp), %%eax\n"     /* eax = wsize */
 "        negl    %%ecx\n"                /* nbytes = -nbytes */
-"        movl    32(%%esp), %%esi\n"     /* from = window */
+"        movl    28(%%esp), %%esi\n"     /* from = window */
 
 "        cmpl    %%ebp, %%eax\n"
 "        jb      .L_invalid_distance_too_far\n" /* if (dist > wsize) */
 
 "        addl    %%ebp, %%ecx\n"         /* nbytes = dist - nbytes */
-"        cmpl    $0, 28(%%esp)\n"
+"        cmpl    $0, 52(%%esp)\n"
 "        jne     .L_wrap_around_window\n" /* if (write != 0) */
 
 "        subl    %%ecx, %%eax\n"
 "        addl    %%eax, %%esi\n"         /* from += wsize - nbytes */
 
-"        movl    60(%%esp), %%eax\n"
-"        cmpl    %%ecx, %%eax\n"
-"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
-
-"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
-"        rep     movsb\n"
-"        movl    %%edi, %%esi\n"
-"        subl    %%ebp, %%esi\n"         /* from = out - dist */
-"        jmp     .L_do_copy1\n"
-
+"        movl    64(%%esp), %%eax\n"     /* eax = len */
 "        cmpl    %%ecx, %%eax\n"
-"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
 
 "        subl    %%ecx, %%eax\n"         /* len -= nbytes */
 "        rep     movsb\n"
 "        movl    %%edi, %%esi\n"
 "        subl    %%ebp, %%esi\n"         /* from = out - dist */
-"        jmp     .L_do_copy1\n"
+"        jmp     .L_do_copy\n"
 
+".align 32,0x90\n"
 ".L_wrap_around_window:\n"
-"        movl    28(%%esp), %%eax\n"
+"        movl    52(%%esp), %%eax\n"     /* eax = write */
 "        cmpl    %%eax, %%ecx\n"
 "        jbe     .L_contiguous_in_window\n" /* if (write >= nbytes) */
 
-"        addl    24(%%esp), %%esi\n"
-"        addl    %%eax, %%esi\n"
-"        subl    %%ecx, %%esi\n"         /* from += wsize + write - nbytes */
+"        addl    48(%%esp), %%esi\n"     /* from += wsize */
+"        addl    %%eax, %%esi\n"         /* from += write */
+"        subl    %%ecx, %%esi\n"         /* from -= nbytes */
 "        subl    %%eax, %%ecx\n"         /* nbytes -= write */
 
-"        movl    60(%%esp), %%eax\n"
+"        movl    64(%%esp), %%eax\n"     /* eax = len */
 "        cmpl    %%ecx, %%eax\n"
-"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
 
 "        subl    %%ecx, %%eax\n"         /* len -= nbytes */
 "        rep     movsb\n"
-"        movl    32(%%esp), %%esi\n"     /* from = window */
-"        movl    28(%%esp), %%ecx\n"     /* nbytes = write */
+"        movl    28(%%esp), %%esi\n"     /* from = window */
+"        movl    52(%%esp), %%ecx\n"     /* nbytes = write */
 "        cmpl    %%ecx, %%eax\n"
-"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
 
 "        subl    %%ecx, %%eax\n"         /* len -= nbytes */
 "        rep     movsb\n"
 "        movl    %%edi, %%esi\n"
 "        subl    %%ebp, %%esi\n"         /* from = out - dist */
-"        jmp     .L_do_copy1\n"
+"        jmp     .L_do_copy\n"
 
+".align 32,0x90\n"
 ".L_contiguous_in_window:\n"
 "        addl    %%eax, %%esi\n"
 "        subl    %%ecx, %%esi\n"         /* from += write - nbytes */
 
-"        movl    60(%%esp), %%eax\n"
+"        movl    64(%%esp), %%eax\n"     /* eax = len */
 "        cmpl    %%ecx, %%eax\n"
-"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+"        jbe     .L_do_copy\n"           /* if (nbytes >= len) */
 
 "        subl    %%ecx, %%eax\n"         /* len -= nbytes */
 "        rep     movsb\n"
 "        movl    %%edi, %%esi\n"
 "        subl    %%ebp, %%esi\n"         /* from = out - dist */
+"        jmp     .L_do_copy\n"           /* if (nbytes >= len) */
 
-".L_do_copy1:\n"
+".align 32,0x90\n"
+".L_do_copy:\n"
 "        movl    %%eax, %%ecx\n"
 "        rep     movsb\n"
 
-"        movl    4(%%esp), %%esi\n"      /* move in back to %esi, toss from */
-"        movl    44(%%esp), %%ebp\n"     /* ebp = lcode */
+"        movl    8(%%esp), %%esi\n"      /* move in back to %esi, toss from */
+"        movl    32(%%esp), %%ebp\n"     /* ebp = lcode */
 "        jmp     .L_while_test\n"
 
 ".L_test_for_end_of_block:\n"
 "        testb   $32, %%al\n"
 "        jz      .L_invalid_literal_length_code\n"
-"        movl    $1, 68(%%esp)\n"
+"        movl    $1, 72(%%esp)\n"
 "        jmp     .L_break_loop_with_status\n"
 
 ".L_invalid_literal_length_code:\n"
-"        movl    $2, 68(%%esp)\n"
+"        movl    $2, 72(%%esp)\n"
 "        jmp     .L_break_loop_with_status\n"
 
 ".L_invalid_distance_code:\n"
-"        movl    $3, 68(%%esp)\n"
+"        movl    $3, 72(%%esp)\n"
 "        jmp     .L_break_loop_with_status\n"
 
 ".L_invalid_distance_too_far:\n"
-"        movl    4(%%esp), %%esi\n"
-"        movl    $4, 68(%%esp)\n"
+"        movl    8(%%esp), %%esi\n"
+"        movl    $4, 72(%%esp)\n"
 "        jmp     .L_break_loop_with_status\n"
 
 ".L_break_loop:\n"
-"        movl    $0, 68(%%esp)\n"
+"        movl    $0, 72(%%esp)\n"
 
 ".L_break_loop_with_status:\n"
 /* put in, out, bits, and hold back into ar and pop esp */
-"        movl    %%esi, 4(%%esp)\n"
-"        movl    %%edi, 12(%%esp)\n"
-"        movl    %%ebx, 40(%%esp)\n"
-"        movl    %%edx, 36(%%esp)\n"
+"        movl    %%esi, 8(%%esp)\n"      /* save in */
+"        movl    %%edi, 16(%%esp)\n"     /* save out */
+"        movl    %%ebx, 44(%%esp)\n"     /* save bits */
+"        movl    %%edx, 40(%%esp)\n"     /* save hold */
+"        movl    4(%%esp), %%ebp\n"      /* restore esp, ebp */
 "        movl    (%%esp), %%esp\n"
-"        popl    %%ebp\n"
-"        popf\n"
           :
           : "m" (ar)
           : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"
     );
-#elif defined( _MSC_VER )
+#elif defined( _MSC_VER ) && ! defined( _M_AMD64 )
     __asm {
        lea     eax, ar
-       pushfd
-       push    ebp
-       mov     [eax], esp
+       mov     [eax], esp         /* save esp, ebp */
+       mov     [eax+4], ebp
        mov     esp, eax
-       mov     esi, [esp+4]       /* esi = in */
-       mov     edi, [esp+12]      /* edi = out */
-       mov     edx, [esp+36]      /* edx = hold */
-       mov     ebx, [esp+40]      /* ebx = bits */
-       mov     ebp, [esp+44]      /* ebp = lcode */
+       mov     esi, [esp+8]       /* esi = in */
+       mov     edi, [esp+16]      /* edi = out */
+       mov     edx, [esp+40]      /* edx = hold */
+       mov     ebx, [esp+44]      /* ebx = bits */
+       mov     ebp, [esp+32]      /* ebp = lcode */
 
        cld
        jmp     L_do_loop
 
+ALIGN 4
 L_while_test:
-       cmp     [esp+20], edi
+       cmp     [esp+24], edi
        jbe     L_break_loop
-       cmp     [esp+8], esi
+       cmp     [esp+12], esi
        jbe     L_break_loop
 
 L_do_loop:
@@ -465,7 +828,7 @@ L_do_loop:
        or      edx, eax        /* hold |= *((ushort *)in)++ << bits */
 
 L_get_length_code:
-       mov     eax, [esp+52]      /* eax = lmask */
+       mov     eax, [esp+56]      /* eax = lmask */
        and     eax, edx          /* eax &= hold */
        mov     eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */
 
@@ -481,10 +844,11 @@ L_dolen:
        stosb
        jmp     L_while_test
 
+ALIGN 4
 L_test_for_length_base:
        mov     ecx, eax          /* len = this */
        shr     ecx, 16            /* len = this.val */
-       mov     [esp+60], ecx      /* len = this */
+       mov     [esp+64], ecx      /* save len */
        mov     cl, al
 
        test    al, 16
@@ -504,13 +868,14 @@ L_test_for_length_base:
        mov     cl, ch            /* move op back to ecx */
 
 L_add_bits_to_len:
-       mov     eax, 1
+       sub     bl, cl
+       xor     eax, eax
+       inc     eax
        shl     eax, cl
        dec     eax
-       sub     bl, cl
        and     eax, edx          /* eax &= hold */
        shr     edx, cl
-       add     [esp+60], eax      /* len += hold & mask[op] */
+       add     [esp+64], eax      /* len += hold & mask[op] */
 
 L_decode_distance:
        cmp     bl, 15
@@ -524,8 +889,8 @@ L_decode_distance:
        or      edx, eax         /* hold |= *((ushort *)in)++ << bits */
 
 L_get_distance_code:
-       mov     eax, [esp+56]      /* eax = dmask */
-       mov     ecx, [esp+48]      /* ecx = dcode */
+       mov     eax, [esp+60]      /* eax = dmask */
+       mov     ecx, [esp+36]      /* ecx = dcode */
        and     eax, edx          /* eax &= hold */
        mov     eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */
 
@@ -554,200 +919,207 @@ L_dodist:
        mov     cl, ch            /* move op back to ecx */
 
 L_add_bits_to_dist:
-       mov     eax, 1
+       sub     bl, cl
+       xor     eax, eax
+       inc     eax
        shl     eax, cl
        dec     eax                 /* (1 << op) - 1 */
-       sub     bl, cl
        and     eax, edx          /* eax &= hold */
        shr     edx, cl
        add     ebp, eax          /* dist += hold & ((1 << op) - 1) */
 
 L_check_window:
-       mov     [esp+4], esi       /* save in so from can use it's reg */
+       mov     [esp+8], esi       /* save in so from can use it's reg */
        mov     eax, edi
-       sub     eax, [esp+16]      /* nbytes = out - beg */
+       sub     eax, [esp+20]      /* nbytes = out - beg */
 
        cmp     eax, ebp
        jb      L_clip_window        /* if (dist > nbytes) 4.2% */
 
-       mov     ecx, [esp+60]
+       mov     ecx, [esp+64]      /* ecx = len */
        mov     esi, edi
        sub     esi, ebp          /* from = out - dist */
 
-       sub     ecx, 3             /* copy from to out */
+       sar     ecx, 1
+       jnc     L_copy_two
+
+       rep     movsw
        mov     al, [esi]
        mov     [edi], al
-       mov     al, [esi+1]
-       mov     ah, [esi+2]
-       add     esi, 3
-       mov     [edi+1], al
-       mov     [edi+2], ah
-       add     edi, 3
-       rep     movsb
+       inc     edi
+
+       mov     esi, [esp+8]      /* move in back to %esi, toss from */
+       mov     ebp, [esp+32]     /* ebp = lcode */
+       jmp     L_while_test
 
-       mov     esi, [esp+4]      /* move in back to %esi, toss from */
-       mov     ebp, [esp+44]     /* ebp = lcode */
+L_copy_two:
+       rep     movsw
+       mov     esi, [esp+8]      /* move in back to %esi, toss from */
+       mov     ebp, [esp+32]     /* ebp = lcode */
        jmp     L_while_test
 
+ALIGN 4
 L_check_dist_one:
        cmp     ebp, 1            /* if dist 1, is a memset */
        jne     L_check_window
-       cmp     [esp+16], edi
-       je      L_check_window
-
-       dec     edi
-       mov     ecx, [esp+60]
-       mov     al, [edi]
-       sub     ecx, 3
-
-       mov     [edi+1], al       /* memset out with from[-1] */
-       mov     [edi+2], al
-       mov     [edi+3], al
-       add     edi, 4
-       rep     stosb
-       mov     ebp, [esp+44]      /* ebp = lcode */
+       cmp     [esp+20], edi
+       je      L_check_window    /* out == beg, if outside window */
+
+       mov     ecx, [esp+64]     /* ecx = len */
+       mov     al, [edi-1]
+       mov     ah, al
+
+       sar     ecx, 1
+       jnc     L_set_two
+       mov     [edi], al         /* memset out with from[-1] */
+       inc     edi
+
+L_set_two:
+       rep     stosw
+       mov     ebp, [esp+32]     /* ebp = lcode */
        jmp     L_while_test
 
+ALIGN 4
 L_test_for_second_level_length:
        test    al, 64
        jnz     L_test_for_end_of_block /* if ((op & 64) != 0) */
 
-       mov     eax, 1
+       xor     eax, eax
+       inc     eax
        shl     eax, cl
        dec     eax
        and     eax, edx         /* eax &= hold */
-       add     eax, [esp+60]     /* eax += this.val */
+       add     eax, [esp+64]     /* eax += len */
        mov     eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/
        jmp     L_dolen
 
+ALIGN 4
 L_test_for_second_level_dist:
        test    al, 64
        jnz     L_invalid_distance_code /* if ((op & 64) != 0) */
 
-       mov     eax, 1
+       xor     eax, eax
+       inc     eax
        shl     eax, cl
        dec     eax
        and     eax, edx         /* eax &= hold */
-       add     eax, ebp         /* eax += this.val */
-       mov     ecx, [esp+48]     /* ecx = dcode */
+       add     eax, ebp         /* eax += dist */
+       mov     ecx, [esp+36]     /* ecx = dcode */
        mov     eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/
        jmp     L_dodist
 
+ALIGN 4
 L_clip_window:
        mov     ecx, eax
-       mov     eax, [esp+24]     /* prepare for dist compare */
+       mov     eax, [esp+48]     /* eax = wsize */
        neg     ecx                /* nbytes = -nbytes */
-       mov     esi, [esp+32]     /* from = window */
+       mov     esi, [esp+28]     /* from = window */
 
        cmp     eax, ebp
        jb      L_invalid_distance_too_far /* if (dist > wsize) */
 
        add     ecx, ebp         /* nbytes = dist - nbytes */
-       cmp     dword ptr [esp+28], 0
+       cmp     dword ptr [esp+52], 0
        jne     L_wrap_around_window /* if (write != 0) */
 
        sub     eax, ecx
        add     esi, eax         /* from += wsize - nbytes */
 
-       mov     eax, [esp+60]
-       cmp     eax, ecx
-       jbe     L_do_copy1          /* if (nbytes >= len) */
-
-       sub     eax, ecx         /* len -= nbytes */
-       rep     movsb
-       mov     esi, edi
-       sub     esi, ebp         /* from = out - dist */
-       jmp     L_do_copy1
-
+       mov     eax, [esp+64]    /* eax = len */
        cmp     eax, ecx
-       jbe     L_do_copy1          /* if (nbytes >= len) */
+       jbe     L_do_copy          /* if (nbytes >= len) */
 
        sub     eax, ecx         /* len -= nbytes */
        rep     movsb
        mov     esi, edi
        sub     esi, ebp         /* from = out - dist */
-       jmp     L_do_copy1
+       jmp     L_do_copy
 
+ALIGN 4
 L_wrap_around_window:
-       mov     eax, [esp+28]
+       mov     eax, [esp+52]    /* eax = write */
        cmp     ecx, eax
        jbe     L_contiguous_in_window /* if (write >= nbytes) */
 
-       add     esi, [esp+24]
-       add     esi, eax
-       sub     esi, ecx         /* from += wsize + write - nbytes */
+       add     esi, [esp+48]    /* from += wsize */
+       add     esi, eax         /* from += write */
+       sub     esi, ecx         /* from -= nbytes */
        sub     ecx, eax         /* nbytes -= write */
 
-       mov     eax, [esp+60]
+       mov     eax, [esp+64]    /* eax = len */
        cmp     eax, ecx
-       jbe     L_do_copy1          /* if (nbytes >= len) */
+       jbe     L_do_copy          /* if (nbytes >= len) */
 
        sub     eax, ecx         /* len -= nbytes */
        rep     movsb
-       mov     esi, [esp+32]     /* from = window */
-       mov     ecx, [esp+28]     /* nbytes = write */
+       mov     esi, [esp+28]     /* from = window */
+       mov     ecx, [esp+52]     /* nbytes = write */
        cmp     eax, ecx
-       jbe     L_do_copy1          /* if (nbytes >= len) */
+       jbe     L_do_copy          /* if (nbytes >= len) */
 
        sub     eax, ecx         /* len -= nbytes */
        rep     movsb
        mov     esi, edi
        sub     esi, ebp         /* from = out - dist */
-       jmp     L_do_copy1
+       jmp     L_do_copy
 
+ALIGN 4
 L_contiguous_in_window:
        add     esi, eax
        sub     esi, ecx         /* from += write - nbytes */
 
-       mov     eax, [esp+60]
+       mov     eax, [esp+64]    /* eax = len */
        cmp     eax, ecx
-       jbe     L_do_copy1          /* if (nbytes >= len) */
+       jbe     L_do_copy          /* if (nbytes >= len) */
 
        sub     eax, ecx         /* len -= nbytes */
        rep     movsb
        mov     esi, edi
        sub     esi, ebp         /* from = out - dist */
+       jmp     L_do_copy
 
-L_do_copy1:
+ALIGN 4
+L_do_copy:
        mov     ecx, eax
        rep     movsb
 
-       mov     esi, [esp+4]      /* move in back to %esi, toss from */
-       mov     ebp, [esp+44]     /* ebp = lcode */
+       mov     esi, [esp+8]      /* move in back to %esi, toss from */
+       mov     ebp, [esp+32]     /* ebp = lcode */
        jmp     L_while_test
 
 L_test_for_end_of_block:
        test    al, 32
        jz      L_invalid_literal_length_code
-       mov     dword ptr [esp+68], 1
+       mov     dword ptr [esp+72], 1
        jmp     L_break_loop_with_status
 
 L_invalid_literal_length_code:
-       mov     dword ptr [esp+68], 2
+       mov     dword ptr [esp+72], 2
        jmp     L_break_loop_with_status
 
 L_invalid_distance_code:
-       mov     dword ptr [esp+68], 3
+       mov     dword ptr [esp+72], 3
        jmp     L_break_loop_with_status
 
 L_invalid_distance_too_far:
        mov     esi, [esp+4]
-       mov     dword ptr [esp+68], 4
+       mov     dword ptr [esp+72], 4
        jmp     L_break_loop_with_status
 
 L_break_loop:
-       mov     dword ptr [esp+68], 0
+       mov     dword ptr [esp+72], 0
 
 L_break_loop_with_status:
 /* put in, out, bits, and hold back into ar and pop esp */
-       mov     [esp+4], esi
-       mov     [esp+12], edi
-       mov     [esp+40], ebx
-       mov     [esp+36], edx
+       mov     [esp+8], esi     /* save in */
+       mov     [esp+16], edi    /* save out */
+       mov     [esp+44], ebx    /* save bits */
+       mov     [esp+40], edx    /* save hold */
+       mov     ebp, [esp+4]     /* restore esp, ebp */
        mov     esp, [esp]
-       pop     ebp
-       popfd
     }
+#else
+#error "x86 architecture not defined"
 #endif
 
     if (ar.status > 1) {
@@ -772,10 +1144,12 @@ L_break_loop_with_status:
     /* update state and return */
     strm->next_in = ar.in;
     strm->next_out = ar.out;
-    strm->avail_in = (unsigned)(ar.in < ar.last ? 5 + (ar.last - ar.in) :
-                                                  5 - (ar.in - ar.last));
-    strm->avail_out = (unsigned)(ar.out < ar.end ? 257 + (ar.end - ar.out) :
-                                                   257 - (ar.out - ar.end));
+    strm->avail_in = (unsigned)(ar.in < ar.last ?
+                                PAD_AVAIL_IN + (ar.last - ar.in) :
+                                PAD_AVAIL_IN - (ar.in - ar.last));
+    strm->avail_out = (unsigned)(ar.out < ar.end ?
+                                 PAD_AVAIL_OUT + (ar.end - ar.out) :
+                                 PAD_AVAIL_OUT - (ar.out - ar.end));
     state->hold = ar.hold;
     state->bits = ar.bits;
     return;
index f9bffd5..2245a29 100644 (file)
 /*
  * typedef enum inflate_mode consts, in inflate.h
  */
-#ifndef NO_GUNZIP
-#define GUNZIP
-#endif
-
-#ifdef GUNZIP
 #define INFLATE_MODE_TYPE 11  /* state->mode flags enum-ed in inflate.h */
 #define INFLATE_MODE_BAD  26
-#else
-#define INFLATE_MODE_TYPE 3
-#define INFLATE_MODE_BAD  17
-#endif
 
 
 #if ! defined( USE_MMX ) && ! defined( NO_MMX )
index 2287804..4b03a71 100644 (file)
-
-; match.asm -- Pentium-Pro optimized version of longest_match()
-;
-; Updated for zlib 1.1.3 and converted to MASM 6.1x
-; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>
-;                    and Chuck Walbourn <chuckw@kinesoft.com>
-; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>
-;
-; This is free software; you can redistribute it and/or modify it
-; under the terms of the GNU General Public License.
-
-; Based on match.S
-; Written for zlib 1.1.2
-; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
-
-       .686P
-       .MODEL  FLAT
-
-;===========================================================================
-; EQUATES
-;===========================================================================
-
-MAX_MATCH      EQU 258
-MIN_MATCH      EQU 3
-MIN_LOOKAHEAD  EQU (MAX_MATCH + MIN_MATCH + 1)
-MAX_MATCH_8    EQU ((MAX_MATCH + 7) AND (NOT 7))
-
-;===========================================================================
-; STRUCTURES
-;===========================================================================
-
-; This STRUCT assumes a 4-byte alignment
-
-DEFLATE_STATE  STRUCT
-ds_strm                        dd ?
-ds_status              dd ?
-ds_pending_buf         dd ?
-ds_pending_buf_size    dd ?
-ds_pending_out         dd ?
-ds_pending             dd ?
-ds_wrap                        dd ?
-ds_data_type           db ?
-ds_method              db ?
-                       db ?    ; padding
-                       db ?    ; padding
-ds_last_flush          dd ?
-ds_w_size              dd ?    ; used
-ds_w_bits              dd ?
-ds_w_mask              dd ?    ; used
-ds_window              dd ?    ; used
-ds_window_size         dd ?
-ds_prev                        dd ?    ; used
-ds_head                        dd ?
-ds_ins_h               dd ?
-ds_hash_size           dd ?
-ds_hash_bits           dd ?
-ds_hash_mask           dd ?
-ds_hash_shift          dd ?
-ds_block_start         dd ?
-ds_match_length                dd ?    ; used
-ds_prev_match          dd ?    ; used
-ds_match_available     dd ?
-ds_strstart            dd ?    ; used
-ds_match_start         dd ?    ; used
-ds_lookahead           dd ?    ; used
-ds_prev_length         dd ?    ; used
-ds_max_chain_length    dd ?    ; used
-ds_max_laxy_match      dd ?
-ds_level               dd ?
-ds_strategy            dd ?
-ds_good_match          dd ?    ; used
-ds_nice_match          dd ?    ; used
-
-; Don't need anymore of the struct for match
-DEFLATE_STATE  ENDS
-
-;===========================================================================
-; CODE
-;===========================================================================
-_TEXT  SEGMENT
-
-;---------------------------------------------------------------------------
-; match_init
-;---------------------------------------------------------------------------
-       ALIGN   4
-PUBLIC _match_init
-_match_init    PROC
-       ; no initialization needed
-       ret
-_match_init    ENDP
-
-;---------------------------------------------------------------------------
-; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
-;---------------------------------------------------------------------------
-       ALIGN   4
-
-PUBLIC _longest_match
-_longest_match PROC
-
-; Since this code uses EBP for a scratch register, the stack frame must
-; be manually constructed and referenced relative to the ESP register.
-
-; Stack image
-; Variables
-chainlenwmask  =  0    ; high word: current chain len
-                       ; low word: s->wmask
-window         =  4    ; local copy of s->window
-windowbestlen  =  8    ; s->window + bestlen
-scanend                = 12    ; last two bytes of string
-scanstart      = 16    ; first two bytes of string
-scanalign      = 20    ; dword-misalignment of string
-nicematch      = 24    ; a good enough match size
-bestlen                = 28    ; size of best match so far
-scan           = 32    ; ptr to string wanting match
-varsize                = 36    ; number of bytes (also offset to last saved register)
-
-; Saved Registers (actually pushed into place)
-ebx_save       = 36
-edi_save       = 40
-esi_save       = 44
-ebp_save       = 48
-
-; Parameters
-retaddr                = 52
-deflatestate   = 56
-curmatch       = 60
-
-; Save registers that the compiler may be using
-       push    ebp
-       push    edi
-       push    esi
-       push    ebx
-
-; Allocate local variable space
-       sub     esp,varsize
-
-; Retrieve the function arguments. ecx will hold cur_match
-; throughout the entire function. edx will hold the pointer to the
-; deflate_state structure during the function's setup (before
-; entering the main loop).
-
-       mov     edx, [esp+deflatestate]
-ASSUME edx:PTR DEFLATE_STATE
-
-       mov     ecx, [esp+curmatch]
-
-; uInt wmask = s->w_mask;
-; unsigned chain_length = s->max_chain_length;
-; if (s->prev_length >= s->good_match) {
-;     chain_length >>= 2;
-; }
-
-       mov     eax, [edx].ds_prev_length
-       mov     ebx, [edx].ds_good_match
-       cmp     eax, ebx
-       mov     eax, [edx].ds_w_mask
-       mov     ebx, [edx].ds_max_chain_length
-       jl      SHORT LastMatchGood
-       shr     ebx, 2
-LastMatchGood:
-
-; chainlen is decremented once beforehand so that the function can
-; use the sign flag instead of the zero flag for the exit test.
-; It is then shifted into the high word, to make room for the wmask
-; value, which it will always accompany.
-
-       dec     ebx
-       shl     ebx, 16
-       or      ebx, eax
-       mov     [esp+chainlenwmask], ebx
-
-; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-       mov     eax, [edx].ds_nice_match
-       mov     ebx, [edx].ds_lookahead
-       cmp     ebx, eax
-       jl      SHORT LookaheadLess
-       mov     ebx, eax
-LookaheadLess:
-       mov     [esp+nicematch], ebx
-
-;/* register Bytef *scan = s->window + s->strstart;                     */
-
-       mov     esi, [edx].ds_window
-       mov     [esp+window], esi
-       mov     ebp, [edx].ds_strstart
-       lea     edi, [esi+ebp]
-       mov     [esp+scan],edi
-
-;/* Determine how many bytes the scan ptr is off from being             */
-;/* dword-aligned.                                                      */
-
-       mov     eax, edi
-       neg     eax
-       and     eax, 3
-       mov     [esp+scanalign], eax
-
-;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */
-;/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */
-
-       mov     eax, [edx].ds_w_size
-       sub     eax, MIN_LOOKAHEAD
-       sub     ebp, eax
-       jg      SHORT LimitPositive
-       xor     ebp, ebp
-LimitPositive:
-
-;/* int best_len = s->prev_length;                                      */
-
-       mov     eax, [edx].ds_prev_length
-       mov     [esp+bestlen], eax
-
-;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
-
-       add     esi, eax
-       mov     [esp+windowbestlen], esi
-
-;/* register ush scan_start = *(ushf*)scan;                             */
-;/* register ush scan_end   = *(ushf*)(scan+best_len-1);                */
-;/* Posf *prev = s->prev;                                               */
-
-       movzx   ebx, WORD PTR[edi]
-       mov     [esp+scanstart], ebx
-       movzx   ebx, WORD PTR[eax+edi-1]
-       mov     [esp+scanend], ebx
-       mov     edi, [edx].ds_prev
-
-;/* Jump into the main loop.                                            */
-
-       mov     edx, [esp+chainlenwmask]
-       jmp     SHORT LoopEntry
-
-;/* do {
-; *     match = s->window + cur_match;
-; *     if (*(ushf*)(match+best_len-1) != scan_end ||
-; *         *(ushf*)match != scan_start) continue;
-; *     [...]
-; * } while ((cur_match = prev[cur_match & wmask]) > limit
-; *          && --chain_length != 0);
-; *
-; * Here is the inner loop of the function. The function will spend the
-; * majority of its time in this loop, and majority of that time will
-; * be spent in the first ten instructions.
-; *
-; * Within this loop:
-; * %ebx = scanend
-; * %ecx = curmatch
-; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
-; * %esi = windowbestlen - i.e., (window + bestlen)
-; * %edi = prev
-; * %ebp = limit
-; */
-
-       ALIGN   4
-LookupLoop:
-       and     ecx, edx
-       movzx   ecx, WORD PTR[edi+ecx*2]
-       cmp     ecx, ebp
-       jbe     LeaveNow
-       sub     edx, 000010000H
-       js      LeaveNow
-
-LoopEntry:
-       movzx   eax, WORD PTR[esi+ecx-1]
-       cmp     eax, ebx
-       jnz     SHORT LookupLoop
-
-       mov     eax, [esp+window]
-       movzx   eax, WORD PTR[eax+ecx]
-       cmp     eax, [esp+scanstart]
-       jnz     SHORT LookupLoop
-
-;/* Store the current value of chainlen.                                */
-
-       mov     [esp+chainlenwmask], edx
-
-;/* Point %edi to the string under scrutiny, and %esi to the string we  */
-;/* are hoping to match it up with. In actuality, %esi and %edi are     */
-;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */
-;/* initialized to -(MAX_MATCH_8 - scanalign).                          */
-
-       mov     esi, [esp+window]
-       mov     edi, [esp+scan]
-       add     esi, ecx
-       mov     eax, [esp+scanalign]
-       mov     edx, -MAX_MATCH_8
-       lea     edi, [edi+eax+MAX_MATCH_8]
-       lea     esi, [esi+eax+MAX_MATCH_8]
-
-;/* Test the strings for equality, 8 bytes at a time. At the end,
-; * adjust %edx so that it is offset to the exact byte that mismatched.
-; *
-; * We already know at this point that the first three bytes of the
-; * strings match each other, and they can be safely passed over before
-; * starting the compare loop. So what this code does is skip over 0-3
-; * bytes, as much as necessary in order to dword-align the %edi
-; * pointer. (%esi will still be misaligned three times out of four.)
-; *
-; * It should be confessed that this loop usually does not represent
-; * much of the total running time. Replacing it with a more
-; * straightforward "rep cmpsb" would not drastically degrade
-; * performance.
-; */
-
-LoopCmps:
-       mov     eax, DWORD PTR[esi+edx]
-       xor     eax, DWORD PTR[edi+edx]
-       jnz     SHORT LeaveLoopCmps
-
-       mov     eax, DWORD PTR[esi+edx+4]
-       xor     eax, DWORD PTR[edi+edx+4]
-       jnz     SHORT LeaveLoopCmps4
-
-       add     edx, 8
-       jnz     SHORT LoopCmps
-       jmp     LenMaximum
-       ALIGN   4
-
-LeaveLoopCmps4:
-       add     edx, 4
-
-LeaveLoopCmps:
-       test    eax, 00000FFFFH
-       jnz     SHORT LenLower
-
-       add     edx, 2
-       shr     eax, 16
-
-LenLower:
-       sub     al, 1
-       adc     edx, 0
-
-;/* Calculate the length of the match. If it is longer than MAX_MATCH,  */
-;/* then automatically accept it as the best possible match and leave.  */
-
-       lea     eax, [edi+edx]
-       mov     edi, [esp+scan]
-       sub     eax, edi
-       cmp     eax, MAX_MATCH
-       jge     SHORT LenMaximum
-
-;/* If the length of the match is not longer than the best match we     */
-;/* have so far, then forget it and return to the lookup loop.          */
-
-       mov     edx, [esp+deflatestate]
-       mov     ebx, [esp+bestlen]
-       cmp     eax, ebx
-       jg      SHORT LongerMatch
-       mov     esi, [esp+windowbestlen]
-       mov     edi, [edx].ds_prev
-       mov     ebx, [esp+scanend]
-       mov     edx, [esp+chainlenwmask]
-       jmp     LookupLoop
-       ALIGN   4
-
-;/*         s->match_start = cur_match;                                 */
-;/*         best_len = len;                                             */
-;/*         if (len >= nice_match) break;                               */
-;/*         scan_end = *(ushf*)(scan+best_len-1);                       */
-
-LongerMatch:
-       mov     ebx, [esp+nicematch]
-       mov     [esp+bestlen], eax
-       mov     [edx].ds_match_start, ecx
-       cmp     eax, ebx
-       jge     SHORT LeaveNow
-       mov     esi, [esp+window]
-       add     esi, eax
-       mov     [esp+windowbestlen], esi
-       movzx   ebx, WORD PTR[edi+eax-1]
-       mov     edi, [edx].ds_prev
-       mov     [esp+scanend], ebx
-       mov     edx, [esp+chainlenwmask]
-       jmp     LookupLoop
-       ALIGN   4
-
-;/* Accept the current string, with the maximum possible length.        */
-
-LenMaximum:
-       mov     edx, [esp+deflatestate]
-       mov     DWORD PTR[esp+bestlen], MAX_MATCH
-       mov     [edx].ds_match_start, ecx
-
-;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */
-;/* return s->lookahead;                                                */
-
-LeaveNow:
-       mov     edx, [esp+deflatestate]
-       mov     ebx, [esp+bestlen]
-       mov     eax, [edx].ds_lookahead
-       cmp     ebx, eax
-       jg      SHORT LookaheadRet
-       mov     eax, ebx
-LookaheadRet:
-
-; Restore the stack and return from whence we came.
-
-       add     esp, varsize
-       pop     ebx
-       pop     esi
-       pop     edi
-       pop     ebp
-       ret
-
-_longest_match ENDP
-
-_TEXT  ENDS
-END
+\r
+; match.asm -- Pentium-Pro optimized version of longest_match()\r
+;\r
+; Updated for zlib 1.1.3 and converted to MASM 6.1x\r
+; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>\r
+;                    and Chuck Walbourn <chuckw@kinesoft.com>\r
+; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>\r
+;\r
+; This is free software; you can redistribute it and/or modify it\r
+; under the terms of the GNU General Public License.\r
+\r
+; Based on match.S\r
+; Written for zlib 1.1.2\r
+; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>\r
+;\r
+; Modified by Gilles Vollant (2005) for add gzhead and gzindex\r
+\r
+       .686P\r
+       .MODEL  FLAT\r
+\r
+;===========================================================================\r
+; EQUATES\r
+;===========================================================================\r
+\r
+MAX_MATCH      EQU 258\r
+MIN_MATCH      EQU 3\r
+MIN_LOOKAHEAD  EQU (MAX_MATCH + MIN_MATCH + 1)\r
+MAX_MATCH_8    EQU ((MAX_MATCH + 7) AND (NOT 7))\r
+\r
+;===========================================================================\r
+; STRUCTURES\r
+;===========================================================================\r
+\r
+; This STRUCT assumes a 4-byte alignment\r
+\r
+DEFLATE_STATE  STRUCT\r
+ds_strm                        dd ?\r
+ds_status              dd ?\r
+ds_pending_buf         dd ?\r
+ds_pending_buf_size    dd ?\r
+ds_pending_out         dd ?\r
+ds_pending             dd ?\r
+ds_wrap                        dd ?\r
+; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)\r
+ds_gzhead               dd ?\r
+ds_gzindex              dd ?\r
+ds_data_type           db ?\r
+ds_method              db ?\r
+                       db ?    ; padding\r
+                       db ?    ; padding\r
+ds_last_flush          dd ?\r
+ds_w_size              dd ?    ; used\r
+ds_w_bits              dd ?\r
+ds_w_mask              dd ?    ; used\r
+ds_window              dd ?    ; used\r
+ds_window_size         dd ?\r
+ds_prev                        dd ?    ; used\r
+ds_head                        dd ?\r
+ds_ins_h               dd ?\r
+ds_hash_size           dd ?\r
+ds_hash_bits           dd ?\r
+ds_hash_mask           dd ?\r
+ds_hash_shift          dd ?\r
+ds_block_start         dd ?\r
+ds_match_length                dd ?    ; used\r
+ds_prev_match          dd ?    ; used\r
+ds_match_available     dd ?\r
+ds_strstart            dd ?    ; used\r
+ds_match_start         dd ?    ; used\r
+ds_lookahead           dd ?    ; used\r
+ds_prev_length         dd ?    ; used\r
+ds_max_chain_length    dd ?    ; used\r
+ds_max_laxy_match      dd ?\r
+ds_level               dd ?\r
+ds_strategy            dd ?\r
+ds_good_match          dd ?    ; used\r
+ds_nice_match          dd ?    ; used\r
+\r
+; Don't need anymore of the struct for match\r
+DEFLATE_STATE  ENDS\r
+\r
+;===========================================================================\r
+; CODE\r
+;===========================================================================\r
+_TEXT  SEGMENT\r
+\r
+;---------------------------------------------------------------------------\r
+; match_init\r
+;---------------------------------------------------------------------------\r
+       ALIGN   4\r
+PUBLIC _match_init\r
+_match_init    PROC\r
+       ; no initialization needed\r
+       ret\r
+_match_init    ENDP\r
+\r
+;---------------------------------------------------------------------------\r
+; uInt longest_match(deflate_state *deflatestate, IPos curmatch)\r
+;---------------------------------------------------------------------------\r
+       ALIGN   4\r
+\r
+PUBLIC _longest_match\r
+_longest_match PROC\r
+\r
+; Since this code uses EBP for a scratch register, the stack frame must\r
+; be manually constructed and referenced relative to the ESP register.\r
+\r
+; Stack image\r
+; Variables\r
+chainlenwmask  =  0    ; high word: current chain len\r
+                       ; low word: s->wmask\r
+window         =  4    ; local copy of s->window\r
+windowbestlen  =  8    ; s->window + bestlen\r
+scanend                = 12    ; last two bytes of string\r
+scanstart      = 16    ; first two bytes of string\r
+scanalign      = 20    ; dword-misalignment of string\r
+nicematch      = 24    ; a good enough match size\r
+bestlen                = 28    ; size of best match so far\r
+scan           = 32    ; ptr to string wanting match\r
+varsize                = 36    ; number of bytes (also offset to last saved register)\r
+\r
+; Saved Registers (actually pushed into place)\r
+ebx_save       = 36\r
+edi_save       = 40\r
+esi_save       = 44\r
+ebp_save       = 48\r
+\r
+; Parameters\r
+retaddr                = 52\r
+deflatestate   = 56\r
+curmatch       = 60\r
+\r
+; Save registers that the compiler may be using\r
+       push    ebp\r
+       push    edi\r
+       push    esi\r
+       push    ebx\r
+\r
+; Allocate local variable space\r
+       sub     esp,varsize\r
+\r
+; Retrieve the function arguments. ecx will hold cur_match\r
+; throughout the entire function. edx will hold the pointer to the\r
+; deflate_state structure during the function's setup (before\r
+; entering the main loop).\r
+\r
+       mov     edx, [esp+deflatestate]\r
+ASSUME edx:PTR DEFLATE_STATE\r
+\r
+       mov     ecx, [esp+curmatch]\r
+\r
+; uInt wmask = s->w_mask;\r
+; unsigned chain_length = s->max_chain_length;\r
+; if (s->prev_length >= s->good_match) {\r
+;     chain_length >>= 2;\r
+; }\r
+\r
+       mov     eax, [edx].ds_prev_length\r
+       mov     ebx, [edx].ds_good_match\r
+       cmp     eax, ebx\r
+       mov     eax, [edx].ds_w_mask\r
+       mov     ebx, [edx].ds_max_chain_length\r
+       jl      SHORT LastMatchGood\r
+       shr     ebx, 2\r
+LastMatchGood:\r
+\r
+; chainlen is decremented once beforehand so that the function can\r
+; use the sign flag instead of the zero flag for the exit test.\r
+; It is then shifted into the high word, to make room for the wmask\r
+; value, which it will always accompany.\r
+\r
+       dec     ebx\r
+       shl     ebx, 16\r
+       or      ebx, eax\r
+       mov     [esp+chainlenwmask], ebx\r
+\r
+; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\r
+\r
+       mov     eax, [edx].ds_nice_match\r
+       mov     ebx, [edx].ds_lookahead\r
+       cmp     ebx, eax\r
+       jl      SHORT LookaheadLess\r
+       mov     ebx, eax\r
+LookaheadLess:\r
+       mov     [esp+nicematch], ebx\r
+\r
+;/* register Bytef *scan = s->window + s->strstart;                     */\r
+\r
+       mov     esi, [edx].ds_window\r
+       mov     [esp+window], esi\r
+       mov     ebp, [edx].ds_strstart\r
+       lea     edi, [esi+ebp]\r
+       mov     [esp+scan],edi\r
+\r
+;/* Determine how many bytes the scan ptr is off from being             */\r
+;/* dword-aligned.                                                      */\r
+\r
+       mov     eax, edi\r
+       neg     eax\r
+       and     eax, 3\r
+       mov     [esp+scanalign], eax\r
+\r
+;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */\r
+;/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */\r
+\r
+       mov     eax, [edx].ds_w_size\r
+       sub     eax, MIN_LOOKAHEAD\r
+       sub     ebp, eax\r
+       jg      SHORT LimitPositive\r
+       xor     ebp, ebp\r
+LimitPositive:\r
+\r
+;/* int best_len = s->prev_length;                                      */\r
+\r
+       mov     eax, [edx].ds_prev_length\r
+       mov     [esp+bestlen], eax\r
+\r
+;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */\r
+\r
+       add     esi, eax\r
+       mov     [esp+windowbestlen], esi\r
+\r
+;/* register ush scan_start = *(ushf*)scan;                             */\r
+;/* register ush scan_end   = *(ushf*)(scan+best_len-1);                */\r
+;/* Posf *prev = s->prev;                                               */\r
+\r
+       movzx   ebx, WORD PTR[edi]\r
+       mov     [esp+scanstart], ebx\r
+       movzx   ebx, WORD PTR[eax+edi-1]\r
+       mov     [esp+scanend], ebx\r
+       mov     edi, [edx].ds_prev\r
+\r
+;/* Jump into the main loop.                                            */\r
+\r
+       mov     edx, [esp+chainlenwmask]\r
+       jmp     SHORT LoopEntry\r
+\r
+;/* do {\r
+; *     match = s->window + cur_match;\r
+; *     if (*(ushf*)(match+best_len-1) != scan_end ||\r
+; *         *(ushf*)match != scan_start) continue;\r
+; *     [...]\r
+; * } while ((cur_match = prev[cur_match & wmask]) > limit\r
+; *          && --chain_length != 0);\r
+; *\r
+; * Here is the inner loop of the function. The function will spend the\r
+; * majority of its time in this loop, and majority of that time will\r
+; * be spent in the first ten instructions.\r
+; *\r
+; * Within this loop:\r
+; * %ebx = scanend\r
+; * %ecx = curmatch\r
+; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)\r
+; * %esi = windowbestlen - i.e., (window + bestlen)\r
+; * %edi = prev\r
+; * %ebp = limit\r
+; */\r
+\r
+       ALIGN   4\r
+LookupLoop:\r
+       and     ecx, edx\r
+       movzx   ecx, WORD PTR[edi+ecx*2]\r
+       cmp     ecx, ebp\r
+       jbe     LeaveNow\r
+       sub     edx, 000010000H\r
+       js      LeaveNow\r
+\r
+LoopEntry:\r
+       movzx   eax, WORD PTR[esi+ecx-1]\r
+       cmp     eax, ebx\r
+       jnz     SHORT LookupLoop\r
+\r
+       mov     eax, [esp+window]\r
+       movzx   eax, WORD PTR[eax+ecx]\r
+       cmp     eax, [esp+scanstart]\r
+       jnz     SHORT LookupLoop\r
+\r
+;/* Store the current value of chainlen.                                */\r
+\r
+       mov     [esp+chainlenwmask], edx\r
+\r
+;/* Point %edi to the string under scrutiny, and %esi to the string we  */\r
+;/* are hoping to match it up with. In actuality, %esi and %edi are     */\r
+;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is     */\r
+;/* initialized to -(MAX_MATCH_8 - scanalign).                          */\r
+\r
+       mov     esi, [esp+window]\r
+       mov     edi, [esp+scan]\r
+       add     esi, ecx\r
+       mov     eax, [esp+scanalign]\r
+       mov     edx, -MAX_MATCH_8\r
+       lea     edi, [edi+eax+MAX_MATCH_8]\r
+       lea     esi, [esi+eax+MAX_MATCH_8]\r
+\r
+;/* Test the strings for equality, 8 bytes at a time. At the end,\r
+; * adjust %edx so that it is offset to the exact byte that mismatched.\r
+; *\r
+; * We already know at this point that the first three bytes of the\r
+; * strings match each other, and they can be safely passed over before\r
+; * starting the compare loop. So what this code does is skip over 0-3\r
+; * bytes, as much as necessary in order to dword-align the %edi\r
+; * pointer. (%esi will still be misaligned three times out of four.)\r
+; *\r
+; * It should be confessed that this loop usually does not represent\r
+; * much of the total running time. Replacing it with a more\r
+; * straightforward "rep cmpsb" would not drastically degrade\r
+; * performance.\r
+; */\r
+\r
+LoopCmps:\r
+       mov     eax, DWORD PTR[esi+edx]\r
+       xor     eax, DWORD PTR[edi+edx]\r
+       jnz     SHORT LeaveLoopCmps\r
+\r
+       mov     eax, DWORD PTR[esi+edx+4]\r
+       xor     eax, DWORD PTR[edi+edx+4]\r
+       jnz     SHORT LeaveLoopCmps4\r
+\r
+       add     edx, 8\r
+       jnz     SHORT LoopCmps\r
+       jmp     LenMaximum\r
+       ALIGN   4\r
+\r
+LeaveLoopCmps4:\r
+       add     edx, 4\r
+\r
+LeaveLoopCmps:\r
+       test    eax, 00000FFFFH\r
+       jnz     SHORT LenLower\r
+\r
+       add     edx, 2\r
+       shr     eax, 16\r
+\r
+LenLower:\r
+       sub     al, 1\r
+       adc     edx, 0\r
+\r
+;/* Calculate the length of the match. If it is longer than MAX_MATCH,  */\r
+;/* then automatically accept it as the best possible match and leave.  */\r
+\r
+       lea     eax, [edi+edx]\r
+       mov     edi, [esp+scan]\r
+       sub     eax, edi\r
+       cmp     eax, MAX_MATCH\r
+       jge     SHORT LenMaximum\r
+\r
+;/* If the length of the match is not longer than the best match we     */\r
+;/* have so far, then forget it and return to the lookup loop.          */\r
+\r
+       mov     edx, [esp+deflatestate]\r
+       mov     ebx, [esp+bestlen]\r
+       cmp     eax, ebx\r
+       jg      SHORT LongerMatch\r
+       mov     esi, [esp+windowbestlen]\r
+       mov     edi, [edx].ds_prev\r
+       mov     ebx, [esp+scanend]\r
+       mov     edx, [esp+chainlenwmask]\r
+       jmp     LookupLoop\r
+       ALIGN   4\r
+\r
+;/*         s->match_start = cur_match;                                 */\r
+;/*         best_len = len;                                             */\r
+;/*         if (len >= nice_match) break;                               */\r
+;/*         scan_end = *(ushf*)(scan+best_len-1);                       */\r
+\r
+LongerMatch:\r
+       mov     ebx, [esp+nicematch]\r
+       mov     [esp+bestlen], eax\r
+       mov     [edx].ds_match_start, ecx\r
+       cmp     eax, ebx\r
+       jge     SHORT LeaveNow\r
+       mov     esi, [esp+window]\r
+       add     esi, eax\r
+       mov     [esp+windowbestlen], esi\r
+       movzx   ebx, WORD PTR[edi+eax-1]\r
+       mov     edi, [edx].ds_prev\r
+       mov     [esp+scanend], ebx\r
+       mov     edx, [esp+chainlenwmask]\r
+       jmp     LookupLoop\r
+       ALIGN   4\r
+\r
+;/* Accept the current string, with the maximum possible length.        */\r
+\r
+LenMaximum:\r
+       mov     edx, [esp+deflatestate]\r
+       mov     DWORD PTR[esp+bestlen], MAX_MATCH\r
+       mov     [edx].ds_match_start, ecx\r
+\r
+;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */\r
+;/* return s->lookahead;                                                */\r
+\r
+LeaveNow:\r
+       mov     edx, [esp+deflatestate]\r
+       mov     ebx, [esp+bestlen]\r
+       mov     eax, [edx].ds_lookahead\r
+       cmp     ebx, eax\r
+       jg      SHORT LookaheadRet\r
+       mov     eax, ebx\r
+LookaheadRet:\r
+\r
+; Restore the stack and return from whence we came.\r
+\r
+       add     esp, varsize\r
+       pop     ebx\r
+       pop     esi\r
+       pop     edi\r
+       pop     ebp\r
+       ret\r
+\r
+_longest_match ENDP\r
+\r
+_TEXT  ENDS\r
+END\r
index ec360e6..874bb2d 100644 (file)
-;
-; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
-; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
-; File written by Gilles Vollant, by modifiying the longest_match
-;  from Jean-loup Gailly in deflate.c
-; It need wmask == 0x7fff
-;     (assembly code is faster with a fixed wmask)
-;
-; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK)
-;   I compile with : "ml /coff /Zi /c gvmat32.asm"
-;
-
-;uInt longest_match_7fff(s, cur_match)
-;    deflate_state *s;
-;    IPos cur_match;                             /* current match */
-
-       NbStack         equ     76
-       cur_match       equ     dword ptr[esp+NbStack-0]
-       str_s           equ     dword ptr[esp+NbStack-4]
-; 5 dword on top (ret,ebp,esi,edi,ebx)
-       adrret          equ     dword ptr[esp+NbStack-8]
-       pushebp         equ     dword ptr[esp+NbStack-12]
-       pushedi         equ     dword ptr[esp+NbStack-16]
-       pushesi         equ     dword ptr[esp+NbStack-20]
-       pushebx         equ     dword ptr[esp+NbStack-24]
-
-       chain_length    equ     dword ptr [esp+NbStack-28]
-       limit           equ     dword ptr [esp+NbStack-32]
-       best_len        equ     dword ptr [esp+NbStack-36]
-       window          equ     dword ptr [esp+NbStack-40]
-       prev            equ     dword ptr [esp+NbStack-44]
-       scan_start      equ      word ptr [esp+NbStack-48]
-       wmask           equ     dword ptr [esp+NbStack-52]
-       match_start_ptr equ     dword ptr [esp+NbStack-56]
-       nice_match      equ     dword ptr [esp+NbStack-60]
-       scan            equ     dword ptr [esp+NbStack-64]
-
-       windowlen       equ     dword ptr [esp+NbStack-68]
-       match_start     equ     dword ptr [esp+NbStack-72]
-       strend          equ     dword ptr [esp+NbStack-76]
-       NbStackAdd      equ     (NbStack-24)
-
-    .386p
-
-    name    gvmatch
-    .MODEL  FLAT
-
-
-
-;  all the +4 offsets are due to the addition of pending_buf_size (in zlib
-;  in the deflate_state structure since the asm code was first written
-;  (if you compile with zlib 1.0.4 or older, remove the +4).
-;  Note : these value are good with a 8 bytes boundary pack structure
-    dep_chain_length    equ     70h+4
-    dep_window          equ     2ch+4
-    dep_strstart        equ     60h+4
-    dep_prev_length     equ     6ch+4
-    dep_nice_match      equ     84h+4
-    dep_w_size          equ     20h+4
-    dep_prev            equ     34h+4
-    dep_w_mask          equ     28h+4
-    dep_good_match      equ     80h+4
-    dep_match_start     equ     64h+4
-    dep_lookahead       equ     68h+4
-
-
-_TEXT                   segment
-
-IFDEF NOUNDERLINE
-                       public  longest_match_7fff
-                       public  longest_match_686
-;                        public  match_init
-ELSE
-                       public  _longest_match_7fff
-                       public  _longest_match_686
-;                        public  _match_init
-ENDIF
-
-    MAX_MATCH           equ     258
-    MIN_MATCH           equ     3
-    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
-
-
-
-IFDEF NOUNDERLINE
-;match_init      proc near
-;                ret
-;match_init      endp
-ELSE
-;_match_init     proc near
-;                ret
-;_match_init     endp
-ENDIF
-
-
-IFDEF NOUNDERLINE
-longest_match_7fff   proc near
-ELSE
-_longest_match_7fff  proc near
-ENDIF
-
-       mov     edx,[esp+4]
-
-
-
-       push    ebp
-       push    edi
-       push    esi
-       push    ebx
-
-       sub     esp,NbStackAdd
-
-; initialize or check the variables used in match.asm.
-       mov     ebp,edx
-
-; chain_length = s->max_chain_length
-; if (prev_length>=good_match) chain_length >>= 2
-       mov     edx,[ebp+dep_chain_length]
-       mov     ebx,[ebp+dep_prev_length]
-       cmp     [ebp+dep_good_match],ebx
-       ja      noshr
-       shr     edx,2
-noshr:
-; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
-       inc     edx
-       mov     edi,[ebp+dep_nice_match]
-       mov     chain_length,edx
-       mov     eax,[ebp+dep_lookahead]
-       cmp     eax,edi
-; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-       jae     nolookaheadnicematch
-       mov     edi,eax
-nolookaheadnicematch:
-; best_len = s->prev_length
-       mov     best_len,ebx
-
-; window = s->window
-       mov     esi,[ebp+dep_window]
-       mov     ecx,[ebp+dep_strstart]
-       mov     window,esi
-
-       mov     nice_match,edi
-; scan = window + strstart
-       add     esi,ecx
-       mov     scan,esi
-; dx = *window
-       mov     dx,word ptr [esi]
-; bx = *(window+best_len-1)
-       mov     bx,word ptr [esi+ebx-1]
-       add     esi,MAX_MATCH-1
-; scan_start = *scan
-       mov     scan_start,dx
-; strend = scan + MAX_MATCH-1
-       mov     strend,esi
-; bx = scan_end = *(window+best_len-1)
-
-;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-;        s->strstart - (IPos)MAX_DIST(s) : NIL;
-
-       mov     esi,[ebp+dep_w_size]
-       sub     esi,MIN_LOOKAHEAD
-; here esi = MAX_DIST(s)
-       sub     ecx,esi
-       ja      nodist
-       xor     ecx,ecx
-nodist:
-       mov     limit,ecx
-
-; prev = s->prev
-       mov     edx,[ebp+dep_prev]
-       mov     prev,edx
-
-;
-       mov     edx,dword ptr [ebp+dep_match_start]
-       mov     bp,scan_start
-       mov     eax,cur_match
-       mov     match_start,edx
-
-       mov     edx,window
-       mov     edi,edx
-       add     edi,best_len
-       mov     esi,prev
-       dec     edi
-; windowlen = window + best_len -1
-       mov     windowlen,edi
-
-       jmp     beginloop2
-       align   4
-
-; here, in the loop
-;       eax = ax = cur_match
-;       ecx = limit
-;        bx = scan_end
-;        bp = scan_start
-;       edi = windowlen (window + best_len -1)
-;       esi = prev
-
-
-;// here; chain_length <=16
-normalbeg0add16:
-       add     chain_length,16
-       jz      exitloop
-normalbeg0:
-       cmp     word ptr[edi+eax],bx
-       je      normalbeg2noroll
-rcontlabnoroll:
-; cur_match = prev[cur_match & wmask]
-       and     eax,7fffh
-       mov     ax,word ptr[esi+eax*2]
-; if cur_match > limit, go to exitloop
-       cmp     ecx,eax
-       jnb     exitloop
-; if --chain_length != 0, go to exitloop
-       dec     chain_length
-       jnz     normalbeg0
-       jmp     exitloop
-
-normalbeg2noroll:
-; if (scan_start==*(cur_match+window)) goto normalbeg2
-       cmp     bp,word ptr[edx+eax]
-       jne     rcontlabnoroll
-       jmp     normalbeg2
-
-contloop3:
-       mov     edi,windowlen
-
-; cur_match = prev[cur_match & wmask]
-       and     eax,7fffh
-       mov     ax,word ptr[esi+eax*2]
-; if cur_match > limit, go to exitloop
-       cmp     ecx,eax
-jnbexitloopshort1:
-       jnb     exitloop
-; if --chain_length != 0, go to exitloop
-
-
-; begin the main loop
-beginloop2:
-       sub     chain_length,16+1
-; if chain_length <=16, don't use the unrolled loop
-       jna     normalbeg0add16
-
-do16:
-       cmp     word ptr[edi+eax],bx
-       je      normalbeg2dc0
-
-maccn   MACRO   lab
-       and     eax,7fffh
-       mov     ax,word ptr[esi+eax*2]
-       cmp     ecx,eax
-       jnb     exitloop
-       cmp     word ptr[edi+eax],bx
-       je      lab
-       ENDM
-
-rcontloop0:
-       maccn   normalbeg2dc1
-
-rcontloop1:
-       maccn   normalbeg2dc2
-
-rcontloop2:
-       maccn   normalbeg2dc3
-
-rcontloop3:
-       maccn   normalbeg2dc4
-
-rcontloop4:
-       maccn   normalbeg2dc5
-
-rcontloop5:
-       maccn   normalbeg2dc6
-
-rcontloop6:
-       maccn   normalbeg2dc7
-
-rcontloop7:
-       maccn   normalbeg2dc8
-
-rcontloop8:
-       maccn   normalbeg2dc9
-
-rcontloop9:
-       maccn   normalbeg2dc10
-
-rcontloop10:
-       maccn   short normalbeg2dc11
-
-rcontloop11:
-       maccn   short normalbeg2dc12
-
-rcontloop12:
-       maccn   short normalbeg2dc13
-
-rcontloop13:
-       maccn   short normalbeg2dc14
-
-rcontloop14:
-       maccn   short normalbeg2dc15
-
-rcontloop15:
-       and     eax,7fffh
-       mov     ax,word ptr[esi+eax*2]
-       cmp     ecx,eax
-       jnb     exitloop
-
-       sub     chain_length,16
-       ja      do16
-       jmp     normalbeg0add16
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-normbeg MACRO   rcontlab,valsub
-; if we are here, we know that *(match+best_len-1) == scan_end
-       cmp     bp,word ptr[edx+eax]
-; if (match != scan_start) goto rcontlab
-       jne     rcontlab
-; calculate the good chain_length, and we'll compare scan and match string
-       add     chain_length,16-valsub
-       jmp     iseq
-       ENDM
-
-
-normalbeg2dc11:
-       normbeg rcontloop11,11
-
-normalbeg2dc12:
-       normbeg short rcontloop12,12
-
-normalbeg2dc13:
-       normbeg short rcontloop13,13
-
-normalbeg2dc14:
-       normbeg short rcontloop14,14
-
-normalbeg2dc15:
-       normbeg short rcontloop15,15
-
-normalbeg2dc10:
-       normbeg rcontloop10,10
-
-normalbeg2dc9:
-       normbeg rcontloop9,9
-
-normalbeg2dc8:
-       normbeg rcontloop8,8
-
-normalbeg2dc7:
-       normbeg rcontloop7,7
-
-normalbeg2dc6:
-       normbeg rcontloop6,6
-
-normalbeg2dc5:
-       normbeg rcontloop5,5
-
-normalbeg2dc4:
-       normbeg rcontloop4,4
-
-normalbeg2dc3:
-       normbeg rcontloop3,3
-
-normalbeg2dc2:
-       normbeg rcontloop2,2
-
-normalbeg2dc1:
-       normbeg rcontloop1,1
-
-normalbeg2dc0:
-       normbeg rcontloop0,0
-
-
-; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
-
-normalbeg2:
-       mov     edi,window
-
-       cmp     bp,word ptr[edi+eax]
-       jne     contloop3                   ; if *(ushf*)match != scan_start, continue
-
-iseq:
-; if we are here, we know that *(match+best_len-1) == scan_end
-; and (match == scan_start)
-
-       mov     edi,edx
-       mov     esi,scan                    ; esi = scan
-       add     edi,eax                     ; edi = window + cur_match = match
-
-       mov     edx,[esi+3]                 ; compare manually dword at match+3
-       xor     edx,[edi+3]                 ; and scan +3
-
-       jz      begincompare                ; if equal, go to long compare
-
-; we will determine the unmatch byte and calculate len (in esi)
-       or      dl,dl
-       je      eq1rr
-       mov     esi,3
-       jmp     trfinval
-eq1rr:
-       or      dx,dx
-       je      eq1
-
-       mov     esi,4
-       jmp     trfinval
-eq1:
-       and     edx,0ffffffh
-       jz      eq11
-       mov     esi,5
-       jmp     trfinval
-eq11:
-       mov     esi,6
-       jmp     trfinval
-
-begincompare:
-       ; here we now scan and match begin same
-       add     edi,6
-       add     esi,6
-       mov     ecx,(MAX_MATCH-(2+4))/4     ; scan for at most MAX_MATCH bytes
-       repe    cmpsd                       ; loop until mismatch
-
-       je      trfin                       ; go to trfin if not unmatch
-; we determine the unmatch byte
-       sub     esi,4
-       mov     edx,[edi-4]
-       xor     edx,[esi]
-
-       or      dl,dl
-       jnz     trfin
-       inc     esi
-
-       or      dx,dx
-       jnz     trfin
-       inc     esi
-
-       and     edx,0ffffffh
-       jnz     trfin
-       inc     esi
-
-trfin:
-       sub     esi,scan          ; esi = len
-trfinval:
-; here we have finised compare, and esi contain len of equal string
-       cmp     esi,best_len        ; if len > best_len, go newbestlen
-       ja      short newbestlen
-; now we restore edx, ecx and esi, for the big loop
-       mov     esi,prev
-       mov     ecx,limit
-       mov     edx,window
-       jmp     contloop3
-
-newbestlen:
-       mov     best_len,esi        ; len become best_len
-
-       mov     match_start,eax     ; save new position as match_start
-       cmp     esi,nice_match      ; if best_len >= nice_match, exit
-       jae     exitloop
-       mov     ecx,scan
-       mov     edx,window          ; restore edx=window
-       add     ecx,esi
-       add     esi,edx
-
-       dec     esi
-       mov     windowlen,esi       ; windowlen = window + best_len-1
-       mov     bx,[ecx-1]          ; bx = *(scan+best_len-1) = scan_end
-
-; now we restore ecx and esi, for the big loop :
-       mov     esi,prev
-       mov     ecx,limit
-       jmp     contloop3
-
-exitloop:
-; exit : s->match_start=match_start
-       mov     ebx,match_start
-       mov     ebp,str_s
-       mov     ecx,best_len
-       mov     dword ptr [ebp+dep_match_start],ebx
-       mov     eax,dword ptr [ebp+dep_lookahead]
-       cmp     ecx,eax
-       ja      minexlo
-       mov     eax,ecx
-minexlo:
-; return min(best_len,s->lookahead)
-
-; restore stack and register ebx,esi,edi,ebp
-       add     esp,NbStackAdd
-
-       pop     ebx
-       pop     esi
-       pop     edi
-       pop     ebp
-       ret
-InfoAuthor:
-; please don't remove this string !
-; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
-       db     0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
-
-
-
-IFDEF NOUNDERLINE
-longest_match_7fff   endp
-ELSE
-_longest_match_7fff  endp
-ENDIF
-
-
-IFDEF NOUNDERLINE
-cpudetect32     proc near
-ELSE
-_cpudetect32    proc near
-ENDIF
-
-       push    ebx
-
-       pushfd                  ; push original EFLAGS
-       pop     eax             ; get original EFLAGS
-       mov     ecx, eax        ; save original EFLAGS
-       xor     eax, 40000h     ; flip AC bit in EFLAGS
-       push    eax             ; save new EFLAGS value on stack
-       popfd                   ; replace current EFLAGS value
-       pushfd                  ; get new EFLAGS
-       pop     eax             ; store new EFLAGS in EAX
-       xor     eax, ecx        ; can\92t toggle AC bit, processor=80386
-       jz      end_cpu_is_386  ; jump if 80386 processor
-       push    ecx
-       popfd                   ; restore AC bit in EFLAGS first
-
-       pushfd
-       pushfd
-       pop     ecx
-
-       mov     eax, ecx        ; get original EFLAGS
-       xor     eax, 200000h    ; flip ID bit in EFLAGS
-       push    eax             ; save new EFLAGS value on stack
-       popfd                   ; replace current EFLAGS value
-       pushfd                  ; get new EFLAGS
-       pop             eax                 ; store new EFLAGS in EAX
-       popfd                   ; restore original EFLAGS
-       xor             eax, ecx        ; can\92t toggle ID bit,
-       je              is_old_486              ; processor=old
-
-       mov     eax,1
-       db      0fh,0a2h        ;CPUID
-
-exitcpudetect:
-       pop     ebx
-       ret
-
-end_cpu_is_386:
-       mov     eax,0300h
-       jmp     exitcpudetect
-
-is_old_486:
-       mov     eax,0400h
-       jmp     exitcpudetect
-
-IFDEF NOUNDERLINE
-cpudetect32     endp
-ELSE
-_cpudetect32    endp
-ENDIF
-
-
-
-
-MAX_MATCH       equ     258
-MIN_MATCH       equ     3
-MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)
-MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)
-
-
-;;; stack frame offsets
-
-chainlenwmask  equ  esp + 0    ; high word: current chain len
-                                       ; low word: s->wmask
-window         equ  esp + 4    ; local copy of s->window
-windowbestlen  equ  esp + 8    ; s->window + bestlen
-scanstart      equ  esp + 16   ; first two bytes of string
-scanend                equ  esp + 12   ; last two bytes of string
-scanalign      equ  esp + 20   ; dword-misalignment of string
-nicematch      equ  esp + 24   ; a good enough match size
-bestlen                equ  esp + 28   ; size of best match so far
-scan           equ  esp + 32   ; ptr to string wanting match
-
-LocalVarsSize  equ 36
-;      saved ebx       byte esp + 36
-;      saved edi       byte esp + 40
-;      saved esi       byte esp + 44
-;      saved ebp       byte esp + 48
-;      return address  byte esp + 52
-deflatestate   equ  esp + 56   ; the function arguments
-curmatch       equ  esp + 60
-
-;;; Offsets for fields in the deflate_state structure. These numbers
-;;; are calculated from the definition of deflate_state, with the
-;;; assumption that the compiler will dword-align the fields. (Thus,
-;;; changing the definition of deflate_state could easily cause this
-;;; program to crash horribly, without so much as a warning at
-;;; compile time. Sigh.)
-
-dsWSize                equ 36
-dsWMask                equ 44
-dsWindow       equ 48
-dsPrev         equ 56
-dsMatchLen     equ 88
-dsPrevMatch    equ 92
-dsStrStart     equ 100
-dsMatchStart   equ 104
-dsLookahead    equ 108
-dsPrevLen      equ 112
-dsMaxChainLen  equ 116
-dsGoodMatch    equ 132
-dsNiceMatch    equ 136
-
-
-;;; match.asm -- Pentium-Pro-optimized version of longest_match()
-;;; Written for zlib 1.1.2
-;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
-;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
-;;;
-;;; This is free software; you can redistribute it and/or modify it
-;;; under the terms of the GNU General Public License.
-
-;GLOBAL        _longest_match, _match_init
-
-
-;SECTION       .text
-
-;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
-
-;_longest_match:
-IFDEF NOUNDERLINE
-longest_match_686   proc near
-ELSE
-_longest_match_686  proc near
-ENDIF
-
-
-;;; Save registers that the compiler may be using, and adjust esp to
-;;; make room for our stack frame.
-
-               push    ebp
-               push    edi
-               push    esi
-               push    ebx
-               sub     esp, LocalVarsSize
-
-;;; Retrieve the function arguments. ecx will hold cur_match
-;;; throughout the entire function. edx will hold the pointer to the
-;;; deflate_state structure during the function's setup (before
-;;; entering the main loop.
-
-               mov     edx, [deflatestate]
-               mov     ecx, [curmatch]
-
-;;; uInt wmask = s->w_mask;
-;;; unsigned chain_length = s->max_chain_length;
-;;; if (s->prev_length >= s->good_match) {
-;;;     chain_length >>= 2;
-;;; }
-
-               mov     eax, [edx + dsPrevLen]
-               mov     ebx, [edx + dsGoodMatch]
-               cmp     eax, ebx
-               mov     eax, [edx + dsWMask]
-               mov     ebx, [edx + dsMaxChainLen]
-               jl      LastMatchGood
-               shr     ebx, 2
-LastMatchGood:
-
-;;; chainlen is decremented once beforehand so that the function can
-;;; use the sign flag instead of the zero flag for the exit test.
-;;; It is then shifted into the high word, to make room for the wmask
-;;; value, which it will always accompany.
-
-               dec     ebx
-               shl     ebx, 16
-               or      ebx, eax
-               mov     [chainlenwmask], ebx
-
-;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-               mov     eax, [edx + dsNiceMatch]
-               mov     ebx, [edx + dsLookahead]
-               cmp     ebx, eax
-               jl      LookaheadLess
-               mov     ebx, eax
-LookaheadLess: mov     [nicematch], ebx
-
-;;; register Bytef *scan = s->window + s->strstart;
-
-               mov     esi, [edx + dsWindow]
-               mov     [window], esi
-               mov     ebp, [edx + dsStrStart]
-               lea     edi, [esi + ebp]
-               mov     [scan], edi
-
-;;; Determine how many bytes the scan ptr is off from being
-;;; dword-aligned.
-
-               mov     eax, edi
-               neg     eax
-               and     eax, 3
-               mov     [scanalign], eax
-
-;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
-
-               mov     eax, [edx + dsWSize]
-               sub     eax, MIN_LOOKAHEAD
-               sub     ebp, eax
-               jg      LimitPositive
-               xor     ebp, ebp
-LimitPositive:
-
-;;; int best_len = s->prev_length;
-
-               mov     eax, [edx + dsPrevLen]
-               mov     [bestlen], eax
-
-;;; Store the sum of s->window + best_len in esi locally, and in esi.
-
-               add     esi, eax
-               mov     [windowbestlen], esi
-
-;;; register ush scan_start = *(ushf*)scan;
-;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
-;;; Posf *prev = s->prev;
-
-               movzx   ebx, word ptr [edi]
-               mov     [scanstart], ebx
-               movzx   ebx, word ptr [edi + eax - 1]
-               mov     [scanend], ebx
-               mov     edi, [edx + dsPrev]
-
-;;; Jump into the main loop.
-
-               mov     edx, [chainlenwmask]
-               jmp     short LoopEntry
-
-align 4
-
-;;; do {
-;;;     match = s->window + cur_match;
-;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
-;;;         *(ushf*)match != scan_start) continue;
-;;;     [...]
-;;; } while ((cur_match = prev[cur_match & wmask]) > limit
-;;;          && --chain_length != 0);
-;;;
-;;; Here is the inner loop of the function. The function will spend the
-;;; majority of its time in this loop, and majority of that time will
-;;; be spent in the first ten instructions.
-;;;
-;;; Within this loop:
-;;; ebx = scanend
-;;; ecx = curmatch
-;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
-;;; esi = windowbestlen - i.e., (window + bestlen)
-;;; edi = prev
-;;; ebp = limit
-
-LookupLoop:
-               and     ecx, edx
-               movzx   ecx, word ptr [edi + ecx*2]
-               cmp     ecx, ebp
-               jbe     LeaveNow
-               sub     edx, 00010000h
-               js      LeaveNow
-LoopEntry:     movzx   eax, word ptr [esi + ecx - 1]
-               cmp     eax, ebx
-               jnz     LookupLoop
-               mov     eax, [window]
-               movzx   eax, word ptr [eax + ecx]
-               cmp     eax, [scanstart]
-               jnz     LookupLoop
-
-;;; Store the current value of chainlen.
-
-               mov     [chainlenwmask], edx
-
-;;; Point edi to the string under scrutiny, and esi to the string we
-;;; are hoping to match it up with. In actuality, esi and edi are
-;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
-;;; initialized to -(MAX_MATCH_8 - scanalign).
-
-               mov     esi, [window]
-               mov     edi, [scan]
-               add     esi, ecx
-               mov     eax, [scanalign]
-               mov     edx, 0fffffef8h; -(MAX_MATCH_8)
-               lea     edi, [edi + eax + 0108h] ;MAX_MATCH_8]
-               lea     esi, [esi + eax + 0108h] ;MAX_MATCH_8]
-
-;;; Test the strings for equality, 8 bytes at a time. At the end,
-;;; adjust edx so that it is offset to the exact byte that mismatched.
-;;;
-;;; We already know at this point that the first three bytes of the
-;;; strings match each other, and they can be safely passed over before
-;;; starting the compare loop. So what this code does is skip over 0-3
-;;; bytes, as much as necessary in order to dword-align the edi
-;;; pointer. (esi will still be misaligned three times out of four.)
-;;;
-;;; It should be confessed that this loop usually does not represent
-;;; much of the total running time. Replacing it with a more
-;;; straightforward "rep cmpsb" would not drastically degrade
-;;; performance.
-
-LoopCmps:
-               mov     eax, [esi + edx]
-               xor     eax, [edi + edx]
-               jnz     LeaveLoopCmps
-               mov     eax, [esi + edx + 4]
-               xor     eax, [edi + edx + 4]
-               jnz     LeaveLoopCmps4
-               add     edx, 8
-               jnz     LoopCmps
-               jmp     short LenMaximum
-LeaveLoopCmps4:        add     edx, 4
-LeaveLoopCmps: test    eax, 0000FFFFh
-               jnz     LenLower
-               add     edx,  2
-               shr     eax, 16
-LenLower:      sub     al, 1
-               adc     edx, 0
-
-;;; Calculate the length of the match. If it is longer than MAX_MATCH,
-;;; then automatically accept it as the best possible match and leave.
-
-               lea     eax, [edi + edx]
-               mov     edi, [scan]
-               sub     eax, edi
-               cmp     eax, MAX_MATCH
-               jge     LenMaximum
-
-;;; If the length of the match is not longer than the best match we
-;;; have so far, then forget it and return to the lookup loop.
-
-               mov     edx, [deflatestate]
-               mov     ebx, [bestlen]
-               cmp     eax, ebx
-               jg      LongerMatch
-               mov     esi, [windowbestlen]
-               mov     edi, [edx + dsPrev]
-               mov     ebx, [scanend]
-               mov     edx, [chainlenwmask]
-               jmp     LookupLoop
-
-;;;         s->match_start = cur_match;
-;;;         best_len = len;
-;;;         if (len >= nice_match) break;
-;;;         scan_end = *(ushf*)(scan+best_len-1);
-
-LongerMatch:   mov     ebx, [nicematch]
-               mov     [bestlen], eax
-               mov     [edx + dsMatchStart], ecx
-               cmp     eax, ebx
-               jge     LeaveNow
-               mov     esi, [window]
-               add     esi, eax
-               mov     [windowbestlen], esi
-               movzx   ebx, word ptr [edi + eax - 1]
-               mov     edi, [edx + dsPrev]
-               mov     [scanend], ebx
-               mov     edx, [chainlenwmask]
-               jmp     LookupLoop
-
-;;; Accept the current string, with the maximum possible length.
-
-LenMaximum:    mov     edx, [deflatestate]
-               mov     dword ptr [bestlen], MAX_MATCH
-               mov     [edx + dsMatchStart], ecx
-
-;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
-;;; return s->lookahead;
-
-LeaveNow:
-               mov     edx, [deflatestate]
-               mov     ebx, [bestlen]
-               mov     eax, [edx + dsLookahead]
-               cmp     ebx, eax
-               jg      LookaheadRet
-               mov     eax, ebx
-LookaheadRet:
-
-;;; Restore the stack and return from whence we came.
-
-               add     esp, LocalVarsSize
-               pop     ebx
-               pop     esi
-               pop     edi
-               pop     ebp
-
-               ret
-; please don't remove this string !
-; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
-       db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
-
-IFDEF NOUNDERLINE
-longest_match_686   endp
-ELSE
-_longest_match_686  endp
-ENDIF
-
-_TEXT   ends
-end
+; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86\r
+; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.\r
+; File written by Gilles Vollant, by modifiying the longest_match\r
+;  from Jean-loup Gailly in deflate.c\r
+;\r
+;         http://www.zlib.net\r
+;         http://www.winimage.com/zLibDll\r
+;         http://www.muppetlabs.com/~breadbox/software/assembly.html\r
+;\r
+; For Visual C++ 4.x and higher and ML 6.x and higher\r
+;   ml.exe is in directory \MASM611C of Win95 DDK\r
+;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm\r
+;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/\r
+;\r
+; this file contain two implementation of longest_match\r
+;\r
+;  longest_match_7fff : written 1996 by Gilles Vollant optimized for \r
+;            first Pentium. Assume s->w_mask == 0x7fff\r
+;  longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro\r
+;\r
+;  for using an seembly version of longest_match, you need define ASMV in project\r
+;  There is two way in using gvmat32.asm\r
+;\r
+;  A) Suggested method\r
+;    if you want include both longest_match_7fff and longest_match_686\r
+;    compile the asm file running\r
+;           ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm\r
+;    and include gvmat32c.c in your project\r
+;    if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,\r
+;        longest_match_7fff will be used\r
+;    if you have a more modern CPU (Pentium Pro, II and higher)\r
+;        longest_match_686 will be used\r
+;    on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,\r
+;        but this is not a sitation you'll find often\r
+;\r
+;  B) Alternative\r
+;    if you are not interresed in old cpu performance and want the smaller\r
+;       binaries possible\r
+;\r
+;    compile the asm file running\r
+;           ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm\r
+;    and do not include gvmat32c.c in your project (ou define also \r
+;              NOOLDPENTIUMCODE)\r
+;\r
+; note : as I known, longest_match_686 is very faster than longest_match_7fff\r
+;        on pentium Pro/II/III, faster (but less) in P4, but it seem\r
+;        longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8\r
+;\r
+; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2\r
+\r
+;uInt longest_match_7fff(s, cur_match)\r
+;    deflate_state *s;\r
+;    IPos cur_match;                             /* current match */\r
+\r
+    NbStack         equ     76\r
+    cur_match       equ     dword ptr[esp+NbStack-0]\r
+    str_s           equ     dword ptr[esp+NbStack-4]\r
+; 5 dword on top (ret,ebp,esi,edi,ebx)\r
+    adrret          equ     dword ptr[esp+NbStack-8]\r
+    pushebp         equ     dword ptr[esp+NbStack-12]\r
+    pushedi         equ     dword ptr[esp+NbStack-16]\r
+    pushesi         equ     dword ptr[esp+NbStack-20]\r
+    pushebx         equ     dword ptr[esp+NbStack-24]\r
+\r
+    chain_length    equ     dword ptr [esp+NbStack-28]\r
+    limit           equ     dword ptr [esp+NbStack-32]\r
+    best_len        equ     dword ptr [esp+NbStack-36]\r
+    window          equ     dword ptr [esp+NbStack-40]\r
+    prev            equ     dword ptr [esp+NbStack-44]\r
+    scan_start      equ      word ptr [esp+NbStack-48]\r
+    wmask           equ     dword ptr [esp+NbStack-52]\r
+    match_start_ptr equ     dword ptr [esp+NbStack-56]\r
+    nice_match      equ     dword ptr [esp+NbStack-60]\r
+    scan            equ     dword ptr [esp+NbStack-64]\r
+\r
+    windowlen       equ     dword ptr [esp+NbStack-68]\r
+    match_start     equ     dword ptr [esp+NbStack-72]\r
+    strend          equ     dword ptr [esp+NbStack-76]\r
+    NbStackAdd      equ     (NbStack-24)\r
+\r
+    .386p\r
+\r
+    name    gvmatch\r
+    .MODEL  FLAT\r
+\r
+\r
+\r
+;  all the +zlib1222add offsets are due to the addition of fields\r
+;  in zlib in the deflate_state structure since the asm code was first written\r
+;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").\r
+;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").\r
+;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").\r
+\r
+    zlib1222add         equ     8\r
+\r
+;  Note : these value are good with a 8 bytes boundary pack structure\r
+    dep_chain_length    equ     74h+zlib1222add\r
+    dep_window          equ     30h+zlib1222add\r
+    dep_strstart        equ     64h+zlib1222add\r
+    dep_prev_length     equ     70h+zlib1222add\r
+    dep_nice_match      equ     88h+zlib1222add\r
+    dep_w_size          equ     24h+zlib1222add\r
+    dep_prev            equ     38h+zlib1222add\r
+    dep_w_mask          equ     2ch+zlib1222add\r
+    dep_good_match      equ     84h+zlib1222add\r
+    dep_match_start     equ     68h+zlib1222add\r
+    dep_lookahead       equ     6ch+zlib1222add\r
+\r
+\r
+_TEXT                   segment\r
+\r
+IFDEF NOUNDERLINE\r
+   IFDEF NOOLDPENTIUMCODE\r
+            public  longest_match\r
+            public  match_init\r
+   ELSE            \r
+            public  longest_match_7fff\r
+            public  cpudetect32\r
+            public  longest_match_686\r
+   ENDIF\r
+ELSE\r
+   IFDEF NOOLDPENTIUMCODE\r
+            public  _longest_match\r
+            public  _match_init\r
+   ELSE\r
+            public  _longest_match_7fff\r
+            public  _cpudetect32\r
+            public  _longest_match_686\r
+   ENDIF\r
+ENDIF\r
+\r
+    MAX_MATCH           equ     258\r
+    MIN_MATCH           equ     3\r
+    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)\r
+\r
+\r
+\r
+IFNDEF NOOLDPENTIUMCODE\r
+IFDEF NOUNDERLINE\r
+longest_match_7fff   proc near\r
+ELSE\r
+_longest_match_7fff  proc near\r
+ENDIF\r
+\r
+    mov     edx,[esp+4]\r
+\r
+\r
+\r
+    push    ebp\r
+    push    edi\r
+    push    esi\r
+    push    ebx\r
+\r
+    sub     esp,NbStackAdd\r
+\r
+; initialize or check the variables used in match.asm.\r
+    mov     ebp,edx\r
+\r
+; chain_length = s->max_chain_length\r
+; if (prev_length>=good_match) chain_length >>= 2\r
+    mov     edx,[ebp+dep_chain_length]\r
+    mov     ebx,[ebp+dep_prev_length]\r
+    cmp     [ebp+dep_good_match],ebx\r
+    ja      noshr\r
+    shr     edx,2\r
+noshr:\r
+; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop\r
+    inc     edx\r
+    mov     edi,[ebp+dep_nice_match]\r
+    mov     chain_length,edx\r
+    mov     eax,[ebp+dep_lookahead]\r
+    cmp     eax,edi\r
+; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\r
+    jae     nolookaheadnicematch\r
+    mov     edi,eax\r
+nolookaheadnicematch:\r
+; best_len = s->prev_length\r
+    mov     best_len,ebx\r
+\r
+; window = s->window\r
+    mov     esi,[ebp+dep_window]\r
+    mov     ecx,[ebp+dep_strstart]\r
+    mov     window,esi\r
+\r
+    mov     nice_match,edi\r
+; scan = window + strstart\r
+    add     esi,ecx\r
+    mov     scan,esi\r
+; dx = *window\r
+    mov     dx,word ptr [esi]\r
+; bx = *(window+best_len-1)\r
+    mov     bx,word ptr [esi+ebx-1]\r
+    add     esi,MAX_MATCH-1\r
+; scan_start = *scan\r
+    mov     scan_start,dx\r
+; strend = scan + MAX_MATCH-1\r
+    mov     strend,esi\r
+; bx = scan_end = *(window+best_len-1)\r
+\r
+;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\r
+;        s->strstart - (IPos)MAX_DIST(s) : NIL;\r
+\r
+    mov     esi,[ebp+dep_w_size]\r
+    sub     esi,MIN_LOOKAHEAD\r
+; here esi = MAX_DIST(s)\r
+    sub     ecx,esi\r
+    ja      nodist\r
+    xor     ecx,ecx\r
+nodist:\r
+    mov     limit,ecx\r
+\r
+; prev = s->prev\r
+    mov     edx,[ebp+dep_prev]\r
+    mov     prev,edx\r
+\r
+;\r
+    mov     edx,dword ptr [ebp+dep_match_start]\r
+    mov     bp,scan_start\r
+    mov     eax,cur_match\r
+    mov     match_start,edx\r
+\r
+    mov     edx,window\r
+    mov     edi,edx\r
+    add     edi,best_len\r
+    mov     esi,prev\r
+    dec     edi\r
+; windowlen = window + best_len -1\r
+    mov     windowlen,edi\r
+\r
+    jmp     beginloop2\r
+    align   4\r
+\r
+; here, in the loop\r
+;       eax = ax = cur_match\r
+;       ecx = limit\r
+;        bx = scan_end\r
+;        bp = scan_start\r
+;       edi = windowlen (window + best_len -1)\r
+;       esi = prev\r
+\r
+\r
+;// here; chain_length <=16\r
+normalbeg0add16:\r
+    add     chain_length,16\r
+    jz      exitloop\r
+normalbeg0:\r
+    cmp     word ptr[edi+eax],bx\r
+    je      normalbeg2noroll\r
+rcontlabnoroll:\r
+; cur_match = prev[cur_match & wmask]\r
+    and     eax,7fffh\r
+    mov     ax,word ptr[esi+eax*2]\r
+; if cur_match > limit, go to exitloop\r
+    cmp     ecx,eax\r
+    jnb     exitloop\r
+; if --chain_length != 0, go to exitloop\r
+    dec     chain_length\r
+    jnz     normalbeg0\r
+    jmp     exitloop\r
+\r
+normalbeg2noroll:\r
+; if (scan_start==*(cur_match+window)) goto normalbeg2\r
+    cmp     bp,word ptr[edx+eax]\r
+    jne     rcontlabnoroll\r
+    jmp     normalbeg2\r
+\r
+contloop3:\r
+    mov     edi,windowlen\r
+\r
+; cur_match = prev[cur_match & wmask]\r
+    and     eax,7fffh\r
+    mov     ax,word ptr[esi+eax*2]\r
+; if cur_match > limit, go to exitloop\r
+    cmp     ecx,eax\r
+jnbexitloopshort1:\r
+    jnb     exitloop\r
+; if --chain_length != 0, go to exitloop\r
+\r
+\r
+; begin the main loop\r
+beginloop2:\r
+    sub     chain_length,16+1\r
+; if chain_length <=16, don't use the unrolled loop\r
+    jna     normalbeg0add16\r
+\r
+do16:\r
+    cmp     word ptr[edi+eax],bx\r
+    je      normalbeg2dc0\r
+\r
+maccn   MACRO   lab\r
+    and     eax,7fffh\r
+    mov     ax,word ptr[esi+eax*2]\r
+    cmp     ecx,eax\r
+    jnb     exitloop\r
+    cmp     word ptr[edi+eax],bx\r
+    je      lab\r
+    ENDM\r
+\r
+rcontloop0:\r
+    maccn   normalbeg2dc1\r
+\r
+rcontloop1:\r
+    maccn   normalbeg2dc2\r
+\r
+rcontloop2:\r
+    maccn   normalbeg2dc3\r
+\r
+rcontloop3:\r
+    maccn   normalbeg2dc4\r
+\r
+rcontloop4:\r
+    maccn   normalbeg2dc5\r
+\r
+rcontloop5:\r
+    maccn   normalbeg2dc6\r
+\r
+rcontloop6:\r
+    maccn   normalbeg2dc7\r
+\r
+rcontloop7:\r
+    maccn   normalbeg2dc8\r
+\r
+rcontloop8:\r
+    maccn   normalbeg2dc9\r
+\r
+rcontloop9:\r
+    maccn   normalbeg2dc10\r
+\r
+rcontloop10:\r
+    maccn   short normalbeg2dc11\r
+\r
+rcontloop11:\r
+    maccn   short normalbeg2dc12\r
+\r
+rcontloop12:\r
+    maccn   short normalbeg2dc13\r
+\r
+rcontloop13:\r
+    maccn   short normalbeg2dc14\r
+\r
+rcontloop14:\r
+    maccn   short normalbeg2dc15\r
+\r
+rcontloop15:\r
+    and     eax,7fffh\r
+    mov     ax,word ptr[esi+eax*2]\r
+    cmp     ecx,eax\r
+    jnb     exitloop\r
+\r
+    sub     chain_length,16\r
+    ja      do16\r
+    jmp     normalbeg0add16\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+normbeg MACRO   rcontlab,valsub\r
+; if we are here, we know that *(match+best_len-1) == scan_end\r
+    cmp     bp,word ptr[edx+eax]\r
+; if (match != scan_start) goto rcontlab\r
+    jne     rcontlab\r
+; calculate the good chain_length, and we'll compare scan and match string\r
+    add     chain_length,16-valsub\r
+    jmp     iseq\r
+    ENDM\r
+\r
+\r
+normalbeg2dc11:\r
+    normbeg rcontloop11,11\r
+\r
+normalbeg2dc12:\r
+    normbeg short rcontloop12,12\r
+\r
+normalbeg2dc13:\r
+    normbeg short rcontloop13,13\r
+\r
+normalbeg2dc14:\r
+    normbeg short rcontloop14,14\r
+\r
+normalbeg2dc15:\r
+    normbeg short rcontloop15,15\r
+\r
+normalbeg2dc10:\r
+    normbeg rcontloop10,10\r
+\r
+normalbeg2dc9:\r
+    normbeg rcontloop9,9\r
+\r
+normalbeg2dc8:\r
+    normbeg rcontloop8,8\r
+\r
+normalbeg2dc7:\r
+    normbeg rcontloop7,7\r
+\r
+normalbeg2dc6:\r
+    normbeg rcontloop6,6\r
+\r
+normalbeg2dc5:\r
+    normbeg rcontloop5,5\r
+\r
+normalbeg2dc4:\r
+    normbeg rcontloop4,4\r
+\r
+normalbeg2dc3:\r
+    normbeg rcontloop3,3\r
+\r
+normalbeg2dc2:\r
+    normbeg rcontloop2,2\r
+\r
+normalbeg2dc1:\r
+    normbeg rcontloop1,1\r
+\r
+normalbeg2dc0:\r
+    normbeg rcontloop0,0\r
+\r
+\r
+; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end\r
+\r
+normalbeg2:\r
+    mov     edi,window\r
+\r
+    cmp     bp,word ptr[edi+eax]\r
+    jne     contloop3                   ; if *(ushf*)match != scan_start, continue\r
+\r
+iseq:\r
+; if we are here, we know that *(match+best_len-1) == scan_end\r
+; and (match == scan_start)\r
+\r
+    mov     edi,edx\r
+    mov     esi,scan                    ; esi = scan\r
+    add     edi,eax                     ; edi = window + cur_match = match\r
+\r
+    mov     edx,[esi+3]                 ; compare manually dword at match+3\r
+    xor     edx,[edi+3]                 ; and scan +3\r
+\r
+    jz      begincompare                ; if equal, go to long compare\r
+\r
+; we will determine the unmatch byte and calculate len (in esi)\r
+    or      dl,dl\r
+    je      eq1rr\r
+    mov     esi,3\r
+    jmp     trfinval\r
+eq1rr:\r
+    or      dx,dx\r
+    je      eq1\r
+\r
+    mov     esi,4\r
+    jmp     trfinval\r
+eq1:\r
+    and     edx,0ffffffh\r
+    jz      eq11\r
+    mov     esi,5\r
+    jmp     trfinval\r
+eq11:\r
+    mov     esi,6\r
+    jmp     trfinval\r
+\r
+begincompare:\r
+    ; here we now scan and match begin same\r
+    add     edi,6\r
+    add     esi,6\r
+    mov     ecx,(MAX_MATCH-(2+4))/4     ; scan for at most MAX_MATCH bytes\r
+    repe    cmpsd                       ; loop until mismatch\r
+\r
+    je      trfin                       ; go to trfin if not unmatch\r
+; we determine the unmatch byte\r
+    sub     esi,4\r
+    mov     edx,[edi-4]\r
+    xor     edx,[esi]\r
+\r
+    or      dl,dl\r
+    jnz     trfin\r
+    inc     esi\r
+\r
+    or      dx,dx\r
+    jnz     trfin\r
+    inc     esi\r
+\r
+    and     edx,0ffffffh\r
+    jnz     trfin\r
+    inc     esi\r
+\r
+trfin:\r
+    sub     esi,scan          ; esi = len\r
+trfinval:\r
+; here we have finised compare, and esi contain len of equal string\r
+    cmp     esi,best_len        ; if len > best_len, go newbestlen\r
+    ja      short newbestlen\r
+; now we restore edx, ecx and esi, for the big loop\r
+    mov     esi,prev\r
+    mov     ecx,limit\r
+    mov     edx,window\r
+    jmp     contloop3\r
+\r
+newbestlen:\r
+    mov     best_len,esi        ; len become best_len\r
+\r
+    mov     match_start,eax     ; save new position as match_start\r
+    cmp     esi,nice_match      ; if best_len >= nice_match, exit\r
+    jae     exitloop\r
+    mov     ecx,scan\r
+    mov     edx,window          ; restore edx=window\r
+    add     ecx,esi\r
+    add     esi,edx\r
+\r
+    dec     esi\r
+    mov     windowlen,esi       ; windowlen = window + best_len-1\r
+    mov     bx,[ecx-1]          ; bx = *(scan+best_len-1) = scan_end\r
+\r
+; now we restore ecx and esi, for the big loop :\r
+    mov     esi,prev\r
+    mov     ecx,limit\r
+    jmp     contloop3\r
+\r
+exitloop:\r
+; exit : s->match_start=match_start\r
+    mov     ebx,match_start\r
+    mov     ebp,str_s\r
+    mov     ecx,best_len\r
+    mov     dword ptr [ebp+dep_match_start],ebx\r
+    mov     eax,dword ptr [ebp+dep_lookahead]\r
+    cmp     ecx,eax\r
+    ja      minexlo\r
+    mov     eax,ecx\r
+minexlo:\r
+; return min(best_len,s->lookahead)\r
+\r
+; restore stack and register ebx,esi,edi,ebp\r
+    add     esp,NbStackAdd\r
+\r
+    pop     ebx\r
+    pop     esi\r
+    pop     edi\r
+    pop     ebp\r
+    ret\r
+InfoAuthor:\r
+; please don't remove this string !\r
+; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!\r
+    db     0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah\r
+\r
+\r
+\r
+IFDEF NOUNDERLINE\r
+longest_match_7fff   endp\r
+ELSE\r
+_longest_match_7fff  endp\r
+ENDIF\r
+\r
+\r
+IFDEF NOUNDERLINE\r
+cpudetect32     proc near\r
+ELSE\r
+_cpudetect32    proc near\r
+ENDIF\r
+\r
+    push    ebx\r
+\r
+    pushfd                  ; push original EFLAGS\r
+    pop     eax             ; get original EFLAGS\r
+    mov     ecx, eax        ; save original EFLAGS\r
+    xor     eax, 40000h     ; flip AC bit in EFLAGS\r
+    push    eax             ; save new EFLAGS value on stack\r
+    popfd                   ; replace current EFLAGS value\r
+    pushfd                  ; get new EFLAGS\r
+    pop     eax             ; store new EFLAGS in EAX\r
+    xor     eax, ecx        ; can\92t toggle AC bit, processor=80386\r
+    jz      end_cpu_is_386  ; jump if 80386 processor\r
+    push    ecx\r
+    popfd                   ; restore AC bit in EFLAGS first\r
+\r
+    pushfd\r
+    pushfd\r
+    pop     ecx\r
+\r
+    mov     eax, ecx        ; get original EFLAGS\r
+    xor     eax, 200000h    ; flip ID bit in EFLAGS\r
+    push    eax             ; save new EFLAGS value on stack\r
+    popfd                   ; replace current EFLAGS value\r
+    pushfd                  ; get new EFLAGS\r
+    pop     eax             ; store new EFLAGS in EAX\r
+    popfd                   ; restore original EFLAGS\r
+    xor     eax, ecx        ; can\92t toggle ID bit,\r
+    je      is_old_486      ; processor=old\r
+\r
+    mov     eax,1\r
+    db      0fh,0a2h        ;CPUID\r
+\r
+exitcpudetect:\r
+    pop ebx\r
+    ret\r
+\r
+end_cpu_is_386:\r
+    mov     eax,0300h\r
+    jmp     exitcpudetect\r
+\r
+is_old_486:\r
+    mov     eax,0400h\r
+    jmp     exitcpudetect\r
+\r
+IFDEF NOUNDERLINE\r
+cpudetect32     endp\r
+ELSE\r
+_cpudetect32    endp\r
+ENDIF\r
+ENDIF\r
+\r
+MAX_MATCH       equ     258\r
+MIN_MATCH       equ     3\r
+MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)\r
+MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)\r
+\r
+\r
+;;; stack frame offsets\r
+\r
+chainlenwmask   equ  esp + 0    ; high word: current chain len\r
+                    ; low word: s->wmask\r
+window      equ  esp + 4    ; local copy of s->window\r
+windowbestlen   equ  esp + 8    ; s->window + bestlen\r
+scanstart   equ  esp + 16   ; first two bytes of string\r
+scanend     equ  esp + 12   ; last two bytes of string\r
+scanalign   equ  esp + 20   ; dword-misalignment of string\r
+nicematch   equ  esp + 24   ; a good enough match size\r
+bestlen     equ  esp + 28   ; size of best match so far\r
+scan        equ  esp + 32   ; ptr to string wanting match\r
+\r
+LocalVarsSize   equ 36\r
+;   saved ebx   byte esp + 36\r
+;   saved edi   byte esp + 40\r
+;   saved esi   byte esp + 44\r
+;   saved ebp   byte esp + 48\r
+;   return address  byte esp + 52\r
+deflatestate    equ  esp + 56   ; the function arguments\r
+curmatch    equ  esp + 60\r
+\r
+;;; Offsets for fields in the deflate_state structure. These numbers\r
+;;; are calculated from the definition of deflate_state, with the\r
+;;; assumption that the compiler will dword-align the fields. (Thus,\r
+;;; changing the definition of deflate_state could easily cause this\r
+;;; program to crash horribly, without so much as a warning at\r
+;;; compile time. Sigh.)\r
+\r
+dsWSize     equ 36+zlib1222add\r
+dsWMask     equ 44+zlib1222add\r
+dsWindow    equ 48+zlib1222add\r
+dsPrev      equ 56+zlib1222add\r
+dsMatchLen  equ 88+zlib1222add\r
+dsPrevMatch equ 92+zlib1222add\r
+dsStrStart  equ 100+zlib1222add\r
+dsMatchStart    equ 104+zlib1222add\r
+dsLookahead equ 108+zlib1222add\r
+dsPrevLen   equ 112+zlib1222add\r
+dsMaxChainLen   equ 116+zlib1222add\r
+dsGoodMatch equ 132+zlib1222add\r
+dsNiceMatch equ 136+zlib1222add\r
+\r
+\r
+;;; match.asm -- Pentium-Pro-optimized version of longest_match()\r
+;;; Written for zlib 1.1.2\r
+;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>\r
+;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html\r
+;;;\r
+;;; This is free software; you can redistribute it and/or modify it\r
+;;; under the terms of the GNU General Public License.\r
+\r
+;GLOBAL _longest_match, _match_init\r
+\r
+\r
+;SECTION    .text\r
+\r
+;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)\r
+\r
+;_longest_match:\r
+IFDEF NOOLDPENTIUMCODE\r
+    IFDEF NOUNDERLINE\r
+    longest_match       proc near\r
+    ELSE\r
+    _longest_match      proc near\r
+    ENDIF\r
+ELSE\r
+    IFDEF NOUNDERLINE\r
+    longest_match_686   proc near\r
+    ELSE\r
+    _longest_match_686  proc near\r
+    ENDIF\r
+ENDIF\r
+\r
+;;; Save registers that the compiler may be using, and adjust esp to\r
+;;; make room for our stack frame.\r
+\r
+        push    ebp\r
+        push    edi\r
+        push    esi\r
+        push    ebx\r
+        sub esp, LocalVarsSize\r
+\r
+;;; Retrieve the function arguments. ecx will hold cur_match\r
+;;; throughout the entire function. edx will hold the pointer to the\r
+;;; deflate_state structure during the function's setup (before\r
+;;; entering the main loop.\r
+\r
+        mov edx, [deflatestate]\r
+        mov ecx, [curmatch]\r
+\r
+;;; uInt wmask = s->w_mask;\r
+;;; unsigned chain_length = s->max_chain_length;\r
+;;; if (s->prev_length >= s->good_match) {\r
+;;;     chain_length >>= 2;\r
+;;; }\r
+\r
+        mov eax, [edx + dsPrevLen]\r
+        mov ebx, [edx + dsGoodMatch]\r
+        cmp eax, ebx\r
+        mov eax, [edx + dsWMask]\r
+        mov ebx, [edx + dsMaxChainLen]\r
+        jl  LastMatchGood\r
+        shr ebx, 2\r
+LastMatchGood:\r
+\r
+;;; chainlen is decremented once beforehand so that the function can\r
+;;; use the sign flag instead of the zero flag for the exit test.\r
+;;; It is then shifted into the high word, to make room for the wmask\r
+;;; value, which it will always accompany.\r
+\r
+        dec ebx\r
+        shl ebx, 16\r
+        or  ebx, eax\r
+        mov [chainlenwmask], ebx\r
+\r
+;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\r
+\r
+        mov eax, [edx + dsNiceMatch]\r
+        mov ebx, [edx + dsLookahead]\r
+        cmp ebx, eax\r
+        jl  LookaheadLess\r
+        mov ebx, eax\r
+LookaheadLess:  mov [nicematch], ebx\r
+\r
+;;; register Bytef *scan = s->window + s->strstart;\r
+\r
+        mov esi, [edx + dsWindow]\r
+        mov [window], esi\r
+        mov ebp, [edx + dsStrStart]\r
+        lea edi, [esi + ebp]\r
+        mov [scan], edi\r
+\r
+;;; Determine how many bytes the scan ptr is off from being\r
+;;; dword-aligned.\r
+\r
+        mov eax, edi\r
+        neg eax\r
+        and eax, 3\r
+        mov [scanalign], eax\r
+\r
+;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\r
+;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;\r
+\r
+        mov eax, [edx + dsWSize]\r
+        sub eax, MIN_LOOKAHEAD\r
+        sub ebp, eax\r
+        jg  LimitPositive\r
+        xor ebp, ebp\r
+LimitPositive:\r
+\r
+;;; int best_len = s->prev_length;\r
+\r
+        mov eax, [edx + dsPrevLen]\r
+        mov [bestlen], eax\r
+\r
+;;; Store the sum of s->window + best_len in esi locally, and in esi.\r
+\r
+        add esi, eax\r
+        mov [windowbestlen], esi\r
+\r
+;;; register ush scan_start = *(ushf*)scan;\r
+;;; register ush scan_end   = *(ushf*)(scan+best_len-1);\r
+;;; Posf *prev = s->prev;\r
+\r
+        movzx   ebx, word ptr [edi]\r
+        mov [scanstart], ebx\r
+        movzx   ebx, word ptr [edi + eax - 1]\r
+        mov [scanend], ebx\r
+        mov edi, [edx + dsPrev]\r
+\r
+;;; Jump into the main loop.\r
+\r
+        mov edx, [chainlenwmask]\r
+        jmp short LoopEntry\r
+\r
+align 4\r
+\r
+;;; do {\r
+;;;     match = s->window + cur_match;\r
+;;;     if (*(ushf*)(match+best_len-1) != scan_end ||\r
+;;;         *(ushf*)match != scan_start) continue;\r
+;;;     [...]\r
+;;; } while ((cur_match = prev[cur_match & wmask]) > limit\r
+;;;          && --chain_length != 0);\r
+;;;\r
+;;; Here is the inner loop of the function. The function will spend the\r
+;;; majority of its time in this loop, and majority of that time will\r
+;;; be spent in the first ten instructions.\r
+;;;\r
+;;; Within this loop:\r
+;;; ebx = scanend\r
+;;; ecx = curmatch\r
+;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)\r
+;;; esi = windowbestlen - i.e., (window + bestlen)\r
+;;; edi = prev\r
+;;; ebp = limit\r
+\r
+LookupLoop:\r
+        and ecx, edx\r
+        movzx   ecx, word ptr [edi + ecx*2]\r
+        cmp ecx, ebp\r
+        jbe LeaveNow\r
+        sub edx, 00010000h\r
+        js  LeaveNow\r
+LoopEntry:  movzx   eax, word ptr [esi + ecx - 1]\r
+        cmp eax, ebx\r
+        jnz LookupLoop\r
+        mov eax, [window]\r
+        movzx   eax, word ptr [eax + ecx]\r
+        cmp eax, [scanstart]\r
+        jnz LookupLoop\r
+\r
+;;; Store the current value of chainlen.\r
+\r
+        mov [chainlenwmask], edx\r
+\r
+;;; Point edi to the string under scrutiny, and esi to the string we\r
+;;; are hoping to match it up with. In actuality, esi and edi are\r
+;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is\r
+;;; initialized to -(MAX_MATCH_8 - scanalign).\r
+\r
+        mov esi, [window]\r
+        mov edi, [scan]\r
+        add esi, ecx\r
+        mov eax, [scanalign]\r
+        mov edx, 0fffffef8h; -(MAX_MATCH_8)\r
+        lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]\r
+        lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]\r
+\r
+;;; Test the strings for equality, 8 bytes at a time. At the end,\r
+;;; adjust edx so that it is offset to the exact byte that mismatched.\r
+;;;\r
+;;; We already know at this point that the first three bytes of the\r
+;;; strings match each other, and they can be safely passed over before\r
+;;; starting the compare loop. So what this code does is skip over 0-3\r
+;;; bytes, as much as necessary in order to dword-align the edi\r
+;;; pointer. (esi will still be misaligned three times out of four.)\r
+;;;\r
+;;; It should be confessed that this loop usually does not represent\r
+;;; much of the total running time. Replacing it with a more\r
+;;; straightforward "rep cmpsb" would not drastically degrade\r
+;;; performance.\r
+\r
+LoopCmps:\r
+        mov eax, [esi + edx]\r
+        xor eax, [edi + edx]\r
+        jnz LeaveLoopCmps\r
+        mov eax, [esi + edx + 4]\r
+        xor eax, [edi + edx + 4]\r
+        jnz LeaveLoopCmps4\r
+        add edx, 8\r
+        jnz LoopCmps\r
+        jmp short LenMaximum\r
+LeaveLoopCmps4: add edx, 4\r
+LeaveLoopCmps:  test    eax, 0000FFFFh\r
+        jnz LenLower\r
+        add edx,  2\r
+        shr eax, 16\r
+LenLower:   sub al, 1\r
+        adc edx, 0\r
+\r
+;;; Calculate the length of the match. If it is longer than MAX_MATCH,\r
+;;; then automatically accept it as the best possible match and leave.\r
+\r
+        lea eax, [edi + edx]\r
+        mov edi, [scan]\r
+        sub eax, edi\r
+        cmp eax, MAX_MATCH\r
+        jge LenMaximum\r
+\r
+;;; If the length of the match is not longer than the best match we\r
+;;; have so far, then forget it and return to the lookup loop.\r
+\r
+        mov edx, [deflatestate]\r
+        mov ebx, [bestlen]\r
+        cmp eax, ebx\r
+        jg  LongerMatch\r
+        mov esi, [windowbestlen]\r
+        mov edi, [edx + dsPrev]\r
+        mov ebx, [scanend]\r
+        mov edx, [chainlenwmask]\r
+        jmp LookupLoop\r
+\r
+;;;         s->match_start = cur_match;\r
+;;;         best_len = len;\r
+;;;         if (len >= nice_match) break;\r
+;;;         scan_end = *(ushf*)(scan+best_len-1);\r
+\r
+LongerMatch:    mov ebx, [nicematch]\r
+        mov [bestlen], eax\r
+        mov [edx + dsMatchStart], ecx\r
+        cmp eax, ebx\r
+        jge LeaveNow\r
+        mov esi, [window]\r
+        add esi, eax\r
+        mov [windowbestlen], esi\r
+        movzx   ebx, word ptr [edi + eax - 1]\r
+        mov edi, [edx + dsPrev]\r
+        mov [scanend], ebx\r
+        mov edx, [chainlenwmask]\r
+        jmp LookupLoop\r
+\r
+;;; Accept the current string, with the maximum possible length.\r
+\r
+LenMaximum: mov edx, [deflatestate]\r
+        mov dword ptr [bestlen], MAX_MATCH\r
+        mov [edx + dsMatchStart], ecx\r
+\r
+;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;\r
+;;; return s->lookahead;\r
+\r
+LeaveNow:\r
+        mov edx, [deflatestate]\r
+        mov ebx, [bestlen]\r
+        mov eax, [edx + dsLookahead]\r
+        cmp ebx, eax\r
+        jg  LookaheadRet\r
+        mov eax, ebx\r
+LookaheadRet:\r
+\r
+;;; Restore the stack and return from whence we came.\r
+\r
+        add esp, LocalVarsSize\r
+        pop ebx\r
+        pop esi\r
+        pop edi\r
+        pop ebp\r
+\r
+        ret\r
+; please don't remove this string !\r
+; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!\r
+    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah\r
+\r
+\r
+IFDEF NOOLDPENTIUMCODE\r
+    IFDEF NOUNDERLINE\r
+    longest_match       endp\r
+    ELSE\r
+    _longest_match      endp\r
+    ENDIF\r
+\r
+    IFDEF NOUNDERLINE\r
+    match_init      proc near\r
+                    ret\r
+    match_init      endp\r
+    ELSE\r
+    _match_init     proc near\r
+                    ret\r
+    _match_init     endp\r
+    ENDIF    \r
+ELSE\r
+    IFDEF NOUNDERLINE\r
+    longest_match_686   endp\r
+    ELSE\r
+    _longest_match_686  endp\r
+    ENDIF\r
+ENDIF\r
+\r
+_TEXT   ends\r
+end\r
index 9ed25f3..7ad2b27 100644 (file)
-/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
- * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
- * File written by Gilles Vollant, by modifiying the longest_match
- *  from Jean-loup Gailly in deflate.c
- *  it prepare all parameters and call the assembly longest_match_gvasm
- *  longest_match execute standard C code is wmask != 0x7fff
- *     (assembly code is faster with a fixed wmask)
- *
- */
-
-#include "deflate.h"
-
-#ifdef ASMV
-#define NIL 0
-
-#define UNALIGNED_OK
-
-
-/* if your C compiler don't add underline before function name,
-        define ADD_UNDERLINE_ASMFUNC */
-#ifdef ADD_UNDERLINE_ASMFUNC
-#define longest_match_7fff _longest_match_7fff
-#define longest_match_686  _longest_match_686
-#define cpudetect32        _cpudetect32
-#endif
-
-
-
-void match_init()
-{
-}
-
-unsigned long cpudetect32();
-
-uInt longest_match_c(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-
-uInt longest_match_7fff(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-uInt longest_match_686(
-    deflate_state *s,
-    IPos cur_match);                             /* current match */
-
-uInt longest_match(
-    deflate_state *s,
-    IPos cur_match)                             /* current match */
-{
-    static uInt iIsPPro=2;
-
-    if ((s->w_mask == 0x7fff) && (iIsPPro==0))
-        return longest_match_7fff(s,cur_match);
-
-    if (iIsPPro==1)
-        return longest_match_686(s,cur_match);
-
-    if (iIsPPro==2)
-        iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
-
-    return longest_match_c(s,cur_match);
-}
-
-
-
-uInt longest_match_c(s, cur_match)
-    deflate_state *s;
-    IPos cur_match;                             /* current match */
-{
-    unsigned chain_length = s->max_chain_length;/* max hash chain length */
-    register Bytef *scan = s->window + s->strstart; /* current string */
-    register Bytef *match;                       /* matched string */
-    register int len;                           /* length of current match */
-    int best_len = s->prev_length;              /* best match length so far */
-    int nice_match = s->nice_match;             /* stop if match long enough */
-    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
-        s->strstart - (IPos)MAX_DIST(s) : NIL;
-    /* Stop when cur_match becomes <= limit. To simplify the code,
-     * we prevent matches with the string of window index 0.
-     */
-    Posf *prev = s->prev;
-    uInt wmask = s->w_mask;
-
-#ifdef UNALIGNED_OK
-    /* Compare two bytes at a time. Note: this is not always beneficial.
-     * Try with and without -DUNALIGNED_OK to check.
-     */
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
-    register ush scan_start = *(ushf*)scan;
-    register ush scan_end   = *(ushf*)(scan+best_len-1);
-#else
-    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
-    register Byte scan_end1  = scan[best_len-1];
-    register Byte scan_end   = scan[best_len];
-#endif
-
-    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
-     * It is easy to get rid of this optimization if necessary.
-     */
-    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
-    /* Do not waste too much time if we already have a good match: */
-    if (s->prev_length >= s->good_match) {
-        chain_length >>= 2;
-    }
-    /* Do not look for matches beyond the end of the input. This is necessary
-     * to make deflate deterministic.
-     */
-    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
-
-    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
-    do {
-        Assert(cur_match < s->strstart, "no future");
-        match = s->window + cur_match;
-
-        /* Skip to next match if the match length cannot increase
-         * or if the match length is less than 2:
-         */
-#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
-        /* This code assumes sizeof(unsigned short) == 2. Do not use
-         * UNALIGNED_OK if your compiler uses a different size.
-         */
-        if (*(ushf*)(match+best_len-1) != scan_end ||
-            *(ushf*)match != scan_start) continue;
-
-        /* It is not necessary to compare scan[2] and match[2] since they are
-         * always equal when the other bytes match, given that the hash keys
-         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
-         * strstart+3, +5, ... up to strstart+257. We check for insufficient
-         * lookahead only every 4th comparison; the 128th check will be made
-         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
-         * necessary to put more guard bytes at the end of the window, or
-         * to check more often for insufficient lookahead.
-         */
-        Assert(scan[2] == match[2], "scan[2]?");
-        scan++, match++;
-        do {
-        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
-                 scan < strend);
-        /* The funny "do {}" generates better code on most compilers */
-
-        /* Here, scan <= window+strstart+257 */
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-        if (*scan == *match) scan++;
-
-        len = (MAX_MATCH - 1) - (int)(strend-scan);
-        scan = strend - (MAX_MATCH-1);
-
-#else /* UNALIGNED_OK */
-
-        if (match[best_len]   != scan_end  ||
-            match[best_len-1] != scan_end1 ||
-            *match            != *scan     ||
-            *++match          != scan[1])      continue;
-
-        /* The check at best_len-1 can be removed because it will be made
-         * again later. (This heuristic is not always a win.)
-         * It is not necessary to compare scan[2] and match[2] since they
-         * are always equal when the other bytes match, given that
-         * the hash keys are equal and that HASH_BITS >= 8.
-         */
-        scan += 2, match++;
-        Assert(*scan == *match, "match[2]?");
-
-        /* We check for insufficient lookahead only every 8th comparison;
-         * the 256th check will be made at strstart+258.
-         */
-        do {
-        } while (*++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 *++scan == *++match && *++scan == *++match &&
-                 scan < strend);
-
-        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
-        len = MAX_MATCH - (int)(strend - scan);
-        scan = strend - MAX_MATCH;
-
-#endif /* UNALIGNED_OK */
-
-        if (len > best_len) {
-            s->match_start = cur_match;
-            best_len = len;
-            if (len >= nice_match) break;
-#ifdef UNALIGNED_OK
-            scan_end = *(ushf*)(scan+best_len-1);
-#else
-            scan_end1  = scan[best_len-1];
-            scan_end   = scan[best_len];
-#endif
-        }
-    } while ((cur_match = prev[cur_match & wmask]) > limit
-             && --chain_length != 0);
-
-    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
-    return s->lookahead;
-}
-
-#endif /* ASMV */
+/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86\r
+ * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.\r
+ * File written by Gilles Vollant, by modifiying the longest_match\r
+ *  from Jean-loup Gailly in deflate.c\r
+ *  it prepare all parameters and call the assembly longest_match_gvasm\r
+ *  longest_match execute standard C code is wmask != 0x7fff\r
+ *     (assembly code is faster with a fixed wmask)\r
+ *\r
+ * Read comment at beginning of gvmat32.asm for more information\r
+ */\r
+\r
+#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))\r
+#include "deflate.h"\r
+\r
+/* if your C compiler don't add underline before function name,\r
+        define ADD_UNDERLINE_ASMFUNC */\r
+#ifdef ADD_UNDERLINE_ASMFUNC\r
+#define longest_match_7fff _longest_match_7fff\r
+#define longest_match_686  _longest_match_686\r
+#define cpudetect32        _cpudetect32\r
+#endif\r
+\r
+\r
+unsigned long cpudetect32();\r
+\r
+uInt longest_match_c(\r
+    deflate_state *s,\r
+    IPos cur_match);                             /* current match */\r
+\r
+\r
+uInt longest_match_7fff(\r
+    deflate_state *s,\r
+    IPos cur_match);                             /* current match */\r
+\r
+uInt longest_match_686(\r
+    deflate_state *s,\r
+    IPos cur_match);                             /* current match */\r
+\r
+\r
+static uInt iIsPPro=2;\r
+\r
+void match_init ()\r
+{\r
+    iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;\r
+}\r
+\r
+uInt longest_match(\r
+    deflate_state *s,\r
+    IPos cur_match)                             /* current match */\r
+{\r
+    if (iIsPPro!=0)\r
+        return longest_match_686(s,cur_match);\r
+\r
+    if (s->w_mask != 0x7fff)\r
+        return longest_match_686(s,cur_match);\r
+\r
+    /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */\r
+        return longest_match_7fff(s,cur_match);\r
+}\r
+\r
+\r
+#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */\r
index 7d76e1c..4a20512 100644 (file)
-; 75 "inffast.S"
-;FILE "inffast.S"
-
-;;;GLOBAL _inflate_fast
-
-;;;SECTION .text
-
-
-
-       .586p
-       .mmx
-
-       name    inflate_fast_x86
-       .MODEL  FLAT
-
-_DATA                  segment
-inflate_fast_use_mmx:
-       dd      1
-
-
-_TEXT                  segment
-PUBLIC _inflate_fast
-
-ALIGN 4
-_inflate_fast:
-       jmp inflate_fast_entry
-
-
-
-ALIGN 4
-       db      'Fast decoding Code from Chris Anderson'
-       db      0
-
-ALIGN 4
-invalid_literal_length_code_msg:
-       db      'invalid literal/length code'
-       db      0
-
-ALIGN 4
-invalid_distance_code_msg:
-       db      'invalid distance code'
-       db      0
-
-ALIGN 4
-invalid_distance_too_far_msg:
-       db      'invalid distance too far back'
-       db      0
-
-
-ALIGN 4
-inflate_fast_mask:
-dd     0
-dd     1
-dd     3
-dd     7
-dd     15
-dd     31
-dd     63
-dd     127
-dd     255
-dd     511
-dd     1023
-dd     2047
-dd     4095
-dd     8191
-dd     16383
-dd     32767
-dd     65535
-dd     131071
-dd     262143
-dd     524287
-dd     1048575
-dd     2097151
-dd     4194303
-dd     8388607
-dd     16777215
-dd     33554431
-dd     67108863
-dd     134217727
-dd     268435455
-dd     536870911
-dd     1073741823
-dd     2147483647
-dd     4294967295
-
-
-
-mode_state      equ    0       ;/* state->mode */
-wsize_state     equ    32      ;/* state->wsize */
-write_state     equ    (36+4)  ;/* state->write */
-window_state    equ    (40+4)  ;/* state->window */
-hold_state      equ    (44+4)  ;/* state->hold */
-bits_state      equ    (48+4)  ;/* state->bits */
-lencode_state   equ    (64+4)  ;/* state->lencode */
-distcode_state  equ    (68+4)  ;/* state->distcode */
-lenbits_state   equ    (72+4)  ;/* state->lenbits */
-distbits_state  equ    (76+4)  ;/* state->distbits */
-
-
-;;SECTION .text
-; 205 "inffast.S"
-;GLOBAL        inflate_fast_use_mmx
-
-;SECTION .data
-
-
-; GLOBAL inflate_fast_use_mmx:object
-;.size inflate_fast_use_mmx, 4
-; 226 "inffast.S"
-;SECTION .text
-
-ALIGN 4
-inflate_fast_entry:
-       push  edi
-       push  esi
-       push  ebp
-       push  ebx
-       pushfd
-       sub  esp,64
-       cld
-
-
-
-
-       mov  esi, [esp+88]
-       mov  edi, [esi+28]
-
-
-
-
-
-
-
-       mov  edx, [esi+4]
-       mov  eax, [esi+0]
-
-       add  edx,eax
-       sub  edx,11
-
-       mov  [esp+44],eax
-       mov  [esp+20],edx
-
-       mov  ebp, [esp+92]
-       mov  ecx, [esi+16]
-       mov  ebx, [esi+12]
-
-       sub  ebp,ecx
-       neg  ebp
-       add  ebp,ebx
-
-       sub  ecx,257
-       add  ecx,ebx
-
-       mov  [esp+60],ebx
-       mov  [esp+40],ebp
-       mov  [esp+16],ecx
-; 285 "inffast.S"
-       mov  eax, [edi+lencode_state]
-       mov  ecx, [edi+distcode_state]
-
-       mov  [esp+8],eax
-       mov  [esp+12],ecx
-
-       mov  eax,1
-       mov  ecx, [edi+lenbits_state]
-       shl  eax,cl
-       dec  eax
-       mov  [esp+0],eax
-
-       mov  eax,1
-       mov  ecx, [edi+distbits_state]
-       shl  eax,cl
-       dec  eax
-       mov  [esp+4],eax
-
-       mov  eax, [edi+wsize_state]
-       mov  ecx, [edi+write_state]
-       mov  edx, [edi+window_state]
-
-       mov  [esp+52],eax
-       mov  [esp+48],ecx
-       mov  [esp+56],edx
-
-       mov  ebp, [edi+hold_state]
-       mov  ebx, [edi+bits_state]
-; 321 "inffast.S"
-       mov  esi, [esp+44]
-       mov  ecx, [esp+20]
-       cmp  ecx,esi
-       ja   L_align_long
-
-       add  ecx,11
-       sub  ecx,esi
-       mov  eax,12
-       sub  eax,ecx
-       lea  edi, [esp+28]
-       rep movsb
-       mov  ecx,eax
-       xor  eax,eax
-       rep stosb
-       lea  esi, [esp+28]
-       mov  [esp+20],esi
-       jmp  L_is_aligned
-
-
-L_align_long:
-       test  esi,3
-       jz   L_is_aligned
-       xor  eax,eax
-       mov  al, [esi]
-       inc  esi
-       mov  ecx,ebx
-       add  ebx,8
-       shl  eax,cl
-       or  ebp,eax
-       jmp L_align_long
-
-L_is_aligned:
-       mov  edi, [esp+60]
-; 366 "inffast.S"
-L_check_mmx:
-       cmp  dword ptr [inflate_fast_use_mmx],2
-       je   L_init_mmx
-       ja   L_do_loop
-
-       push  eax
-       push  ebx
-       push  ecx
-       push  edx
-       pushfd
-       mov  eax, [esp]
-       xor  dword ptr [esp],0200000h
-
-
-
-
-       popfd
-       pushfd
-       pop  edx
-       xor  edx,eax
-       jz   L_dont_use_mmx
-       xor  eax,eax
-       cpuid
-       cmp  ebx,0756e6547h
-       jne  L_dont_use_mmx
-       cmp  ecx,06c65746eh
-       jne  L_dont_use_mmx
-       cmp  edx,049656e69h
-       jne  L_dont_use_mmx
-       mov  eax,1
-       cpuid
-       shr  eax,8
-       and  eax,15
-       cmp  eax,6
-       jne  L_dont_use_mmx
-       test  edx,0800000h
-       jnz  L_use_mmx
-       jmp  L_dont_use_mmx
-L_use_mmx:
-       mov  dword ptr [inflate_fast_use_mmx],2
-       jmp  L_check_mmx_pop
-L_dont_use_mmx:
-       mov  dword ptr [inflate_fast_use_mmx],3
-L_check_mmx_pop:
-       pop  edx
-       pop  ecx
-       pop  ebx
-       pop  eax
-       jmp  L_check_mmx
-; 426 "inffast.S"
-ALIGN 4
-L_do_loop:
-; 437 "inffast.S"
-       cmp  bl,15
-       ja   L_get_length_code
-
-       xor  eax,eax
-       lodsw
-       mov  cl,bl
-       add  bl,16
-       shl  eax,cl
-       or  ebp,eax
-
-L_get_length_code:
-       mov  edx, [esp+0]
-       mov  ecx, [esp+8]
-       and  edx,ebp
-       mov  eax, [ecx+edx*4]
-
-L_dolen:
-
-
-
-
-
-
-       mov  cl,ah
-       sub  bl,ah
-       shr  ebp,cl
-
-
-
-
-
-
-       test  al,al
-       jnz   L_test_for_length_base
-
-       shr  eax,16
-       stosb
-
-L_while_test:
-
-
-       cmp  [esp+16],edi
-       jbe  L_break_loop
-
-       cmp  [esp+20],esi
-       ja   L_do_loop
-       jmp  L_break_loop
-
-L_test_for_length_base:
-; 502 "inffast.S"
-       mov  edx,eax
-       shr  edx,16
-       mov  cl,al
-
-       test  al,16
-       jz   L_test_for_second_level_length
-       and  cl,15
-       jz   L_save_len
-       cmp  bl,cl
-       jae  L_add_bits_to_len
-
-       mov  ch,cl
-       xor  eax,eax
-       lodsw
-       mov  cl,bl
-       add  bl,16
-       shl  eax,cl
-       or  ebp,eax
-       mov  cl,ch
-
-L_add_bits_to_len:
-       mov  eax,1
-       shl  eax,cl
-       dec  eax
-       sub  bl,cl
-       and  eax,ebp
-       shr  ebp,cl
-       add  edx,eax
-
-L_save_len:
-       mov  [esp+24],edx
-
-
-L_decode_distance:
-; 549 "inffast.S"
-       cmp  bl,15
-       ja   L_get_distance_code
-
-       xor  eax,eax
-       lodsw
-       mov  cl,bl
-       add  bl,16
-       shl  eax,cl
-       or  ebp,eax
-
-L_get_distance_code:
-       mov  edx, [esp+4]
-       mov  ecx, [esp+12]
-       and  edx,ebp
-       mov  eax, [ecx+edx*4]
-
-
-L_dodist:
-       mov  edx,eax
-       shr  edx,16
-       mov  cl,ah
-       sub  bl,ah
-       shr  ebp,cl
-; 584 "inffast.S"
-       mov  cl,al
-
-       test  al,16
-       jz  L_test_for_second_level_dist
-       and  cl,15
-       jz  L_check_dist_one
-       cmp  bl,cl
-       jae  L_add_bits_to_dist
-
-       mov  ch,cl
-       xor  eax,eax
-       lodsw
-       mov  cl,bl
-       add  bl,16
-       shl  eax,cl
-       or  ebp,eax
-       mov  cl,ch
-
-L_add_bits_to_dist:
-       mov  eax,1
-       shl  eax,cl
-       dec  eax
-       sub  bl,cl
-       and  eax,ebp
-       shr  ebp,cl
-       add  edx,eax
-       jmp  L_check_window
-
-L_check_window:
-; 625 "inffast.S"
-       mov  [esp+44],esi
-       mov  eax,edi
-       sub  eax, [esp+40]
-
-       cmp  eax,edx
-       jb   L_clip_window
-
-       mov  ecx, [esp+24]
-       mov  esi,edi
-       sub  esi,edx
-
-       sub  ecx,3
-       mov  al, [esi]
-       mov  [edi],al
-       mov  al, [esi+1]
-       mov  dl, [esi+2]
-       add  esi,3
-       mov  [edi+1],al
-       mov  [edi+2],dl
-       add  edi,3
-       rep movsb
-
-       mov  esi, [esp+44]
-       jmp  L_while_test
-
-ALIGN 4
-L_check_dist_one:
-       cmp  edx,1
-       jne  L_check_window
-       cmp  [esp+40],edi
-       je  L_check_window
-
-       dec  edi
-       mov  ecx, [esp+24]
-       mov  al, [edi]
-       sub  ecx,3
-
-       mov  [edi+1],al
-       mov  [edi+2],al
-       mov  [edi+3],al
-       add  edi,4
-       rep stosb
-
-       jmp  L_while_test
-
-ALIGN 4
-L_test_for_second_level_length:
-
-
-
-
-       test  al,64
-       jnz   L_test_for_end_of_block
-
-       mov  eax,1
-       shl  eax,cl
-       dec  eax
-       and  eax,ebp
-       add  eax,edx
-       mov  edx, [esp+8]
-       mov  eax, [edx+eax*4]
-       jmp  L_dolen
-
-ALIGN 4
-L_test_for_second_level_dist:
-
-
-
-
-       test  al,64
-       jnz   L_invalid_distance_code
-
-       mov  eax,1
-       shl  eax,cl
-       dec  eax
-       and  eax,ebp
-       add  eax,edx
-       mov  edx, [esp+12]
-       mov  eax, [edx+eax*4]
-       jmp  L_dodist
-
-ALIGN 4
-L_clip_window:
-; 721 "inffast.S"
-       mov  ecx,eax
-       mov  eax, [esp+52]
-       neg  ecx
-       mov  esi, [esp+56]
-
-       cmp  eax,edx
-       jb   L_invalid_distance_too_far
-
-       add  ecx,edx
-       cmp  dword ptr [esp+48],0
-       jne  L_wrap_around_window
-
-       sub  eax,ecx
-       add  esi,eax
-; 749 "inffast.S"
-       mov  eax, [esp+24]
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,edx
-       jmp  L_do_copy1
-
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,edx
-       jmp  L_do_copy1
-
-L_wrap_around_window:
-; 793 "inffast.S"
-       mov  eax, [esp+48]
-       cmp  ecx,eax
-       jbe  L_contiguous_in_window
-
-       add  esi, [esp+52]
-       add  esi,eax
-       sub  esi,ecx
-       sub  ecx,eax
-
-
-       mov  eax, [esp+24]
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi, [esp+56]
-       mov  ecx, [esp+48]
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,edx
-       jmp  L_do_copy1
-
-L_contiguous_in_window:
-; 836 "inffast.S"
-       add  esi,eax
-       sub  esi,ecx
-
-
-       mov  eax, [esp+24]
-       cmp  eax,ecx
-       jbe  L_do_copy1
-
-       sub  eax,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,edx
-
-L_do_copy1:
-; 862 "inffast.S"
-       mov  ecx,eax
-       rep movsb
-
-       mov  esi, [esp+44]
-       jmp  L_while_test
-; 878 "inffast.S"
-ALIGN 4
-L_init_mmx:
-       emms
-
-
-
-
-
-       movd mm0,ebp
-       mov  ebp,ebx
-; 896 "inffast.S"
-       movd mm4,[esp+0]
-       movq mm3,mm4
-       movd mm5,[esp+4]
-       movq mm2,mm5
-       pxor mm1,mm1
-       mov  ebx, [esp+8]
-       jmp  L_do_loop_mmx
-
-ALIGN 4
-L_do_loop_mmx:
-       psrlq mm0,mm1
-
-       cmp  ebp,32
-       ja  L_get_length_code_mmx
-
-       movd mm6,ebp
-       movd mm7,[esi]
-       add  esi,4
-       psllq mm7,mm6
-       add  ebp,32
-       por mm0,mm7
-
-L_get_length_code_mmx:
-       pand mm4,mm0
-       movd eax,mm4
-       movq mm4,mm3
-       mov  eax, [ebx+eax*4]
-
-L_dolen_mmx:
-       movzx  ecx,ah
-       movd mm1,ecx
-       sub  ebp,ecx
-
-       test  al,al
-       jnz L_test_for_length_base_mmx
-
-       shr  eax,16
-       stosb
-
-L_while_test_mmx:
-
-
-       cmp  [esp+16],edi
-       jbe L_break_loop
-
-       cmp  [esp+20],esi
-       ja L_do_loop_mmx
-       jmp L_break_loop
-
-L_test_for_length_base_mmx:
-
-       mov  edx,eax
-       shr  edx,16
-
-       test  al,16
-       jz  L_test_for_second_level_length_mmx
-       and  eax,15
-       jz L_decode_distance_mmx
-
-       psrlq mm0,mm1
-       movd mm1,eax
-       movd ecx,mm0
-       sub  ebp,eax
-       and  ecx, [inflate_fast_mask+eax*4]
-       add  edx,ecx
-
-L_decode_distance_mmx:
-       psrlq mm0,mm1
-
-       cmp  ebp,32
-       ja L_get_dist_code_mmx
-
-       movd mm6,ebp
-       movd mm7,[esi]
-       add  esi,4
-       psllq mm7,mm6
-       add  ebp,32
-       por mm0,mm7
-
-L_get_dist_code_mmx:
-       mov  ebx, [esp+12]
-       pand mm5,mm0
-       movd eax,mm5
-       movq mm5,mm2
-       mov  eax, [ebx+eax*4]
-
-L_dodist_mmx:
-
-       movzx  ecx,ah
-       mov  ebx,eax
-       shr  ebx,16
-       sub  ebp,ecx
-       movd mm1,ecx
-
-       test  al,16
-       jz L_test_for_second_level_dist_mmx
-       and  eax,15
-       jz L_check_dist_one_mmx
-
-L_add_bits_to_dist_mmx:
-       psrlq mm0,mm1
-       movd mm1,eax
-       movd ecx,mm0
-       sub  ebp,eax
-       and  ecx, [inflate_fast_mask+eax*4]
-       add  ebx,ecx
-
-L_check_window_mmx:
-       mov  [esp+44],esi
-       mov  eax,edi
-       sub  eax, [esp+40]
-
-       cmp  eax,ebx
-       jb L_clip_window_mmx
-
-       mov  ecx,edx
-       mov  esi,edi
-       sub  esi,ebx
-
-       sub  ecx,3
-       mov  al, [esi]
-       mov  [edi],al
-       mov  al, [esi+1]
-       mov  dl, [esi+2]
-       add  esi,3
-       mov  [edi+1],al
-       mov  [edi+2],dl
-       add  edi,3
-       rep movsb
-
-       mov  esi, [esp+44]
-       mov  ebx, [esp+8]
-       jmp  L_while_test_mmx
-
-ALIGN 4
-L_check_dist_one_mmx:
-       cmp  ebx,1
-       jne  L_check_window_mmx
-       cmp  [esp+40],edi
-       je   L_check_window_mmx
-
-       dec  edi
-       mov  ecx,edx
-       mov  al, [edi]
-       sub  ecx,3
-
-       mov  [edi+1],al
-       mov  [edi+2],al
-       mov  [edi+3],al
-       add  edi,4
-       rep stosb
-
-       mov  ebx, [esp+8]
-       jmp  L_while_test_mmx
-
-ALIGN 4
-L_test_for_second_level_length_mmx:
-       test  al,64
-       jnz L_test_for_end_of_block
-
-       and  eax,15
-       psrlq mm0,mm1
-       movd ecx,mm0
-       and  ecx, [inflate_fast_mask+eax*4]
-       add  ecx,edx
-       mov  eax, [ebx+ecx*4]
-       jmp L_dolen_mmx
-
-ALIGN 4
-L_test_for_second_level_dist_mmx:
-       test  al,64
-       jnz L_invalid_distance_code
-
-       and  eax,15
-       psrlq mm0,mm1
-       movd ecx,mm0
-       and  ecx, [inflate_fast_mask+eax*4]
-       mov  eax, [esp+12]
-       add  ecx,ebx
-       mov  eax, [eax+ecx*4]
-       jmp  L_dodist_mmx
-
-ALIGN 4
-L_clip_window_mmx:
-
-       mov  ecx,eax
-       mov  eax, [esp+52]
-       neg  ecx
-       mov  esi, [esp+56]
-
-       cmp  eax,ebx
-       jb  L_invalid_distance_too_far
-
-       add  ecx,ebx
-       cmp  dword ptr [esp+48],0
-       jne  L_wrap_around_window_mmx
-
-       sub  eax,ecx
-       add  esi,eax
-
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,ebx
-       jmp  L_do_copy1_mmx
-
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,ebx
-       jmp  L_do_copy1_mmx
-
-L_wrap_around_window_mmx:
-
-       mov  eax, [esp+48]
-       cmp  ecx,eax
-       jbe  L_contiguous_in_window_mmx
-
-       add  esi, [esp+52]
-       add  esi,eax
-       sub  esi,ecx
-       sub  ecx,eax
-
-
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi, [esp+56]
-       mov  ecx, [esp+48]
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,ebx
-       jmp  L_do_copy1_mmx
-
-L_contiguous_in_window_mmx:
-
-       add  esi,eax
-       sub  esi,ecx
-
-
-       cmp  edx,ecx
-       jbe  L_do_copy1_mmx
-
-       sub  edx,ecx
-       rep movsb
-       mov  esi,edi
-       sub  esi,ebx
-
-L_do_copy1_mmx:
-
-
-       mov  ecx,edx
-       rep movsb
-
-       mov  esi, [esp+44]
-       mov  ebx, [esp+8]
-       jmp  L_while_test_mmx
-; 1174 "inffast.S"
-L_invalid_distance_code:
-
-
-
-
-
-       mov  ecx, invalid_distance_code_msg
-       mov  edx,26
-       jmp  L_update_stream_state
-
-L_test_for_end_of_block:
-
-
-
-
-
-       test  al,32
-       jz  L_invalid_literal_length_code
-
-       mov  ecx,0
-       mov  edx,11
-       jmp  L_update_stream_state
-
-L_invalid_literal_length_code:
-
-
-
-
-
-       mov  ecx, invalid_literal_length_code_msg
-       mov  edx,26
-       jmp  L_update_stream_state
-
-L_invalid_distance_too_far:
-
-
-
-       mov  esi, [esp+44]
-       mov  ecx, invalid_distance_too_far_msg
-       mov  edx,26
-       jmp  L_update_stream_state
-
-L_update_stream_state:
-
-       mov  eax, [esp+88]
-       test  ecx,ecx
-       jz  L_skip_msg
-       mov  [eax+24],ecx
-L_skip_msg:
-       mov  eax, [eax+28]
-       mov  [eax+mode_state],edx
-       jmp  L_break_loop
-
-ALIGN 4
-L_break_loop:
-; 1243 "inffast.S"
-       cmp  dword ptr [inflate_fast_use_mmx],2
-       jne  L_update_next_in
-
-
-
-       mov  ebx,ebp
-
-L_update_next_in:
-; 1266 "inffast.S"
-       mov  eax, [esp+88]
-       mov  ecx,ebx
-       mov  edx, [eax+28]
-       shr  ecx,3
-       sub  esi,ecx
-       shl  ecx,3
-       sub  ebx,ecx
-       mov  [eax+12],edi
-       mov  [edx+bits_state],ebx
-       mov  ecx,ebx
-
-       lea  ebx, [esp+28]
-       cmp  [esp+20],ebx
-       jne  L_buf_not_used
-
-       sub  esi,ebx
-       mov  ebx, [eax+0]
-       mov  [esp+20],ebx
-       add  esi,ebx
-       mov  ebx, [eax+4]
-       sub  ebx,11
-       add  [esp+20],ebx
-
-L_buf_not_used:
-       mov  [eax+0],esi
-
-       mov  ebx,1
-       shl  ebx,cl
-       dec  ebx
-
-
-
-
-
-       cmp  dword ptr [inflate_fast_use_mmx],2
-       jne  L_update_hold
-
-
-
-       psrlq mm0,mm1
-       movd ebp,mm0
-
-       emms
-
-L_update_hold:
-
-
-
-       and  ebp,ebx
-       mov  [edx+hold_state],ebp
-
-
-
-
-       mov  ebx, [esp+20]
-       cmp  ebx,esi
-       jbe  L_last_is_smaller
-
-       sub  ebx,esi
-       add  ebx,11
-       mov  [eax+4],ebx
-       jmp  L_fixup_out
-L_last_is_smaller:
-       sub  esi,ebx
-       neg  esi
-       add  esi,11
-       mov  [eax+4],esi
-
-
-
-
-L_fixup_out:
-
-       mov  ebx, [esp+16]
-       cmp  ebx,edi
-       jbe  L_end_is_smaller
-
-       sub  ebx,edi
-       add  ebx,257
-       mov  [eax+16],ebx
-       jmp  L_done
-L_end_is_smaller:
-       sub  edi,ebx
-       neg  edi
-       add  edi,257
-       mov  [eax+16],edi
-
-
-
-
-
-L_done:
-       add  esp,64
-       popfd
-       pop  ebx
-       pop  ebp
-       pop  esi
-       pop  edi
-       ret
-
-
-
-
-_TEXT  ends
-end
+;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding\r
+; *\r
+; * inffas32.asm is derivated from inffas86.c, with translation of assembly code\r
+; *\r
+; * Copyright (C) 1995-2003 Mark Adler\r
+; * For conditions of distribution and use, see copyright notice in zlib.h\r
+; *\r
+; * Copyright (C) 2003 Chris Anderson <christop@charm.net>\r
+; * Please use the copyright conditions above.\r
+; *\r
+; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from\r
+; * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at\r
+; * the moment.  I have successfully compiled and tested this code with gcc2.96,\r
+; * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S\r
+; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX\r
+; * enabled.  I will attempt to merge the MMX code into this version.  Newer\r
+; * versions of this and inffast.S can be found at\r
+; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/\r
+; * \r
+; * 2005 : modification by Gilles Vollant\r
+; */\r
+; For Visual C++ 4.x and higher and ML 6.x and higher\r
+;   ml.exe is in directory \MASM611C of Win95 DDK\r
+;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm\r
+;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/\r
+;\r
+;\r
+;   compile with command line option\r
+;   ml  /coff /Zi /c /Flinffas32.lst inffas32.asm\r
+\r
+;   if you define NO_GZIP (see inflate.h), compile with\r
+;   ml  /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm\r
+\r
+\r
+; zlib122sup is 0 fort zlib 1.2.2.1 and lower\r
+; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head \r
+;        in inflate_state in inflate.h)\r
+zlib1222sup      equ    8\r
+\r
+\r
+IFDEF GUNZIP\r
+  INFLATE_MODE_TYPE    equ 11\r
+  INFLATE_MODE_BAD     equ 26\r
+ELSE\r
+  IFNDEF NO_GUNZIP\r
+    INFLATE_MODE_TYPE    equ 11\r
+    INFLATE_MODE_BAD     equ 26\r
+  ELSE\r
+    INFLATE_MODE_TYPE    equ 3\r
+    INFLATE_MODE_BAD     equ 17\r
+  ENDIF\r
+ENDIF\r
+\r
+\r
+; 75 "inffast.S"\r
+;FILE "inffast.S"\r
+\r
+;;;GLOBAL _inflate_fast\r
+\r
+;;;SECTION .text\r
+\r
+\r
+\r
+       .586p\r
+       .mmx\r
+\r
+       name    inflate_fast_x86\r
+       .MODEL  FLAT\r
+\r
+_DATA                  segment\r
+inflate_fast_use_mmx:\r
+       dd      1\r
+\r
+\r
+_TEXT                  segment\r
+PUBLIC _inflate_fast\r
+\r
+ALIGN 4\r
+_inflate_fast:\r
+       jmp inflate_fast_entry\r
+\r
+\r
+\r
+ALIGN 4\r
+       db      'Fast decoding Code from Chris Anderson'\r
+       db      0\r
+\r
+ALIGN 4\r
+invalid_literal_length_code_msg:\r
+       db      'invalid literal/length code'\r
+       db      0\r
+\r
+ALIGN 4\r
+invalid_distance_code_msg:\r
+       db      'invalid distance code'\r
+       db      0\r
+\r
+ALIGN 4\r
+invalid_distance_too_far_msg:\r
+       db      'invalid distance too far back'\r
+       db      0\r
+\r
+\r
+ALIGN 4\r
+inflate_fast_mask:\r
+dd     0\r
+dd     1\r
+dd     3\r
+dd     7\r
+dd     15\r
+dd     31\r
+dd     63\r
+dd     127\r
+dd     255\r
+dd     511\r
+dd     1023\r
+dd     2047\r
+dd     4095\r
+dd     8191\r
+dd     16383\r
+dd     32767\r
+dd     65535\r
+dd     131071\r
+dd     262143\r
+dd     524287\r
+dd     1048575\r
+dd     2097151\r
+dd     4194303\r
+dd     8388607\r
+dd     16777215\r
+dd     33554431\r
+dd     67108863\r
+dd     134217727\r
+dd     268435455\r
+dd     536870911\r
+dd     1073741823\r
+dd     2147483647\r
+dd     4294967295\r
+\r
+\r
+mode_state      equ    0       ;/* state->mode */\r
+wsize_state     equ    (32+zlib1222sup)        ;/* state->wsize */\r
+write_state     equ    (36+4+zlib1222sup)      ;/* state->write */\r
+window_state    equ    (40+4+zlib1222sup)      ;/* state->window */\r
+hold_state      equ    (44+4+zlib1222sup)      ;/* state->hold */\r
+bits_state      equ    (48+4+zlib1222sup)      ;/* state->bits */\r
+lencode_state   equ    (64+4+zlib1222sup)      ;/* state->lencode */\r
+distcode_state  equ    (68+4+zlib1222sup)      ;/* state->distcode */\r
+lenbits_state   equ    (72+4+zlib1222sup)      ;/* state->lenbits */\r
+distbits_state  equ    (76+4+zlib1222sup)      ;/* state->distbits */\r
+\r
+\r
+;;SECTION .text\r
+; 205 "inffast.S"\r
+;GLOBAL        inflate_fast_use_mmx\r
+\r
+;SECTION .data\r
+\r
+\r
+; GLOBAL inflate_fast_use_mmx:object\r
+;.size inflate_fast_use_mmx, 4\r
+; 226 "inffast.S"\r
+;SECTION .text\r
+\r
+ALIGN 4\r
+inflate_fast_entry:\r
+       push  edi\r
+       push  esi\r
+       push  ebp\r
+       push  ebx\r
+       pushfd\r
+       sub  esp,64\r
+       cld\r
+\r
+\r
+\r
+\r
+       mov  esi, [esp+88]\r
+       mov  edi, [esi+28]\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+       mov  edx, [esi+4]\r
+       mov  eax, [esi+0]\r
+\r
+       add  edx,eax\r
+       sub  edx,11\r
+\r
+       mov  [esp+44],eax\r
+       mov  [esp+20],edx\r
+\r
+       mov  ebp, [esp+92]\r
+       mov  ecx, [esi+16]\r
+       mov  ebx, [esi+12]\r
+\r
+       sub  ebp,ecx\r
+       neg  ebp\r
+       add  ebp,ebx\r
+\r
+       sub  ecx,257\r
+       add  ecx,ebx\r
+\r
+       mov  [esp+60],ebx\r
+       mov  [esp+40],ebp\r
+       mov  [esp+16],ecx\r
+; 285 "inffast.S"\r
+       mov  eax, [edi+lencode_state]\r
+       mov  ecx, [edi+distcode_state]\r
+\r
+       mov  [esp+8],eax\r
+       mov  [esp+12],ecx\r
+\r
+       mov  eax,1\r
+       mov  ecx, [edi+lenbits_state]\r
+       shl  eax,cl\r
+       dec  eax\r
+       mov  [esp+0],eax\r
+\r
+       mov  eax,1\r
+       mov  ecx, [edi+distbits_state]\r
+       shl  eax,cl\r
+       dec  eax\r
+       mov  [esp+4],eax\r
+\r
+       mov  eax, [edi+wsize_state]\r
+       mov  ecx, [edi+write_state]\r
+       mov  edx, [edi+window_state]\r
+\r
+       mov  [esp+52],eax\r
+       mov  [esp+48],ecx\r
+       mov  [esp+56],edx\r
+\r
+       mov  ebp, [edi+hold_state]\r
+       mov  ebx, [edi+bits_state]\r
+; 321 "inffast.S"\r
+       mov  esi, [esp+44]\r
+       mov  ecx, [esp+20]\r
+       cmp  ecx,esi\r
+       ja   L_align_long\r
+\r
+       add  ecx,11\r
+       sub  ecx,esi\r
+       mov  eax,12\r
+       sub  eax,ecx\r
+       lea  edi, [esp+28]\r
+       rep movsb\r
+       mov  ecx,eax\r
+       xor  eax,eax\r
+       rep stosb\r
+       lea  esi, [esp+28]\r
+       mov  [esp+20],esi\r
+       jmp  L_is_aligned\r
+\r
+\r
+L_align_long:\r
+       test  esi,3\r
+       jz   L_is_aligned\r
+       xor  eax,eax\r
+       mov  al, [esi]\r
+       inc  esi\r
+       mov  ecx,ebx\r
+       add  ebx,8\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+       jmp L_align_long\r
+\r
+L_is_aligned:\r
+       mov  edi, [esp+60]\r
+; 366 "inffast.S"\r
+L_check_mmx:\r
+       cmp  dword ptr [inflate_fast_use_mmx],2\r
+       je   L_init_mmx\r
+       ja   L_do_loop\r
+\r
+       push  eax\r
+       push  ebx\r
+       push  ecx\r
+       push  edx\r
+       pushfd\r
+       mov  eax, [esp]\r
+       xor  dword ptr [esp],0200000h\r
+\r
+\r
+\r
+\r
+       popfd\r
+       pushfd\r
+       pop  edx\r
+       xor  edx,eax\r
+       jz   L_dont_use_mmx\r
+       xor  eax,eax\r
+       cpuid\r
+       cmp  ebx,0756e6547h\r
+       jne  L_dont_use_mmx\r
+       cmp  ecx,06c65746eh\r
+       jne  L_dont_use_mmx\r
+       cmp  edx,049656e69h\r
+       jne  L_dont_use_mmx\r
+       mov  eax,1\r
+       cpuid\r
+       shr  eax,8\r
+       and  eax,15\r
+       cmp  eax,6\r
+       jne  L_dont_use_mmx\r
+       test  edx,0800000h\r
+       jnz  L_use_mmx\r
+       jmp  L_dont_use_mmx\r
+L_use_mmx:\r
+       mov  dword ptr [inflate_fast_use_mmx],2\r
+       jmp  L_check_mmx_pop\r
+L_dont_use_mmx:\r
+       mov  dword ptr [inflate_fast_use_mmx],3\r
+L_check_mmx_pop:\r
+       pop  edx\r
+       pop  ecx\r
+       pop  ebx\r
+       pop  eax\r
+       jmp  L_check_mmx\r
+; 426 "inffast.S"\r
+ALIGN 4\r
+L_do_loop:\r
+; 437 "inffast.S"\r
+       cmp  bl,15\r
+       ja   L_get_length_code\r
+\r
+       xor  eax,eax\r
+       lodsw\r
+       mov  cl,bl\r
+       add  bl,16\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+\r
+L_get_length_code:\r
+       mov  edx, [esp+0]\r
+       mov  ecx, [esp+8]\r
+       and  edx,ebp\r
+       mov  eax, [ecx+edx*4]\r
+\r
+L_dolen:\r
+\r
+\r
+\r
+\r
+\r
+\r
+       mov  cl,ah\r
+       sub  bl,ah\r
+       shr  ebp,cl\r
+\r
+\r
+\r
+\r
+\r
+\r
+       test  al,al\r
+       jnz   L_test_for_length_base\r
+\r
+       shr  eax,16\r
+       stosb\r
+\r
+L_while_test:\r
+\r
+\r
+       cmp  [esp+16],edi\r
+       jbe  L_break_loop\r
+\r
+       cmp  [esp+20],esi\r
+       ja   L_do_loop\r
+       jmp  L_break_loop\r
+\r
+L_test_for_length_base:\r
+; 502 "inffast.S"\r
+       mov  edx,eax\r
+       shr  edx,16\r
+       mov  cl,al\r
+\r
+       test  al,16\r
+       jz   L_test_for_second_level_length\r
+       and  cl,15\r
+       jz   L_save_len\r
+       cmp  bl,cl\r
+       jae  L_add_bits_to_len\r
+\r
+       mov  ch,cl\r
+       xor  eax,eax\r
+       lodsw\r
+       mov  cl,bl\r
+       add  bl,16\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+       mov  cl,ch\r
+\r
+L_add_bits_to_len:\r
+       mov  eax,1\r
+       shl  eax,cl\r
+       dec  eax\r
+       sub  bl,cl\r
+       and  eax,ebp\r
+       shr  ebp,cl\r
+       add  edx,eax\r
+\r
+L_save_len:\r
+       mov  [esp+24],edx\r
+\r
+\r
+L_decode_distance:\r
+; 549 "inffast.S"\r
+       cmp  bl,15\r
+       ja   L_get_distance_code\r
+\r
+       xor  eax,eax\r
+       lodsw\r
+       mov  cl,bl\r
+       add  bl,16\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+\r
+L_get_distance_code:\r
+       mov  edx, [esp+4]\r
+       mov  ecx, [esp+12]\r
+       and  edx,ebp\r
+       mov  eax, [ecx+edx*4]\r
+\r
+\r
+L_dodist:\r
+       mov  edx,eax\r
+       shr  edx,16\r
+       mov  cl,ah\r
+       sub  bl,ah\r
+       shr  ebp,cl\r
+; 584 "inffast.S"\r
+       mov  cl,al\r
+\r
+       test  al,16\r
+       jz  L_test_for_second_level_dist\r
+       and  cl,15\r
+       jz  L_check_dist_one\r
+       cmp  bl,cl\r
+       jae  L_add_bits_to_dist\r
+\r
+       mov  ch,cl\r
+       xor  eax,eax\r
+       lodsw\r
+       mov  cl,bl\r
+       add  bl,16\r
+       shl  eax,cl\r
+       or  ebp,eax\r
+       mov  cl,ch\r
+\r
+L_add_bits_to_dist:\r
+       mov  eax,1\r
+       shl  eax,cl\r
+       dec  eax\r
+       sub  bl,cl\r
+       and  eax,ebp\r
+       shr  ebp,cl\r
+       add  edx,eax\r
+       jmp  L_check_window\r
+\r
+L_check_window:\r
+; 625 "inffast.S"\r
+       mov  [esp+44],esi\r
+       mov  eax,edi\r
+       sub  eax, [esp+40]\r
+\r
+       cmp  eax,edx\r
+       jb   L_clip_window\r
+\r
+       mov  ecx, [esp+24]\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+\r
+       sub  ecx,3\r
+       mov  al, [esi]\r
+       mov  [edi],al\r
+       mov  al, [esi+1]\r
+       mov  dl, [esi+2]\r
+       add  esi,3\r
+       mov  [edi+1],al\r
+       mov  [edi+2],dl\r
+       add  edi,3\r
+       rep movsb\r
+\r
+       mov  esi, [esp+44]\r
+       jmp  L_while_test\r
+\r
+ALIGN 4\r
+L_check_dist_one:\r
+       cmp  edx,1\r
+       jne  L_check_window\r
+       cmp  [esp+40],edi\r
+       je  L_check_window\r
+\r
+       dec  edi\r
+       mov  ecx, [esp+24]\r
+       mov  al, [edi]\r
+       sub  ecx,3\r
+\r
+       mov  [edi+1],al\r
+       mov  [edi+2],al\r
+       mov  [edi+3],al\r
+       add  edi,4\r
+       rep stosb\r
+\r
+       jmp  L_while_test\r
+\r
+ALIGN 4\r
+L_test_for_second_level_length:\r
+\r
+\r
+\r
+\r
+       test  al,64\r
+       jnz   L_test_for_end_of_block\r
+\r
+       mov  eax,1\r
+       shl  eax,cl\r
+       dec  eax\r
+       and  eax,ebp\r
+       add  eax,edx\r
+       mov  edx, [esp+8]\r
+       mov  eax, [edx+eax*4]\r
+       jmp  L_dolen\r
+\r
+ALIGN 4\r
+L_test_for_second_level_dist:\r
+\r
+\r
+\r
+\r
+       test  al,64\r
+       jnz   L_invalid_distance_code\r
+\r
+       mov  eax,1\r
+       shl  eax,cl\r
+       dec  eax\r
+       and  eax,ebp\r
+       add  eax,edx\r
+       mov  edx, [esp+12]\r
+       mov  eax, [edx+eax*4]\r
+       jmp  L_dodist\r
+\r
+ALIGN 4\r
+L_clip_window:\r
+; 721 "inffast.S"\r
+       mov  ecx,eax\r
+       mov  eax, [esp+52]\r
+       neg  ecx\r
+       mov  esi, [esp+56]\r
+\r
+       cmp  eax,edx\r
+       jb   L_invalid_distance_too_far\r
+\r
+       add  ecx,edx\r
+       cmp  dword ptr [esp+48],0\r
+       jne  L_wrap_around_window\r
+\r
+       sub  eax,ecx\r
+       add  esi,eax\r
+; 749 "inffast.S"\r
+       mov  eax, [esp+24]\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+       jmp  L_do_copy1\r
+\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+       jmp  L_do_copy1\r
+\r
+L_wrap_around_window:\r
+; 793 "inffast.S"\r
+       mov  eax, [esp+48]\r
+       cmp  ecx,eax\r
+       jbe  L_contiguous_in_window\r
+\r
+       add  esi, [esp+52]\r
+       add  esi,eax\r
+       sub  esi,ecx\r
+       sub  ecx,eax\r
+\r
+\r
+       mov  eax, [esp+24]\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi, [esp+56]\r
+       mov  ecx, [esp+48]\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+       jmp  L_do_copy1\r
+\r
+L_contiguous_in_window:\r
+; 836 "inffast.S"\r
+       add  esi,eax\r
+       sub  esi,ecx\r
+\r
+\r
+       mov  eax, [esp+24]\r
+       cmp  eax,ecx\r
+       jbe  L_do_copy1\r
+\r
+       sub  eax,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,edx\r
+\r
+L_do_copy1:\r
+; 862 "inffast.S"\r
+       mov  ecx,eax\r
+       rep movsb\r
+\r
+       mov  esi, [esp+44]\r
+       jmp  L_while_test\r
+; 878 "inffast.S"\r
+ALIGN 4\r
+L_init_mmx:\r
+       emms\r
+\r
+\r
+\r
+\r
+\r
+       movd mm0,ebp\r
+       mov  ebp,ebx\r
+; 896 "inffast.S"\r
+       movd mm4,[esp+0]\r
+       movq mm3,mm4\r
+       movd mm5,[esp+4]\r
+       movq mm2,mm5\r
+       pxor mm1,mm1\r
+       mov  ebx, [esp+8]\r
+       jmp  L_do_loop_mmx\r
+\r
+ALIGN 4\r
+L_do_loop_mmx:\r
+       psrlq mm0,mm1\r
+\r
+       cmp  ebp,32\r
+       ja  L_get_length_code_mmx\r
+\r
+       movd mm6,ebp\r
+       movd mm7,[esi]\r
+       add  esi,4\r
+       psllq mm7,mm6\r
+       add  ebp,32\r
+       por mm0,mm7\r
+\r
+L_get_length_code_mmx:\r
+       pand mm4,mm0\r
+       movd eax,mm4\r
+       movq mm4,mm3\r
+       mov  eax, [ebx+eax*4]\r
+\r
+L_dolen_mmx:\r
+       movzx  ecx,ah\r
+       movd mm1,ecx\r
+       sub  ebp,ecx\r
+\r
+       test  al,al\r
+       jnz L_test_for_length_base_mmx\r
+\r
+       shr  eax,16\r
+       stosb\r
+\r
+L_while_test_mmx:\r
+\r
+\r
+       cmp  [esp+16],edi\r
+       jbe L_break_loop\r
+\r
+       cmp  [esp+20],esi\r
+       ja L_do_loop_mmx\r
+       jmp L_break_loop\r
+\r
+L_test_for_length_base_mmx:\r
+\r
+       mov  edx,eax\r
+       shr  edx,16\r
+\r
+       test  al,16\r
+       jz  L_test_for_second_level_length_mmx\r
+       and  eax,15\r
+       jz L_decode_distance_mmx\r
+\r
+       psrlq mm0,mm1\r
+       movd mm1,eax\r
+       movd ecx,mm0\r
+       sub  ebp,eax\r
+       and  ecx, [inflate_fast_mask+eax*4]\r
+       add  edx,ecx\r
+\r
+L_decode_distance_mmx:\r
+       psrlq mm0,mm1\r
+\r
+       cmp  ebp,32\r
+       ja L_get_dist_code_mmx\r
+\r
+       movd mm6,ebp\r
+       movd mm7,[esi]\r
+       add  esi,4\r
+       psllq mm7,mm6\r
+       add  ebp,32\r
+       por mm0,mm7\r
+\r
+L_get_dist_code_mmx:\r
+       mov  ebx, [esp+12]\r
+       pand mm5,mm0\r
+       movd eax,mm5\r
+       movq mm5,mm2\r
+       mov  eax, [ebx+eax*4]\r
+\r
+L_dodist_mmx:\r
+\r
+       movzx  ecx,ah\r
+       mov  ebx,eax\r
+       shr  ebx,16\r
+       sub  ebp,ecx\r
+       movd mm1,ecx\r
+\r
+       test  al,16\r
+       jz L_test_for_second_level_dist_mmx\r
+       and  eax,15\r
+       jz L_check_dist_one_mmx\r
+\r
+L_add_bits_to_dist_mmx:\r
+       psrlq mm0,mm1\r
+       movd mm1,eax\r
+       movd ecx,mm0\r
+       sub  ebp,eax\r
+       and  ecx, [inflate_fast_mask+eax*4]\r
+       add  ebx,ecx\r
+\r
+L_check_window_mmx:\r
+       mov  [esp+44],esi\r
+       mov  eax,edi\r
+       sub  eax, [esp+40]\r
+\r
+       cmp  eax,ebx\r
+       jb L_clip_window_mmx\r
+\r
+       mov  ecx,edx\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+\r
+       sub  ecx,3\r
+       mov  al, [esi]\r
+       mov  [edi],al\r
+       mov  al, [esi+1]\r
+       mov  dl, [esi+2]\r
+       add  esi,3\r
+       mov  [edi+1],al\r
+       mov  [edi+2],dl\r
+       add  edi,3\r
+       rep movsb\r
+\r
+       mov  esi, [esp+44]\r
+       mov  ebx, [esp+8]\r
+       jmp  L_while_test_mmx\r
+\r
+ALIGN 4\r
+L_check_dist_one_mmx:\r
+       cmp  ebx,1\r
+       jne  L_check_window_mmx\r
+       cmp  [esp+40],edi\r
+       je   L_check_window_mmx\r
+\r
+       dec  edi\r
+       mov  ecx,edx\r
+       mov  al, [edi]\r
+       sub  ecx,3\r
+\r
+       mov  [edi+1],al\r
+       mov  [edi+2],al\r
+       mov  [edi+3],al\r
+       add  edi,4\r
+       rep stosb\r
+\r
+       mov  ebx, [esp+8]\r
+       jmp  L_while_test_mmx\r
+\r
+ALIGN 4\r
+L_test_for_second_level_length_mmx:\r
+       test  al,64\r
+       jnz L_test_for_end_of_block\r
+\r
+       and  eax,15\r
+       psrlq mm0,mm1\r
+       movd ecx,mm0\r
+       and  ecx, [inflate_fast_mask+eax*4]\r
+       add  ecx,edx\r
+       mov  eax, [ebx+ecx*4]\r
+       jmp L_dolen_mmx\r
+\r
+ALIGN 4\r
+L_test_for_second_level_dist_mmx:\r
+       test  al,64\r
+       jnz L_invalid_distance_code\r
+\r
+       and  eax,15\r
+       psrlq mm0,mm1\r
+       movd ecx,mm0\r
+       and  ecx, [inflate_fast_mask+eax*4]\r
+       mov  eax, [esp+12]\r
+       add  ecx,ebx\r
+       mov  eax, [eax+ecx*4]\r
+       jmp  L_dodist_mmx\r
+\r
+ALIGN 4\r
+L_clip_window_mmx:\r
+\r
+       mov  ecx,eax\r
+       mov  eax, [esp+52]\r
+       neg  ecx\r
+       mov  esi, [esp+56]\r
+\r
+       cmp  eax,ebx\r
+       jb  L_invalid_distance_too_far\r
+\r
+       add  ecx,ebx\r
+       cmp  dword ptr [esp+48],0\r
+       jne  L_wrap_around_window_mmx\r
+\r
+       sub  eax,ecx\r
+       add  esi,eax\r
+\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+       jmp  L_do_copy1_mmx\r
+\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+       jmp  L_do_copy1_mmx\r
+\r
+L_wrap_around_window_mmx:\r
+\r
+       mov  eax, [esp+48]\r
+       cmp  ecx,eax\r
+       jbe  L_contiguous_in_window_mmx\r
+\r
+       add  esi, [esp+52]\r
+       add  esi,eax\r
+       sub  esi,ecx\r
+       sub  ecx,eax\r
+\r
+\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi, [esp+56]\r
+       mov  ecx, [esp+48]\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+       jmp  L_do_copy1_mmx\r
+\r
+L_contiguous_in_window_mmx:\r
+\r
+       add  esi,eax\r
+       sub  esi,ecx\r
+\r
+\r
+       cmp  edx,ecx\r
+       jbe  L_do_copy1_mmx\r
+\r
+       sub  edx,ecx\r
+       rep movsb\r
+       mov  esi,edi\r
+       sub  esi,ebx\r
+\r
+L_do_copy1_mmx:\r
+\r
+\r
+       mov  ecx,edx\r
+       rep movsb\r
+\r
+       mov  esi, [esp+44]\r
+       mov  ebx, [esp+8]\r
+       jmp  L_while_test_mmx\r
+; 1174 "inffast.S"\r
+L_invalid_distance_code:\r
+\r
+\r
+\r
+\r
+\r
+       mov  ecx, invalid_distance_code_msg\r
+       mov  edx,INFLATE_MODE_BAD\r
+       jmp  L_update_stream_state\r
+\r
+L_test_for_end_of_block:\r
+\r
+\r
+\r
+\r
+\r
+       test  al,32\r
+       jz  L_invalid_literal_length_code\r
+\r
+       mov  ecx,0\r
+       mov  edx,INFLATE_MODE_TYPE\r
+       jmp  L_update_stream_state\r
+\r
+L_invalid_literal_length_code:\r
+\r
+\r
+\r
+\r
+\r
+       mov  ecx, invalid_literal_length_code_msg\r
+       mov  edx,INFLATE_MODE_BAD\r
+       jmp  L_update_stream_state\r
+\r
+L_invalid_distance_too_far:\r
+\r
+\r
+\r
+       mov  esi, [esp+44]\r
+       mov  ecx, invalid_distance_too_far_msg\r
+       mov  edx,INFLATE_MODE_BAD\r
+       jmp  L_update_stream_state\r
+\r
+L_update_stream_state:\r
+\r
+       mov  eax, [esp+88]\r
+       test  ecx,ecx\r
+       jz  L_skip_msg\r
+       mov  [eax+24],ecx\r
+L_skip_msg:\r
+       mov  eax, [eax+28]\r
+       mov  [eax+mode_state],edx\r
+       jmp  L_break_loop\r
+\r
+ALIGN 4\r
+L_break_loop:\r
+; 1243 "inffast.S"\r
+       cmp  dword ptr [inflate_fast_use_mmx],2\r
+       jne  L_update_next_in\r
+\r
+\r
+\r
+       mov  ebx,ebp\r
+\r
+L_update_next_in:\r
+; 1266 "inffast.S"\r
+       mov  eax, [esp+88]\r
+       mov  ecx,ebx\r
+       mov  edx, [eax+28]\r
+       shr  ecx,3\r
+       sub  esi,ecx\r
+       shl  ecx,3\r
+       sub  ebx,ecx\r
+       mov  [eax+12],edi\r
+       mov  [edx+bits_state],ebx\r
+       mov  ecx,ebx\r
+\r
+       lea  ebx, [esp+28]\r
+       cmp  [esp+20],ebx\r
+       jne  L_buf_not_used\r
+\r
+       sub  esi,ebx\r
+       mov  ebx, [eax+0]\r
+       mov  [esp+20],ebx\r
+       add  esi,ebx\r
+       mov  ebx, [eax+4]\r
+       sub  ebx,11\r
+       add  [esp+20],ebx\r
+\r
+L_buf_not_used:\r
+       mov  [eax+0],esi\r
+\r
+       mov  ebx,1\r
+       shl  ebx,cl\r
+       dec  ebx\r
+\r
+\r
+\r
+\r
+\r
+       cmp  dword ptr [inflate_fast_use_mmx],2\r
+       jne  L_update_hold\r
+\r
+\r
+\r
+       psrlq mm0,mm1\r
+       movd ebp,mm0\r
+\r
+       emms\r
+\r
+L_update_hold:\r
+\r
+\r
+\r
+       and  ebp,ebx\r
+       mov  [edx+hold_state],ebp\r
+\r
+\r
+\r
+\r
+       mov  ebx, [esp+20]\r
+       cmp  ebx,esi\r
+       jbe  L_last_is_smaller\r
+\r
+       sub  ebx,esi\r
+       add  ebx,11\r
+       mov  [eax+4],ebx\r
+       jmp  L_fixup_out\r
+L_last_is_smaller:\r
+       sub  esi,ebx\r
+       neg  esi\r
+       add  esi,11\r
+       mov  [eax+4],esi\r
+\r
+\r
+\r
+\r
+L_fixup_out:\r
+\r
+       mov  ebx, [esp+16]\r
+       cmp  ebx,edi\r
+       jbe  L_end_is_smaller\r
+\r
+       sub  ebx,edi\r
+       add  ebx,257\r
+       mov  [eax+16],ebx\r
+       jmp  L_done\r
+L_end_is_smaller:\r
+       sub  edi,ebx\r
+       neg  edi\r
+       add  edi,257\r
+       mov  [eax+16],edi\r
+\r
+\r
+\r
+\r
+\r
+L_done:\r
+       add  esp,64\r
+       popfd\r
+       pop  ebx\r
+       pop  ebp\r
+       pop  esi\r
+       pop  edi\r
+       ret\r
+\r
+_TEXT  ends\r
+end\r
index f3fa0a0..70a51f8 100755 (executable)
@@ -1,3 +1,3 @@
-cl /I..\.. /O2 /c gvmat32c.c\r
+cl /DASMV /I..\.. /O2 /c gvmat32c.c\r
 ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm\r
 ml /coff /Zi /c /Flinffas32.lst inffas32.asm\r
index 9c7a89c..622f4bc 100644 (file)
@@ -1,9 +1,9 @@
 /* crypt.h -- base code for crypt/uncrypt ZIPfile
 
 
-   Version 1.00, September 10th, 2003
+   Version 1.01e, February 12th, 2005
 
-   Copyright (C) 1998-2003 Gilles Vollant
+   Copyright (C) 1998-2005 Gilles Vollant
 
    This code is a modified version of crypting code in Infozip distribution
 
index 80443b7..f1bee23 100644 (file)
@@ -1,9 +1,9 @@
 /* ioapi.c -- IO base function header for compress/uncompress .zip
    files using zlib + zip or unzip API
 
-   Version 1.00, September 10th, 2003
+   Version 1.01e, February 12th, 2005
 
-   Copyright (C) 1998-2003 Gilles Vollant
+   Copyright (C) 1998-2005 Gilles Vollant
 */
 
 #include <stdio.h>
@@ -94,7 +94,7 @@ uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
    uLong size;
 {
     uLong ret;
-    ret = fread(buf, 1, (size_t)size, (FILE *)stream);
+    ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
     return ret;
 }
 
@@ -106,7 +106,7 @@ uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
    uLong size;
 {
     uLong ret;
-    ret = fwrite(buf, 1, (size_t)size, (FILE *)stream);
+    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
     return ret;
 }
 
index 6bc2a2c..7d457ba 100644 (file)
@@ -1,9 +1,9 @@
 /* ioapi.h -- IO base function header for compress/uncompress .zip
    files using zlib + zip or unzip API
 
-   Version 1.00, September 10th, 2003
+   Version 1.01e, February 12th, 2005
 
-   Copyright (C) 1998-2003 Gilles Vollant
+   Copyright (C) 1998-2005 Gilles Vollant
 */
 
 #ifndef _ZLIBIOAPI_H
index 02b27cb..a9b5f78 100644 (file)
@@ -2,9 +2,9 @@
    files using zlib + zip or unzip API
    This IO API version uses the Win32 API (for Microsoft Windows)
 
-   Version 1.00, September 10th, 2003
+   Version 1.01e, February 12th, 2005
 
-   Copyright (C) 1998-2003 Gilles Vollant
+   Copyright (C) 1998-2005 Gilles Vollant
 */
 
 #include <stdlib.h>
index c0ebd50..a3a437a 100644 (file)
@@ -2,9 +2,9 @@
    files using zlib + zip or unzip API
    This IO API version uses the Win32 API (for Microsoft Windows)
 
-   Version 1.00, September 10th, 2003
+   Version 1.01e, February 12th, 2005
 
-   Copyright (C) 1998-2003 Gilles Vollant
+   Copyright (C) 1998-2005 Gilles Vollant
 */
 
 #include <windows.h>
index 6d5ebe0..836848c 100644 (file)
@@ -10,7 +10,7 @@ unit zlibpas;
 interface
 
 const
-  ZLIB_VERSION = '1.2.1';
+  ZLIB_VERSION = '1.2.3';
 
 type
   alloc_func = function(opaque: Pointer; items, size: Integer): Pointer;
index 7a8116b..ce0cc40 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * puff.c
- * Copyright (C) 2002, 2003 Mark Adler
+ * Copyright (C) 2002-2004 Mark Adler
  * For conditions of distribution and use, see copyright notice in puff.h
- * version 1.7, 3 Mar 2003
+ * version 1.8, 9 Jan 2004
  *
  * puff.c is a simple inflate written to be an unambiguous way to specify the
  * deflate format.  It is not written for speed but rather simplicity.  As a
@@ -60,6 +60,7 @@
  * 1.6   7 Aug 2002     - Minor format changes
  * 1.7   3 Mar 2003     - Added test code for distribution
  *                      - Added zlib-like license
+ * 1.8   9 Jan 2004     - Added some comments on no distance codes case
  */
 
 #include <setjmp.h>             /* for setjmp(), longjmp(), and jmp_buf */
@@ -577,6 +578,9 @@ local int fixed(struct state *s)
  *   block is fewer bits), but it is allowed by the format.  So incomplete
  *   literal/length codes of one symbol should also be permitted.
  *
+ * - If there are only literal codes and no lengths, then there are no distance
+ *   codes.  This is represented by one distance code with zero bits.
+ *
  * - The list of up to 286 length/literal lengths and up to 30 distance lengths
  *   are themselves compressed using Huffman codes and run-length encoding.  In
  *   the list of code lengths, a 0 symbol means no code, a 1..15 symbol means
index fdabc5c..e5574f4 100644 (file)
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <windows.h>
-#include "zlib.h"
-
-int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
-{
-    FILE* stream;
-    void* ptr;
-    int retVal=1;
-    stream=fopen(filename, "rb");
-    if (stream==NULL)
-        return 0;
-
-    fseek(stream,0,SEEK_END);
-
-    *plFileSize=ftell(stream);
-    fseek(stream,0,SEEK_SET);
-    ptr=malloc((*plFileSize)+1);
-    if (ptr==NULL)
-        retVal=0;
-    else
-    {
-        if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))
-            retVal=0;
-    }
-    fclose(stream);
-    *pFilePtr=ptr;
-    return retVal;
-}
-
-int main(int argc, char *argv[])
-{
-    int BlockSizeCompress=0x8000;
-    int BlockSizeUncompress=0x8000;
-    int cprLevel=Z_DEFAULT_COMPRESSION ;
-    long lFileSize;
-    unsigned char* FilePtr;
-    long lBufferSizeCpr;
-    long lBufferSizeUncpr;
-    long lCompressedSize=0;
-    unsigned char* CprPtr;
-    unsigned char* UncprPtr;
-    long lSizeCpr,lSizeUncpr;
-    DWORD dwGetTick;
-
-    if (argc<=1)
-    {
-        printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");
-        return 0;
-    }
-
-    if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)
-    {
-        printf("error reading %s\n",argv[1]);
-        return 1;
-    }
-    else printf("file %s read, %u bytes\n",argv[1],lFileSize);
-
-    if (argc>=3)
-        BlockSizeCompress=atol(argv[2]);
-
-    if (argc>=4)
-        BlockSizeUncompress=atol(argv[3]);
-
-    if (argc>=5)
-        cprLevel=(int)atol(argv[4]);
-
-    lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200;
-    lBufferSizeUncpr = lBufferSizeCpr;
-
-    CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);
-    UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);
-
-    dwGetTick=GetTickCount();
-    {
-        z_stream zcpr;
-        int ret=Z_OK;
-        long lOrigToDo = lFileSize;
-        long lOrigDone = 0;
-        int step=0;
-        memset(&zcpr,0,sizeof(z_stream));
-        deflateInit(&zcpr,cprLevel);
-
-        zcpr.next_in = FilePtr;
-        zcpr.next_out = CprPtr;
-
-
-        do
-        {
-            long all_read_before = zcpr.total_in;
-            zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);
-            zcpr.avail_out = BlockSizeCompress;
-            ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);
-            lOrigDone += (zcpr.total_in-all_read_before);
-            lOrigToDo -= (zcpr.total_in-all_read_before);
-            step++;
-        } while (ret==Z_OK);
-
-        lSizeCpr=zcpr.total_out;
-        deflateEnd(&zcpr);
-        dwGetTick=GetTickCount()-dwGetTick;
-        printf("total compress size = %u, in %u step\n",lSizeCpr,step);
-        printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.);
-    }
-
-    dwGetTick=GetTickCount();
-    {
-        z_stream zcpr;
-        int ret=Z_OK;
-        long lOrigToDo = lSizeCpr;
-        long lOrigDone = 0;
-        int step=0;
-        memset(&zcpr,0,sizeof(z_stream));
-        inflateInit(&zcpr);
-
-        zcpr.next_in = CprPtr;
-        zcpr.next_out = UncprPtr;
-
-
-        do
-        {
-            long all_read_before = zcpr.total_in;
-            zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress);
-            zcpr.avail_out = BlockSizeUncompress;
-            ret=inflate(&zcpr,Z_SYNC_FLUSH);
-            lOrigDone += (zcpr.total_in-all_read_before);
-            lOrigToDo -= (zcpr.total_in-all_read_before);
-            step++;
-        } while (ret==Z_OK);
-
-        lSizeUncpr=zcpr.total_out;
-        inflateEnd(&zcpr);
-        dwGetTick=GetTickCount()-dwGetTick;
-        printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);
-        printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.);
-    }
-
-    if (lSizeUncpr==lFileSize)
-    {
-        if (memcmp(FilePtr,UncprPtr,lFileSize)==0)
-            printf("compare ok\n");
-
-    }
-
-    return 0;
-
-}
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <windows.h>\r
+\r
+#include "zlib.h"\r
+\r
+\r
+void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B)\r
+{\r
+    R->HighPart = A.HighPart - B.HighPart;\r
+    if (A.LowPart >= B.LowPart)\r
+        R->LowPart = A.LowPart - B.LowPart;\r
+    else\r
+    {\r
+        R->LowPart = A.LowPart - B.LowPart;\r
+        R->HighPart --;\r
+    }\r
+}\r
+\r
+#ifdef _M_X64\r
+// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc\r
+unsigned __int64 __rdtsc(void);\r
+void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)\r
+{\r
+ //   printf("rdtsc = %I64x\n",__rdtsc());\r
+   pbeginTime64->QuadPart=__rdtsc();\r
+}\r
+\r
+LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    LARGE_INTEGER LIres;\r
+    unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart));\r
+    LIres.QuadPart=res;\r
+   // printf("rdtsc = %I64x\n",__rdtsc());\r
+    return LIres;\r
+}\r
+#else\r
+#ifdef _M_IX86\r
+void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)\r
+{\r
+    DWORD dwEdx,dwEax;\r
+    _asm\r
+    {\r
+        rdtsc\r
+        mov dwEax,eax\r
+        mov dwEdx,edx\r
+    }\r
+    pbeginTime64->LowPart=dwEax;\r
+    pbeginTime64->HighPart=dwEdx;\r
+}\r
+\r
+void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)\r
+{\r
+    myGetRDTSC32(pbeginTime64);\r
+}\r
+\r
+LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    LARGE_INTEGER LIres,endTime64;\r
+    myGetRDTSC32(&endTime64);\r
+\r
+    LIres.LowPart=LIres.HighPart=0;\r
+    MyDoMinus64(&LIres,endTime64,beginTime64);\r
+    return LIres;\r
+}\r
+#else\r
+void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)\r
+{\r
+}\r
+\r
+void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)\r
+{\r
+}\r
+\r
+LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    LARGE_INTEGER lr;\r
+    lr.QuadPart=0;\r
+    return lr;\r
+}\r
+#endif\r
+#endif\r
+\r
+void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64)))\r
+    {\r
+        pbeginTime64->LowPart = GetTickCount();\r
+        pbeginTime64->HighPart = 0;\r
+    }\r
+}\r
+\r
+DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)\r
+{\r
+    LARGE_INTEGER endTime64,ticksPerSecond,ticks;\r
+    DWORDLONG ticksShifted,tickSecShifted;\r
+    DWORD dwLog=16+0;\r
+    DWORD dwRet;\r
+    if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64)))\r
+        dwRet = (GetTickCount() - beginTime64.LowPart)*1;\r
+    else\r
+    {\r
+        MyDoMinus64(&ticks,endTime64,beginTime64);\r
+        QueryPerformanceFrequency(&ticksPerSecond);\r
+\r
+    \r
+        {\r
+            ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog);\r
+            tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog);\r
+        \r
+        } \r
+\r
+        dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted));\r
+        dwRet *=1;\r
+    }\r
+    return dwRet;\r
+}\r
+\r
+int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)\r
+{\r
+    FILE* stream;\r
+    void* ptr;\r
+    int retVal=1;\r
+    stream=fopen(filename, "rb");\r
+    if (stream==NULL)\r
+        return 0;\r
+\r
+    fseek(stream,0,SEEK_END);\r
+\r
+    *plFileSize=ftell(stream);\r
+    fseek(stream,0,SEEK_SET);\r
+    ptr=malloc((*plFileSize)+1);\r
+    if (ptr==NULL)\r
+        retVal=0;\r
+    else\r
+    {\r
+        if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))\r
+            retVal=0;\r
+    }\r
+    fclose(stream);\r
+    *pFilePtr=ptr;\r
+    return retVal;\r
+}\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+    int BlockSizeCompress=0x8000;\r
+    int BlockSizeUncompress=0x8000;\r
+    int cprLevel=Z_DEFAULT_COMPRESSION ;\r
+    long lFileSize;\r
+    unsigned char* FilePtr;\r
+    long lBufferSizeCpr;\r
+    long lBufferSizeUncpr;\r
+    long lCompressedSize=0;\r
+    unsigned char* CprPtr;\r
+    unsigned char* UncprPtr;\r
+    long lSizeCpr,lSizeUncpr;\r
+    DWORD dwGetTick,dwMsecQP;\r
+    LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc;\r
+\r
+    if (argc<=1)\r
+    {\r
+        printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");\r
+        return 0;\r
+    }\r
+\r
+    if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)\r
+    {\r
+        printf("error reading %s\n",argv[1]);\r
+        return 1;\r
+    }\r
+    else printf("file %s read, %u bytes\n",argv[1],lFileSize);\r
+\r
+    if (argc>=3)\r
+        BlockSizeCompress=atol(argv[2]);\r
+\r
+    if (argc>=4)\r
+        BlockSizeUncompress=atol(argv[3]);\r
+\r
+    if (argc>=5)\r
+        cprLevel=(int)atol(argv[4]);\r
+\r
+    lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200;\r
+    lBufferSizeUncpr = lBufferSizeCpr;\r
+\r
+    CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);\r
+\r
+    BeginCountPerfCounter(&li_qp,TRUE);\r
+    dwGetTick=GetTickCount();\r
+    BeginCountRdtsc(&li_rdtsc);\r
+    {\r
+        z_stream zcpr;\r
+        int ret=Z_OK;\r
+        long lOrigToDo = lFileSize;\r
+        long lOrigDone = 0;\r
+        int step=0;\r
+        memset(&zcpr,0,sizeof(z_stream));\r
+        deflateInit(&zcpr,cprLevel);\r
+\r
+        zcpr.next_in = FilePtr;\r
+        zcpr.next_out = CprPtr;\r
+\r
+\r
+        do\r
+        {\r
+            long all_read_before = zcpr.total_in;\r
+            zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);\r
+            zcpr.avail_out = BlockSizeCompress;\r
+            ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);\r
+            lOrigDone += (zcpr.total_in-all_read_before);\r
+            lOrigToDo -= (zcpr.total_in-all_read_before);\r
+            step++;\r
+        } while (ret==Z_OK);\r
+\r
+        lSizeCpr=zcpr.total_out;\r
+        deflateEnd(&zcpr);\r
+        dwGetTick=GetTickCount()-dwGetTick;\r
+        dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);\r
+        dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);\r
+        printf("total compress size = %u, in %u step\n",lSizeCpr,step);\r
+        printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);\r
+        printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);\r
+        printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);\r
+    }\r
+\r
+    CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr);\r
+    UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);\r
+\r
+    BeginCountPerfCounter(&li_qp,TRUE);\r
+    dwGetTick=GetTickCount();\r
+    BeginCountRdtsc(&li_rdtsc);\r
+    {\r
+        z_stream zcpr;\r
+        int ret=Z_OK;\r
+        long lOrigToDo = lSizeCpr;\r
+        long lOrigDone = 0;\r
+        int step=0;\r
+        memset(&zcpr,0,sizeof(z_stream));\r
+        inflateInit(&zcpr);\r
+\r
+        zcpr.next_in = CprPtr;\r
+        zcpr.next_out = UncprPtr;\r
+\r
+\r
+        do\r
+        {\r
+            long all_read_before = zcpr.total_in;\r
+            zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress);\r
+            zcpr.avail_out = BlockSizeUncompress;\r
+            ret=inflate(&zcpr,Z_SYNC_FLUSH);\r
+            lOrigDone += (zcpr.total_in-all_read_before);\r
+            lOrigToDo -= (zcpr.total_in-all_read_before);\r
+            step++;\r
+        } while (ret==Z_OK);\r
+\r
+        lSizeUncpr=zcpr.total_out;\r
+        inflateEnd(&zcpr);\r
+        dwGetTick=GetTickCount()-dwGetTick;\r
+        dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);\r
+        dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);\r
+        printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);\r
+        printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);\r
+        printf("uncpr  time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);\r
+        printf("uncpr  result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);\r
+    }\r
+\r
+    if (lSizeUncpr==lFileSize)\r
+    {\r
+        if (memcmp(FilePtr,UncprPtr,lFileSize)==0)\r
+            printf("compare ok\n");\r
+\r
+    }\r
+\r
+    return 0;\r
+}\r
index 3a4b85c..16159f9 100644 (file)
@@ -1,8 +1,8 @@
-Building instructions for the DLL versions of Zlib 1.21\r
-=======================================================\r
+Building instructions for the DLL versions of Zlib 1.2.3\r
+========================================================\r
 \r
 This directory contains projects that build zlib and minizip using\r
-Microsoft Visual C++ 7.0/7.1.\r
+Microsoft Visual C++ 7.0/7.1, and Visual C++ .\r
 \r
 You don't need to build these projects yourself. You can download the\r
 binaries from:\r
@@ -11,18 +11,36 @@ binaries from:
 More information can be found at this site.\r
 \r
 \r
-Build instructions\r
-------------------\r
-- Unzip zlib*.zip and copy the files from contrib\vstudio\vc7,\r
-  from contrib\vstudio\masmx86 and from contrib\minizip into the same\r
-  directory.\r
+Build instructions for Visual Studio 7.x (32 bits)\r
+--------------------------------------------------\r
+- Uncompress current zlib, including all contrib/* files\r
 - Download the crtdll library from\r
     http://www.winimage.com/zLibDll/crtdll.zip\r
-  Unzip crtdll.zip to extract crtdll.lib.\r
-- If you are using x86, use the Release target.\r
-- Open zlibvc.sln with Microsoft Visual C++ 7.0 or 7.1\r
+  Unzip crtdll.zip to extract crtdll.lib on contrib\vstudio\vc7.\r
+- Open contrib\vstudio\vc7\zlibvc.sln with Microsoft Visual C++ 7.x\r
   (Visual Studio .Net 2002 or 2003).\r
 \r
+Build instructions for Visual Studio 2005 (32 bits or 64 bits)\r
+--------------------------------------------------------------\r
+- Uncompress current zlib, including all contrib/* files\r
+- For 32 bits only: download the crtdll library from\r
+    http://www.winimage.com/zLibDll/crtdll.zip\r
+  Unzip crtdll.zip to extract crtdll.lib on contrib\vstudio\vc8.\r
+- Open contrib\vstudio\vc8\zlibvc.sln with Microsoft Visual C++ 8.0