which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@5403 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			157 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			NASM
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			NASM
		
	
	
		
			Executable File
		
	
	
	
	
; crc_i386.asm, optimized CRC calculation function for Zip and UnZip, not
 | 
						|
; copyrighted by Paul Kienitz and Christian Spieler.  Last revised 10 Nov 96.
 | 
						|
;
 | 
						|
; Revised 06-Oct-96, Scott Field (sfield@microsoft.com)
 | 
						|
;   fixed to assemble with masm by not using .model directive which makes
 | 
						|
;   assumptions about segment alignment.  Also,
 | 
						|
;   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather
 | 
						|
;   than lodsb, and other misc. changes resulting in the following performance
 | 
						|
;   increases:
 | 
						|
;
 | 
						|
;      unrolled loops                NO_UNROLLED_LOOPS
 | 
						|
;      *8    >8      <8              *8      >8      <8
 | 
						|
;
 | 
						|
;      +54%  +42%    +35%            +82%    +52%    +25%
 | 
						|
;
 | 
						|
;   first item in each table is input buffer length, even multiple of 8
 | 
						|
;   second item in each table is input buffer length, > 8
 | 
						|
;   third item in each table is input buffer length, < 8
 | 
						|
;
 | 
						|
;
 | 
						|
; FLAT memory model assumed.
 | 
						|
;
 | 
						|
; The loop unroolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
 | 
						|
; This results in shorter code at the expense of reduced performance.
 | 
						|
;
 | 
						|
;==============================================================================
 | 
						|
;
 | 
						|
; Do NOT assemble this source if external crc32 routine from zlib gets used.
 | 
						|
;
 | 
						|
    IFNDEF USE_ZLIB
 | 
						|
;
 | 
						|
        .386p
 | 
						|
        name    crc_i386
 | 
						|
; don't make assumptions about segment align        .model flat
 | 
						|
 | 
						|
extrn   _get_crc_table:near    ; ulg near *get_crc_table(void);
 | 
						|
 | 
						|
;
 | 
						|
    IFNDEF NO_STD_STACKFRAME
 | 
						|
        ; Use a `standard' stack frame setup on routine entry and exit.
 | 
						|
        ; Actually, this option is set as default, because it results
 | 
						|
        ; in smaller code !!
 | 
						|
STD_ENTRY       MACRO
 | 
						|
                push    ebp
 | 
						|
                mov     ebp,esp
 | 
						|
        ENDM
 | 
						|
 | 
						|
        Arg1    EQU     08H[ebp]
 | 
						|
        Arg2    EQU     0CH[ebp]
 | 
						|
        Arg3    EQU     10H[ebp]
 | 
						|
 | 
						|
STD_LEAVE       MACRO
 | 
						|
                pop     ebp
 | 
						|
        ENDM
 | 
						|
 | 
						|
    ELSE  ; NO_STD_STACKFRAME
 | 
						|
 | 
						|
STD_ENTRY       MACRO
 | 
						|
        ENDM
 | 
						|
 | 
						|
        Arg1    EQU     18H[esp]
 | 
						|
        Arg2    EQU     1CH[esp]
 | 
						|
        Arg3    EQU     20H[esp]
 | 
						|
 | 
						|
STD_LEAVE       MACRO
 | 
						|
        ENDM
 | 
						|
 | 
						|
    ENDIF ; ?NO_STD_STACKFRAME
 | 
						|
 | 
						|
; This is the loop body of the CRC32 cruncher.
 | 
						|
; registers modified:
 | 
						|
;   ebx  : crc value "c"
 | 
						|
;   esi  : pointer to next data byte "buf++"
 | 
						|
; registers read:
 | 
						|
;   edi  : pointer to base of crc_table array
 | 
						|
; scratch registers:
 | 
						|
;   eax  : requires upper three bytes of eax = 0, uses al
 | 
						|
Do_CRC  MACRO
 | 
						|
                mov     al, byte ptr [esi]   ; al <-- *buf
 | 
						|
                inc     esi                  ; buf++
 | 
						|
                xor     al,bl                ; (c ^ *buf++) & 0xFF
 | 
						|
                shr     ebx,8                ; c = (c >> 8)
 | 
						|
                xor     ebx,[edi+eax*4]      ;  ^ table[(c ^ *buf++) & 0xFF]
 | 
						|
        ENDM
 | 
						|
 | 
						|
_TEXT   segment para
 | 
						|
 | 
						|
        public  _crc32
 | 
						|
_crc32          proc    near  ; ulg crc32(ulg crc, ZCONST uch *buf, extent len)
 | 
						|
                STD_ENTRY
 | 
						|
                push    edi
 | 
						|
                push    esi
 | 
						|
                push    ebx
 | 
						|
                push    edx
 | 
						|
                push    ecx
 | 
						|
 | 
						|
                mov     esi,Arg2             ; 2nd arg: uch *buf
 | 
						|
                sub     eax,eax              ;> if (!buf)
 | 
						|
                test    esi,esi              ;>   return 0;
 | 
						|
                jz      fine                 ;> else {
 | 
						|
 | 
						|
                call    _get_crc_table
 | 
						|
                mov     edi,eax
 | 
						|
                mov     ebx,Arg1             ; 1st arg: ulg crc
 | 
						|
                sub     eax,eax              ; eax=0; make al usable as a dword
 | 
						|
                mov     ecx,Arg3             ; 3rd arg: extent len
 | 
						|
                not     ebx                  ;>   c = ~crc;
 | 
						|
 | 
						|
    IFNDEF  NO_UNROLLED_LOOPS
 | 
						|
                mov     edx,ecx              ; save len in edx
 | 
						|
                and     edx,000000007H       ; edx = len % 8
 | 
						|
                shr     ecx,3                ; ecx = len / 8
 | 
						|
                jz      No_Eights
 | 
						|
; align loop head at start of 486 internal cache line !!
 | 
						|
                align   16
 | 
						|
Next_Eight:
 | 
						|
                Do_CRC
 | 
						|
                Do_CRC
 | 
						|
                Do_CRC
 | 
						|
                Do_CRC
 | 
						|
                Do_CRC
 | 
						|
                Do_CRC
 | 
						|
                Do_CRC
 | 
						|
                Do_CRC
 | 
						|
                dec     ecx
 | 
						|
                jnz     Next_Eight
 | 
						|
No_Eights:
 | 
						|
                mov     ecx,edx
 | 
						|
 | 
						|
    ENDIF ; NO_UNROLLED_LOOPS
 | 
						|
                jecxz   bail                 ;>   if (len)
 | 
						|
; align loop head at start of 486 internal cache line !!
 | 
						|
                align   16
 | 
						|
loupe:                                       ;>     do {
 | 
						|
                Do_CRC                       ;        c = CRC32(c, *buf++);
 | 
						|
                dec     ecx                  ;>     } while (--len);
 | 
						|
                jnz     loupe
 | 
						|
 | 
						|
bail:                                        ;> }
 | 
						|
                mov     eax,ebx
 | 
						|
                not     eax                  ;> return ~c;
 | 
						|
fine:
 | 
						|
                pop     ecx
 | 
						|
                pop     edx
 | 
						|
                pop     ebx
 | 
						|
                pop     esi
 | 
						|
                pop     edi
 | 
						|
                STD_LEAVE
 | 
						|
                ret
 | 
						|
_crc32          endp
 | 
						|
 | 
						|
_TEXT   ends
 | 
						|
;
 | 
						|
    ENDIF ;!USE_ZLIB
 | 
						|
;
 | 
						|
end
 |