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
144 lines
4.4 KiB
NASM
Executable File
144 lines
4.4 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 19 Jan 96.
|
|
;
|
|
; 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
|
|
.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 "text++"
|
|
; 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
|
|
lodsb ; al <-- *text++
|
|
xor al,bl ; (c ^ *text++) & 0xFF
|
|
shr ebx,8 ; c = (c >> 8)
|
|
xor ebx,[edi+eax*4] ; ^ table[(c ^ *text++) & 0xFF]
|
|
ENDM
|
|
|
|
_TEXT segment para
|
|
|
|
public _crc32
|
|
_crc32 proc near ; ulg crc32(ulg crc, uch *text, extent len)
|
|
STD_ENTRY
|
|
push edi
|
|
push esi
|
|
push ebx
|
|
push edx
|
|
push ecx
|
|
|
|
mov esi,Arg2 ; 2nd arg: uch *text
|
|
test esi,esi
|
|
jne short Crunch_it ;> if (!text)
|
|
sub eax,eax ;> return 0;
|
|
IFNDEF NO_STD_STACKFRAME
|
|
jmp short fine ;>
|
|
ELSE
|
|
jmp fine ;>
|
|
ENDIF
|
|
; align destination of commonly taken jump at longword boundary
|
|
align 4
|
|
Crunch_it: ;> 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 textlen
|
|
not ebx ;> c = ~crc;
|
|
cld ; incr. idx regs on string ops
|
|
|
|
IFNDEF NO_UNROLLED_LOOPS
|
|
mov edx,ecx ; save textlen in edx
|
|
shr ecx,3 ; ecx = textlen / 8
|
|
and edx,000000007H ; edx = textlen % 8
|
|
jecxz 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
|
|
loop Next_Eight
|
|
No_Eights:
|
|
mov ecx,edx
|
|
ENDIF ; NO_UNROLLED_LOOPS
|
|
jecxz bail ;> if (textlen)
|
|
; align loop head at start of 486 internal cache line !!
|
|
align 16
|
|
loupe: ;> do {
|
|
Do_CRC ; c = CRC32(c, *text++);
|
|
loop loupe ;> } while (--textlen);
|
|
|
|
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
|