home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip22.zip / win32 / crc_i386.c < prev    next >
C/C++ Source or Header  |  1997-10-11  |  6KB  |  187 lines

  1. /* crc_i386.c -- Microsoft 32-bit C/C++ adaptation of crc_i386.asm
  2.  * Created by Rodney Brown from crc_i386.asm, modified by Chr. Spieler.
  3.  * publis
  4.  * Last revised 12 Oct 97
  5.  *
  6.  * Original coded (in crc_i386.asm) and put into the public domain
  7.  * by Paul Kienitz and Christian Spieler.
  8.  *
  9.  * Revised 06-Oct-96, Scott Field (sfield@microsoft.com)
  10.  *   fixed to assemble with masm by not using .model directive which makes
  11.  *   assumptions about segment alignment.  Also,
  12.  *   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather
  13.  *   than lodsb, and other misc. changes resulting in the following performance
  14.  *   increases:
  15.  *
  16.  *      unrolled loops                NO_UNROLLED_LOOPS
  17.  *      *8    >8      <8              *8      >8      <8
  18.  *
  19.  *      +54%  +42%    +35%            +82%    +52%    +25%
  20.  *
  21.  *   first item in each table is input buffer length, even multiple of 8
  22.  *   second item in each table is input buffer length, > 8
  23.  *   third item in each table is input buffer length, < 8
  24.  *
  25.  * Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
  26.  *   Incorporated Rodney Brown's 32-bit-reads optimization as found in the
  27.  *   UNIX AS source crc_i386.S. This new code can be disabled by defining
  28.  *   the macro symbol NO_32_BIT_LOADS.
  29.  *
  30.  * Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
  31.  *   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs
  32.  *   (like the Pentium Pro, Pentium II, and probably some Pentium clones).
  33.  *   This optimization is controlled by the macro symbol __686 and is disabled
  34.  *   by default. (This default is based on the assumption that most users
  35.  *   do not yet work on a Pentium Pro or Pentium II machine ...)
  36.  *
  37.  * FLAT memory model assumed.
  38.  *
  39.  * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
  40.  * This results in shorter code at the expense of reduced performance.
  41.  *
  42.  */
  43.  
  44. #include "zip.h"
  45.  
  46. #ifndef USE_ZLIB
  47.  
  48. #ifndef ZCONST
  49. #  define ZCONST const
  50. #endif
  51.  
  52. #if (defined(_MSC_VER) && _MSC_VER >= 700)
  53. #if (defined(_M_IX86) && _M_IX86 >= 300)
  54. /* This code is intended for Microsoft C/C++ (32-bit compiler). */
  55.  
  56. /*
  57.  * These two (three) macros make up the loop body of the CRC32 cruncher.
  58.  * registers modified:
  59.  *   eax  : crc value "c"
  60.  *   esi  : pointer to next data byte (or dword) "buf++"
  61.  * registers read:
  62.  *   edi  : pointer to base of crc_table array
  63.  * scratch registers:
  64.  *   ebx  : index into crc_table array
  65.  *          (requires upper three bytes = 0 when __686 is undefined)
  66.  */
  67. #ifndef __686
  68. #define Do_CRC \
  69.   __asm mov     bl, al \
  70.   __asm shr     eax, 8 \
  71.   __asm xor     eax, [edi+ebx*4]
  72. #else /* __686 */
  73. #ifdef NO_MOVZX_SUPPORT
  74. #define movzx__ebx__al  __asm _emit 0x0F __asm _emit 0xB6 __asm _emit 0xD8
  75. #else
  76. #define movzx__ebx__al  __asm movzx   ebx, al
  77. #endif
  78. #define Do_CRC \
  79.   movzx__ebx__al \
  80.   __asm shr     eax, 8 \
  81.   __asm xor     eax, [edi+ebx*4]
  82. #endif /* ?__686 */
  83.  
  84. #define Do_CRC_byte \
  85.   __asm xor     al, byte ptr [esi] \
  86.   __asm inc     esi \
  87.   Do_CRC
  88.  
  89. #ifndef NO_32_BIT_LOADS
  90. #define Do_CRC_dword \
  91.   __asm xor     eax, dword ptr [esi] \
  92.   __asm add     esi, 4 \
  93.   Do_CRC \
  94.   Do_CRC \
  95.   Do_CRC \
  96.   Do_CRC
  97. #endif /* !NO_32_BIT_LOADS */
  98.  
  99. /* ========================================================================= */
  100. ulg crc32(crc, buf, len)
  101.     ulg crc;                    /* crc shift register */
  102.     ZCONST uch *buf;            /* pointer to bytes to pump through */
  103.     extent len;                 /* number of bytes in buf[] */
  104. /* Run a set of bytes through the crc shift register.  If buf is a NULL
  105.    pointer, then initialize the crc shift register contents instead.
  106.    Return the current crc in either case. */
  107. {
  108.     __asm {
  109.                 push    edx
  110.                 push    ecx
  111.  
  112.                 mov     esi,buf              ; 2nd arg: uch *buf
  113.                 sub     eax,eax              ;> if (!buf)
  114.                 test    esi,esi              ;>   return 0;
  115.                 jz      fine                 ;> else {
  116.  
  117.                 call    get_crc_table
  118.                 mov     edi,eax
  119.                 mov     eax,crc              ; 1st arg: ulg crc
  120. #ifndef __686
  121.                 sub     ebx,ebx              ; ebx=0; make bl usable as a dword
  122. #endif
  123.                 mov     ecx,len              ; 3rd arg: extent len
  124.                 not     eax                  ;>   c = ~crc;
  125.  
  126. #ifndef NO_UNROLLED_LOOPS
  127. #  ifndef NO_32_BIT_LOADS
  128.                 test    ecx,ecx
  129.                 je      bail
  130. align_loop:
  131.                 test    esi,3                ; align buf pointer on next
  132.                 jz      aligned_now          ;  dword boundary
  133.                 Do_CRC_byte
  134.                 dec     ecx
  135.                 jnz     align_loop
  136. aligned_now:
  137. #  endif /* !NO_32_BIT_LOADS */
  138.                 mov     edx,ecx              ; save len in edx
  139.                 and     edx,000000007H       ; edx = len % 8
  140.                 shr     ecx,3                ; ecx = len / 8
  141.                 jz      No_Eights
  142. ; align loop head at start of 486 internal cache line !!
  143.                 align   16
  144. Next_Eight:
  145. #  ifndef NO_32_BIT_LOADS
  146.                 Do_CRC_dword
  147.                 Do_CRC_dword
  148. #  else /* NO_32_BIT_LOADS */
  149.                 Do_CRC_byte
  150.                 Do_CRC_byte
  151.                 Do_CRC_byte
  152.                 Do_CRC_byte
  153.                 Do_CRC_byte
  154.                 Do_CRC_byte
  155.                 Do_CRC_byte
  156.                 Do_CRC_byte
  157. #  endif /* ?NO_32_BIT_LOADS */
  158.                 dec     ecx
  159.                 jnz     Next_Eight
  160. No_Eights:
  161.                 mov     ecx,edx
  162.  
  163. #endif /* NO_UNROLLED_LOOPS */
  164. #ifndef NO_JECXZ_SUPPORT
  165.                 jecxz   bail                 ;>   if (len)
  166. #else
  167.                 test    ecx,ecx              ;>   if (len)
  168.                 jz      bail
  169. #endif
  170. ; align loop head at start of 486 internal cache line !!
  171.                 align   16
  172. loupe:                                       ;>     do {
  173.                 Do_CRC_byte                  ;        c = CRC32(c, *buf++);
  174.                 dec     ecx                  ;>     } while (--len);
  175.                 jnz     loupe
  176.  
  177. bail:                                        ;> }
  178.                 not     eax                  ;> return ~c;
  179. fine:
  180.                 pop     ecx
  181.                 pop     edx
  182.     }
  183. }
  184. #endif /* _M_IX86 >= 300 */
  185. #endif /* _MSC_VER >= 700*/
  186. #endif /* !USE_ZLIB */
  187.