home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip531.zip / crc_i386.S < prev    next >
Text File  |  1997-02-18  |  6KB  |  164 lines

  1. /*
  2.  * crc_i386.S, optimized CRC calculation function for Zip and UnZip, not
  3.  * copyrighted by Paul Kienitz and Christian Spieler.  Last revised 10 Nov 96.
  4.  *
  5.  * GRR 961110:  incorporated Scott Field optimizations from win32/crc_i386.asm
  6.  *              => overall 6% speedup in "unzip -tq" on 9MB zipfile (486-66)
  7.  *
  8.  * FLAT memory model assumed.  Calling interface:
  9.  *   - args are pushed onto the stack from right to left,
  10.  *   - return value is given in the EAX register,
  11.  *   - all other registers (with exception of EFLAGS) are preserved. (With
  12.  *     GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving
  13.  *     them nevertheless does only cost 4 single byte instructions.)
  14.  *
  15.  * This source generates the function
  16.  * ulg crc32(ulg oldcrc, ZCONST uch *text, ulg textlen).
  17.  *
  18.  * The loop unroolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
  19.  * This results in shorter code at the expense of reduced performance.
  20.  */
  21.  
  22. /* This file is NOT used in conjunction with zlib. */
  23. #ifndef USE_ZLIB
  24.  
  25. /* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
  26.  * external symbols with an underline character '_'.
  27.  */
  28. #if defined(NO_UNDERLINE) || defined(__ELF__)
  29. #  define _crc32            crc32
  30. #  define _get_crc_table    get_crc_table
  31. #endif
  32. /* Use 16-byte alignment if your assembler supports it. Warning: gas
  33.  * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4
  34.  * the parameter is a number of bytes.
  35.  */
  36. #ifndef ALIGNMENT
  37. #  define ALIGNMENT .align 4,0x90
  38. #endif
  39.  
  40. #if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386)
  41.  
  42. /* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas).
  43.  * Warning: it uses the AT&T syntax: mov source,dest
  44.  * This file is only optional. If you want to use the C version,
  45.  * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string.
  46.  */
  47.  
  48.                 .file   "crc_i386.S"
  49.  
  50. #if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME)
  51. #  undef USE_STACKFRAME
  52. #else
  53.    /* The default is to use standard stack frame entry, because it
  54.     * results in smaller code!
  55.     */
  56. #  ifndef USE_STD_STACKFRAME
  57. #    define USE_STD_STACKFRAME
  58. #  endif
  59. #endif
  60.  
  61. #ifdef USE_STD_STACKFRAME
  62. #  define _STD_ENTRY    pushl   %ebp ; movl   %esp,%ebp
  63. #  define arg1  8(%ebp)
  64. #  define arg2  12(%ebp)
  65. #  define arg3  16(%ebp)
  66. #  define _STD_LEAVE    popl    %ebp
  67. #else /* !USE_STD_STACKFRAME */
  68. #  define _STD_ENTRY
  69. #  define arg1  24(%esp)
  70. #  define arg2  28(%esp)
  71. #  define arg3  32(%esp)
  72. #  define _STD_LEAVE
  73. #endif /* ?USE_STD_STACKFRAME */
  74.  
  75. /*
  76.  * This is the loop body of the CRC32 cruncher.
  77.  * registers modified:
  78.  *   ebx  : crc value "c"
  79.  *   esi  : pointer to next data byte "text++"
  80.  * registers read:
  81.  *   edi  : pointer to base of crc_table array
  82.  * scratch registers:
  83.  *   eax  : requires upper three bytes of eax = 0, uses al
  84.  */
  85. #define Do_CRC \
  86.                 movb    (%esi),%al          ;/* al <-- *text                */\
  87.                 incl    %esi                ;/* text++                      */\
  88.                 xorb    %bl,%al             ;/* (c ^ *text++) & 0xFF        */\
  89.                 shrl    $8,%ebx             ;/* c = (c >> 8)                */\
  90.                 xorl    (%edi,%eax,4),%ebx  ;/*  ^table[(c^(*text++))&0xFF] */
  91.  
  92.  
  93.                 .text
  94.  
  95.                 .globl  _crc32
  96.  
  97. _crc32:                         /* ulg crc32(ulg crc, uch *text, extent len) */
  98.                 _STD_ENTRY
  99.                 pushl   %edi
  100.                 pushl   %esi
  101.                 pushl   %ebx
  102.                 pushl   %edx
  103.                 pushl   %ecx
  104.  
  105.                 movl    arg2,%esi            /* 2nd arg: uch *text           */
  106.                 subl    %eax,%eax            /* > if (!text)                 */
  107.                 testl   %esi,%esi            /* >   return 0;                */
  108.                 jz      fine                 /* > else {                     */
  109.                 call    _get_crc_table
  110.                 movl    %eax,%edi
  111.                 movl    arg1,%ebx            /* 1st arg: ulg crc             */
  112.                 subl    %eax,%eax            /* eax=0; al usable as dword */
  113.                 movl    arg3,%ecx            /* 3rd arg: extent textlen      */
  114.                 notl    %ebx                 /* >   c = ~crc;                */
  115.  
  116. #ifndef  NO_UNROLLED_LOOPS
  117.                 movl    %ecx,%edx            /* save textlen in edx          */
  118.                 andl    $7,%edx              /* edx = textlen % 8            */
  119.                 shrl    $3,%ecx              /* ecx = textlen / 8            */
  120.                 jz      No_Eights
  121. /*  align loop head at start of 486 internal cache line !! */
  122.                 ALIGNMENT
  123. Next_Eight:
  124.                  Do_CRC
  125.                  Do_CRC
  126.                  Do_CRC
  127.                  Do_CRC
  128.                  Do_CRC
  129.                  Do_CRC
  130.                  Do_CRC
  131.                  Do_CRC
  132.                 decl    %ecx
  133.                 jnz     Next_Eight
  134.  
  135. No_Eights:
  136.                 movl    %edx,%ecx
  137. #endif /* NO_UNROLLED_LOOPS */
  138.  
  139.                 jecxz   bail                 /* > if (textlen)               */
  140. /* align loop head at start of 486 internal cache line !! */
  141.                 ALIGNMENT
  142. loupe:                                       /* >   do {                     */
  143.                  Do_CRC                      /*       c = CRC32(c, *text++); */
  144.                 decl    %ecx                 /* >   } while (--textlen);     */
  145.                 jnz     loupe
  146.  
  147. bail:                                        /* > }                          */
  148.                 movl    %ebx,%eax
  149.                 notl    %eax                 /* > return ~c;                 */
  150. fine:
  151.                 popl    %ecx
  152.                 popl    %edx
  153.                 popl    %ebx
  154.                 popl    %esi
  155.                 popl    %edi
  156.                 _STD_LEAVE
  157.                 ret
  158.  
  159. #else
  160.  error: this asm version is for 386 only
  161. #endif /* i386 || _i386 || _I386 || __i386 */
  162.  
  163. #endif /* !USE_ZLIB */
  164.