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