crc_i386.S
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:9k
源码类别:

压缩解压

开发平台:

MultiPlatform

  1. /*
  2.  * crc_i386.S, optimized CRC calculation function for Zip and UnZip, not
  3.  * copyrighted by Paul Kienitz and Christian Spieler.  Last revised 12 Oct 97.
  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.  * SPC 970402:  revised for Rodney Brown's optimizations (32-bit-wide
  9.  *              aligned reads for most of the data from buffer), can be
  10.  *              disabled by defining the macro NO_32_BIT_LOADS
  11.  *
  12.  * SPC 971012:  added Rodney Brown's additional tweaks for 32-bit-optimized
  13.  *              CPUs (like the Pentium Pro, Pentium II, and probably some
  14.  *              Pentium clones). This optimization is controlled by the
  15.  *              preprocessor switch "__686" and is disabled by default.
  16.  *              (This default is based on the assumption that most users
  17.  *              do not yet work on a Pentium Pro or Pentium II machine ...)
  18.  *
  19.  * FLAT memory model assumed.  Calling interface:
  20.  *   - args are pushed onto the stack from right to left,
  21.  *   - return value is given in the EAX register,
  22.  *   - all other registers (with exception of EFLAGS) are preserved. (With
  23.  *     GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving
  24.  *     them nevertheless adds only 4 single byte instructions.)
  25.  *
  26.  * This source generates the function
  27.  * ulg crc32(ulg crc, ZCONST uch *buf, ulg len).
  28.  *
  29.  * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
  30.  * This results in shorter code at the expense of reduced performance.
  31.  */
  32. /* This file is NOT used in conjunction with zlib. */
  33. #ifndef USE_ZLIB
  34. /* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
  35.  * external symbols with an underline character '_'.
  36.  */
  37. #if defined(NO_UNDERLINE) || defined(__ELF__)
  38. #  define _crc32            crc32
  39. #  define _get_crc_table    get_crc_table
  40. #endif
  41. /* Use 16-byte alignment if your assembler supports it. Warning: gas
  42.  * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4
  43.  * the parameter is a number of bytes.
  44.  */
  45. #ifndef ALIGNMENT
  46. #  define ALIGNMENT .align 4,0x90
  47. #endif
  48. #if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386)
  49. /* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas).
  50.  * Warning: it uses the AT&T syntax: mov source,dest
  51.  * This file is only optional. If you want to use the C version,
  52.  * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string.
  53.  */
  54.                 .file   "crc_i386.S"
  55. #if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME)
  56. #  undef USE_STACKFRAME
  57. #else
  58.    /* The default is to use standard stack frame entry, because it
  59.     * results in smaller code!
  60.     */
  61. #  ifndef USE_STD_STACKFRAME
  62. #    define USE_STD_STACKFRAME
  63. #  endif
  64. #endif
  65. #ifdef USE_STD_STACKFRAME
  66. #  define _STD_ENTRY    pushl   %ebp ; movl   %esp,%ebp
  67. #  define arg1  8(%ebp)
  68. #  define arg2  12(%ebp)
  69. #  define arg3  16(%ebp)
  70. #  define _STD_LEAVE    popl    %ebp
  71. #else /* !USE_STD_STACKFRAME */
  72. #  define _STD_ENTRY
  73. #  define arg1  24(%esp)
  74. #  define arg2  28(%esp)
  75. #  define arg3  32(%esp)
  76. #  define _STD_LEAVE
  77. #endif /* ?USE_STD_STACKFRAME */
  78. /*
  79.  * These two (three) macros make up the loop body of the CRC32 cruncher.
  80.  * registers modified:
  81.  *   eax  : crc value "c"
  82.  *   esi  : pointer to next data byte (or lword) "buf++"
  83.  * registers read:
  84.  *   edi  : pointer to base of crc_table array
  85.  * scratch registers:
  86.  *   ebx  : index into crc_table array
  87.  *          (requires upper three bytes = 0 when __686 is undefined)
  88.  */
  89. #ifndef __686   /* optimize for 386, 486, Pentium */
  90. #define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */
  91.                 movb    %al, %bl                ;/* tmp = c & 0xFF  */
  92.                 shrl    $8, %eax                ;/* c = (c >> 8)    */
  93.                 xorl    (%edi, %ebx, 4), %eax   ;/* c ^= table[tmp] */
  94. #else   /* __686 : optimize for Pentium Pro and compatible CPUs */
  95. #define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */
  96.                 movzbl  %al, %ebx               ;/* tmp = c & 0xFF  */
  97.                 shrl    $8, %eax                ;/* c = (c >> 8)    */
  98.                 xorl    (%edi, %ebx, 4), %eax   ;/* c ^=table[tmp]  */
  99. #endif  /* ?__686 */
  100. #define Do_CRC_byte     /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */
  101.                 xorb    (%esi), %al     ;/* c ^= *buf  */
  102.                 incl    %esi            ;/* buf++      */
  103.                 Do_CRC
  104. #ifndef  NO_32_BIT_LOADS
  105. #define Do_CRC_lword 
  106.                 xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
  107.                 addl    $4, %esi        ;/* ((ulg *)buf)++   */
  108.                 Do_CRC 
  109.                 Do_CRC 
  110.                 Do_CRC 
  111.                 Do_CRC
  112. #endif  /* !NO_32_BIT_LOADS */
  113.                 .text
  114.                 .globl  _crc32
  115. _crc32:                         /* ulg crc32(ulg crc, uch *buf, extent len) */
  116.                 _STD_ENTRY
  117.                 pushl   %edi
  118.                 pushl   %esi
  119.                 pushl   %ebx
  120.                 pushl   %edx
  121.                 pushl   %ecx
  122.                 movl    arg2, %esi           /* 2nd arg: uch *buf            */
  123.                 subl    %eax, %eax           /* > if (!buf)                  */
  124.                 testl   %esi, %esi           /* >   return 0;                */
  125.                 jz      .L_fine              /* > else {                     */
  126.                 call    _get_crc_table
  127.                 movl    %eax, %edi
  128.                 movl    arg1, %eax           /* 1st arg: ulg crc             */
  129. #ifndef __686
  130.                 subl    %ebx, %ebx           /* ebx=0; bl usable as dword    */
  131. #endif
  132.                 movl    arg3, %ecx           /* 3rd arg: extent len          */
  133.                 notl    %eax                 /* >   c = ~crc;                */
  134. #ifndef  NO_UNROLLED_LOOPS
  135. #  ifndef  NO_32_BIT_LOADS
  136.                 testl   %ecx, %ecx
  137.                 jz      .L_bail
  138.                 /* Assert now have positive length */
  139. .L_align_loop:
  140.                 testl   $3, %esi        /* Align buf on lword boundary */
  141.                 jz      .L_aligned_now
  142.                 Do_CRC_byte
  143.                 decl    %ecx
  144.                 jnz     .L_align_loop
  145. .L_aligned_now:
  146. #  endif  /* !NO_32_BIT_LOADS */
  147.                 movl    %ecx, %edx           /* save len in edx          */
  148.                 andl    $7, %edx             /* edx = len % 8            */
  149.                 shrl    $3, %ecx             /* ecx = len / 8            */
  150.                 jz      .L_No_Eights
  151. /*  align loop head at start of 486 internal cache line !! */
  152.                 ALIGNMENT
  153. .L_Next_Eight:
  154. #  ifndef NO_32_BIT_LOADS
  155.                  /* Do_CRC_lword */
  156.                  xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
  157.                  addl    $4, %esi        ;/* ((ulg *)buf)++   */
  158.                  Do_CRC
  159.                  Do_CRC
  160.                  Do_CRC
  161.                  Do_CRC
  162.                  /* Do_CRC_lword */
  163.                  xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
  164.                  addl    $4, %esi        ;/* ((ulg *)buf)++   */
  165.                  Do_CRC
  166.                  Do_CRC
  167.                  Do_CRC
  168.                  Do_CRC
  169. #  else   /* NO_32_BIT_LOADS */
  170.                  Do_CRC_byte
  171.                  Do_CRC_byte
  172.                  Do_CRC_byte
  173.                  Do_CRC_byte
  174.                  Do_CRC_byte
  175.                  Do_CRC_byte
  176.                  Do_CRC_byte
  177.                  Do_CRC_byte
  178. #  endif  /* ?NO_32_BIT_LOADS */
  179.                 decl    %ecx
  180.                 jnz     .L_Next_Eight
  181. .L_No_Eights:
  182.                 movl    %edx, %ecx
  183. #endif /* NO_UNROLLED_LOOPS */
  184. #ifndef NO_JECXZ_SUPPORT
  185.                 jecxz   .L_bail              /* > if (len)                   */
  186. #else
  187.                 testl   %ecx, %ecx           /* > if (len)                   */
  188.                 jz      .L_bail
  189. #endif
  190. /* align loop head at start of 486 internal cache line !! */
  191.                 ALIGNMENT
  192. .L_loupe:                                    /* >   do {                     */
  193.                  Do_CRC_byte                 /*       c = CRC32(c, *buf++);  */
  194.                 decl    %ecx                 /* >   } while (--len);         */
  195.                 jnz     .L_loupe
  196. .L_bail:                                     /* > }                          */
  197.                 notl    %eax                 /* > return ~c;                 */
  198. .L_fine:
  199.                 popl    %ecx
  200.                 popl    %edx
  201.                 popl    %ebx
  202.                 popl    %esi
  203.                 popl    %edi
  204.                 _STD_LEAVE
  205.                 ret
  206. #else
  207.  error: this asm version is for 386 only
  208. #endif /* i386 || _i386 || _I386 || __i386 */
  209. #endif /* !USE_ZLIB */